Snippet List
Inspired by [Base64Field: base64 encoding field for storing binary data in Django TextFields](https://djangosnippets.org/snippets/1669/) but in a generic way.
from django.db import models
import base64
class Base64Encryptor(object):
def encrypt(self, value):
return base64.encodestring(value)
def decrypt(self, msg):
return base64.decodestring(msg)
class MyModel(models.Model):
...
b64_data = EncryptedField(encryptor=Base64Encryptor)
...
# Usage
my_obj = MyModel()
my_obj.b64_data = "hello"
print(my_obj.b64_data) # will output 'hello'
print(my_obj.b64_data_enc) # will output 'aGVsbG8=\n'
Sometimes you need to store information that the server needs in unencrypted form (e.g. OAuth keys and secrets), but you don't really want to leave it lying around in the open on your server. This snippet lets you split that information into two parts:
* a securing passphrase, stored in the Django settings file (or at least made available via that namespace)
* the actual secret information, stored in the ORM database
Obviously, this isn't as secure as using a full blown key management system, but it's still a significant step up from storing the OAuth keys directly in the settings file or the database.
Note also that these fields will be displayed unencrypted in the admin view unless you add something like the following to ``admin.py``:
from django.contrib import admin
from django import forms
from myapp.fields import EncryptedCharField
class MyAppAdmin(admin.ModelAdmin):
formfield_overrides = {
EncryptedCharField: {'widget': forms.PasswordInput(render_value=False)},
}
admin.site.register(PulpServer, PulpServerAdmin)
If Django ever acquires a proper binary data type in the default ORM then the base64 encoding part could be skipped.
This snippet is designed to be compatible with the use of the South database migration tool *without* exposing the passphrase used to encrypt the fields in the migration scripts. (A migration tool like South also allows you to handle the process of *changing* the passphrase, by writing a data migration script that decrypts the data with the old passphrase then writes it back using the new one).
Any tips on getting rid of the current ugly prefix hack that handles the difference between deserialising unencrypted strings and decrypting the values stored in the database would be appreciated!
Sources of inspiration:
[AES encryption with M2Crypto](http://passingcuriosity.com/2009/aes-encryption-in-python-with-m2crypto/)
[EncryptedField snippet](http://djangosnippets.org/snippets/1095/) (helped me improve several Django-specific details)
Requires the M2Crypto module. See [http://sandbox.rulemaker.net/ngps/m2/howto.smime.html](http://sandbox.rulemaker.net/ngps/m2/howto.smime.html) for more information on using M2Crypto to create S/MIME email. This could also be adapted to allow signing, or sign+encrypt, but currently only encrypts.
Use just like `EmailMessage`, except takes an extra parameter `cert`, which is the path to the recipient's public X.509 certificate.
- email
- emailmessage
- encryption
Here's a simple way to transparently encrypt a field (just repeat the idiom for more than one) so that it is not stored plaintext in the database. This might be useful for social security numbers, etc.
The storage size for the ciphertext depends on which algorithm you use. Blowfish here requires 32 characters to store an encrypted 16 characters. Note also that Blowfish requires a block size of a multiple of 8, so that is what the repeat in the _set_ssn() is all about.
The Crypto module is from http://www.amk.ca/python/code/crypto.html
I make no claims as to how secure this scheme is overall, comments on this are welcome.
5 snippets posted so far.