Skip to content

Instantly share code, notes, and snippets.

@amitu
Last active April 29, 2016 11:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save amitu/80f53eb5154a2c0cccf0fb2b00a66fea to your computer and use it in GitHub Desktop.
Save amitu/80f53eb5154a2c0cccf0fb2b00a66fea to your computer and use it in GitHub Desktop.
Django Model base class for encoded key. Useful for when you want to pass id in URL or JSON, but do not leak data to world (about how many objects you have of that kind).
from Crypto.Cipher import AES
from Crypto import Random
import base64
import binascii
import struct
from django.db import models
from django.conf import settings
class EncodedKeyManager(models.Manager):
def get_by_ekey(self, ekey):
return self.get(pk=decode(ekey))
def get_by_ekey_or_404(self, ekey):
from django.http import Http404
try:
return self.get_by_ekey(ekey)
except models.ObjectDoesNotExist:
raise Http404
class EncodedKeyModel(models.Model):
class Meta:
abstract = True
@property
def ekey(self):
return encode(self.pk)
def encode(m):
message = str(m)
length_bytes = struct.pack("i", len(message))
crc_bytes = struct.pack("i", binascii.crc32(message))
message = crc_bytes + length_bytes + message
if len(message) % 16:
message += " " * (16 - len(message) % 16)
cypher = AES.new(
settings.SECRET_KEY[:24], AES.MODE_CBC, settings.SECRET_KEY[-16:]
)
return base64.urlsafe_b64encode(cypher.encrypt(message)).replace("=", ".")
def decode(e):
e = base64.urlsafe_b64decode(str(e).replace(".", "="))
for skey in getattr(settings, "SECRET_KEYS", [settings.SECRET_KEY]):
cypher = AES.new(skey[:24], AES.MODE_CBC, skey[-16:])
msg = cypher.decrypt(e)
crc, length, msg = msg[:4], msg[4:8], msg[8:]
length_int = struct.unpack("i", length)[0]
crc = struct.unpack("i", crc)[0]
msg = msg[:length_int]
if crc != binascii.crc32(msg):
continue
return msg
raise ValueError("Failed to decrypt, CRC never matched.")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment