georgemarshall / django-cryptography

Easily encrypt data in Django
https://django-cryptography.readthedocs.io/
BSD 3-Clause "New" or "Revised" License
371 stars 70 forks source link

Using unique=True on MySQL fails due to missing "key length" #43

Open flyte opened 4 years ago

flyte commented 4 years ago

When creating (in a migration) an encrypted field that has unique=True, the MySQL backend gives the following error:

MySQLdb._exceptions.OperationalError: (1170, "BLOB/TEXT column 'email_new' used in key specification without a key length")

This SO post explains the reason behind the error: https://stackoverflow.com/a/1827099/1791183

1, Is this something that django-cryptography can fix?

  1. Will unique=True even work on an encrypted field?
  2. Is there a workaround?
thismatters commented 3 years ago

To question 2 I say no; it might work on some databases, but generally no.

To question3, yes. The workaround is a little ugly, but it works. Decrypt each row and compare it to new candidate row and see if there is a collision:

for row in EncryptedModel.objects.all():
  if row.unique_attribute == new_unique_attribute:
    raise Exception("bruh... are you fr advocating for a full record search?? yes, but only because there is no alternative")