A field type that encrypts values using Fernet symmetric encryption.
EncryptedString
: A custom field type that transparently encrypts data before storing it in MongoDB and decrypts it when retrievedEncryptedInt
: A custom field type to encrypt Integer values.EncryptedFloat
: A custom field type to encrypt Floats values.EncryptedDecimal
: A custom field type to encrypt decimal.Decimal values.EncryptedJSON
: A custom field type to encrypt JSONs.- Simple integration with ODMantic models
- Compatible with FastAPI and starlette-admin
- Keys rotation is possible by providing multiple comma separated keys in the env variable.
pip install odmantic-fernet-field-type
This package requires a Fernet encryption key stored in the FERNET_KEY
environment variable. You can generate a suitable key by running:
python -m pip install odmantic-fernet-field-type
fernet-key
This will output a generated key along with instructions for setting up your environment.
# .env
...
FERNET_KEY="xxxxxxxyyyyyyyyzzzzzzzzzzz="
# .env
...
FERNET_KEY="pppppppqqqqqqqrrrrrrrrrr=,xxxxxxxyyyyyyyyzzzzzzzzzzz="
from decimal import Decimal
from odmantic import Model
# Note: The import package is "odmantic_fernet_field" and not "odmantic_fernet_field_type"
from odmantic_fernet_field import EncryptedString, EncryptedInt, EncryptedFloat, EncryptedJSON, EncryptedDecimal
class User(Model):
name: str
email: str
password_hash: str
# This field will be automatically encrypted in the database
secret_answer: EncryptedString
account_no: EncryptedInt
account_balance: EncryptedFloat
bank_details: EncryptedJSON
amount: EncryptedDecimal
...
# Create and save a user - the secret_answer, account_no, account_balance, bank_details & amount will be encrypted in MongoDB
user = User(
name="John", email="[email protected]", password_hash="...", secret_answer="April 1st, 2025", account_no=1234567890,
account_balance=1000000.00, amount=Decimal("100.00"), bank_details={
"accountHolder": "John Doe",
"accountNumber": 1234567890,
"type": "Checking",
"isActive": True
}
)
# When you retrieve the user, the secret_answer is automatically decrypted
retrieved_user = await engine.find_one(User, User.email == "[email protected]")
assert retrieved_user.secret_answer == "April 1st, 2025" # This will pass!
The package has been tested and works with FastAPI and starlette-admin:
from fastapi import FastAPI
from starlette_admin import Admin
from starlette_admin.contrib.odmantic import ModelView
from models import User
app = FastAPI()
admin = Admin(title="Admin Panel")
class UserAdmin(ModelView):
# Configure your admin view
pass
admin.add_view(UserAdmin(User))
admin.mount_to(app)
- Never hardcode encryption keys in your source code
- Use environment variables
- Rotate your encryption keys periodically
- Back up your encryption keys—if lost, encrypted data cannot be recovered
- Python 3.9+
- ODMantic 1.0.2+
- MongoDB 6.0+
- Tested with MongoDB 8.0.5
- odmantic 1.0.2+
- python-dotenv 1.0.1+
- cryptography 44.0.2+
This package was inspired by django-fernet-fields, which provides similar functionality for Django models.
MIT
Contributions are welcome! Please feel free to submit a Pull Request.