U UniCore Community Public content rendered for search, speed, and sharing

Advanced Usage

Cryptography

Encryption guidance, examples, and security notes.

Secure encryption and decryption utilities for sensitive data.

External Dependencies

The following external libraries are required to use cryptography features: | Library | Installation | Version | Requirements | | --- | --- | --- | --- | | cryptography | pip install cryptography | >=36.0.0 | Required for all cryptography functions |

pip install cryptography

Encryption

Symmetric encryption using Fernet (AES-based)

Implementation

Uses the cryptography.fernet module to provide secure, authenticated encryption

Security Notes

  • Fernet guarantees that a message encrypted using it cannot be manipulated or read without the key
  • Uses AES in CBC mode with a 128-bit key for encryption
  • PKCS7 padding with HMAC using SHA256 for authentication
  • Encrypted messages include a version, timestamp, IV, and HMAC

Best Practices

  • Never hardcode encryption keys in your source code
  • Store keys securely using environment variables or a dedicated secret management service
  • Rotate keys periodically to limit the damage from potential key exposure
  • Encrypt sensitive data before storing it in databases or transmitting over networks
  • Isolate encryption and decryption operations to minimize the spread of sensitive data

Generate a new encryption key

from unicorefw.crypto import generate_key

# Generate a secure key for encryption
key = generate_key()
print(f"Save this key securely: {key.decode('utf-8')}")

Expected output: Save this key securely: 5Gf7hJkL9pQr3sTuVwXyZ1A2B4C6D8E0F...

Encrypt sensitive data

from unicorefw.crypto import encrypt_string

# Using a previously generated key
key = b'YOUR_SECURE_KEY_HERE'

# Encrypt sensitive information
sensitive_data = "4111-1111-1111-1111"
encrypted = encrypt_string(sensitive_data, key)
print(f"Encrypted: {encrypted}")

Expected output: Encrypted: gAAAAABg6JKjZ2DvZ8_XYW5G1t8JhJk...

Decrypt data

from unicorefw.crypto import decrypt_string

# Using the same key used for encryption
key = b'YOUR_SECURE_KEY_HERE'

# Decrypt the encrypted token
try:
    decrypted = decrypt_string(encrypted, key)
    print(f"Decrypted: {decrypted}")
except ValueError as e:
    print(f"Error: {e}")

Expected output: Decrypted: 4111-1111-1111-1111

Secure storage of keys

import os
from unicorefw.crypto import generate_key, encrypt_string, decrypt_string

# Get key from environment variable or generate a new one
key = os.environ.get('ENCRYPTION_KEY')
if not key:
    new_key = generate_key()
    print(f"Add this to your environment: ENCRYPTION_KEY={new_key.decode('utf-8')}")
    key = new_key
else:
    key = key.encode('utf-8')

# Now use the key for encryption/decryption
sensitive_data = "example@email.com"
encrypted = encrypt_string(sensitive_data, key)

Expected output: Add this to your environment: ENCRYPTION_KEY=5Gf7hJkL9pQr3sTuVwXyZ1A2B4C6D8E0F...

Error Handling

Proper error handling for cryptography operations

Implementation

Provides specific exception handling for encryption/decryption failures

Example 1

from unicorefw.crypto import decrypt_string

try:
    # Attempt to decrypt with incorrect key
    wrong_key = generate_key()  # Different from the key used for encryption
    decrypted = decrypt_string(encrypted_data, wrong_key)
except ValueError as e:
    print(f"Decryption failed: {e}")
except RuntimeError as e:
    print(f"Cryptography library error: {e}")

Expected output: Decryption failed: Decryption failed: Invalid key or ciphertext.

Usage Patterns

Encrypting database fields

from unicorefw.crypto import encrypt_string, decrypt_string

# Function to save user with encrypted sensitive fields
def save_user(user_data, encryption_key):
    # Encrypt sensitive fields before storage
    encrypted_data = {
        'username': user_data['username'],  # Non-sensitive data stored as-is
        'email': encrypt_string(user_data['email'], encryption_key),
        'ssn': encrypt_string(user_data['ssn'], encryption_key)
    }
    # Now save encrypted_data to database
    return db.save('users', encrypted_data)

Notes: Only encrypt fields that contain sensitive information; avoid encrypting fields used for queries

Retrieving and decrypting data

from unicorefw.crypto import encrypt_string, decrypt_string

# Function to retrieve and decrypt user data
def get_user(user_id, encryption_key):
    # Retrieve encrypted data from database
    encrypted_data = db.get('users', user_id)

    # Decrypt sensitive fields
    decrypted_data = {
        'username': encrypted_data['username'],  # Non-encrypted field
        'email': decrypt_string(encrypted_data['email'], encryption_key),
        'ssn': decrypt_string(encrypted_data['ssn'], encryption_key)
    }
    return decrypted_data

Notes: Always handle decryption exceptions as they may indicate tampering or corruption