Search code examples
pythondjangounicodepycrypto

Django PyCrypto - Save Encrypted String to Database Bad Unicode Data


I'm working with PyCrypto in Django and I need to encrypt a string using the user's secret key they made themselves. I successfully wrote an encryption method as follows:

from Crypto.Cipher import AES
from Crypto.Random import get_random_string

def encrypt(value, key):
    """
    Return an encryption of value under key, as well as IV.
    Pads value with extra bytes to make it multiple of 16.
    """
    extra = 16 - (len(value) % 16)
    data = value + chr(extra) * extra
    iv = get_random_bytes(16)
    encryption_suite = AES.new(key, AES.MODE_CBC, iv)
    cipher_text = encryption_suite.encrypt(data)
    return cipher_text, iv

Why am I not using Django's encryptions? Because there is a client application that is NOT written in Django (and won't ever be) that accepts the encrypted value the user stored previously and decrypts it once the user enters their secret key.

Problem is that I can't seem to save the encrypted value to the database for the User model. For example:

user = User.objects.get(id=user_id)
cipher, iv = encrypt(user_value, user_key)
user.secret_value = cipher
user.iv = iv
user.save()

This results in this error:

Warning: Incorrect string value: '\xE7\xAA\x13\x036\xC8...' for column 'iv' at row 1

(same error for secret_value)

I know this must be something to do with improper encoding. What's the right way to go about fixing this? Should I convert each byte into a string character?

Thanks.


Solution

  • I guess you're trying to save binary data into CharFields. Either change field types of user.iv and user.secret_value to BinaryField, or encode these values using for example base64 encoder.