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