I created a gist based on this question: https://gist.github.com/735861
Following Amber's advice, the private keys are encrypted and decrypted using DES. The encrypted key is represented in base 36, but any other character-based representation will work as long as the representation is unique.
Any model that would need this kind of encrypted private key representation only needs to inherit from the model and manager shown in the code.
Here's the meat of the code:
import struct
from Crypto.Cipher import DES
from django.db import models
class EncryptedPKModelManager(models.Manager):
"""Allows models to be identified based on their encrypted_pk value."""
def get(self, *args, **kwargs):
encrypted_pk = kwargs.pop('encrypted_pk', None)
if encrypted_pk:
kwargs['pk'] = struct.unpack('<Q', self.model.encryption.decrypt(
struct.pack('<Q', encrypted_pk)
))[0]
return super(EncryptedPKModelManager, self).get(*args, **kwargs)
class EncryptedPKModel(models.Model):
"""Adds encrypted_pk property to children."""
encryption = DES.new('8charkey') # Change this 8 character secret key
def _encrypted_pk(self):
return struct.unpack('<Q', self.encryption_obj.encrypt(
str(struct.pack('<Q', self.pk))
))[0]
encrypted_pk = property(_encrypted_pk)
class Meta:
abstract = True
For a Transaction
object called transaction
, transaction.encrypted_pk
would return an encrypted representation of the private key. Transaction.objects.get(encrypted_pk=some_value)
would search for objects based on the encrypted private key representation.
It should be noted that this code assumes only works for private keys that can be represented properly as long values.