title: Using mysql AES encrypt and decrypt from Django
body: <p>In my Django app, I want to use <code>AES_ENCRYPT</code> and <code>AES_DECRYPT</code> from the mysql database to encrypt and decrypt stuff.<br>
  I know that python's Crypto package has AES support but the Crypto AES doesn't produce the same result as mysql AES although I made sure that both are using the ECB mode.<br>
  So, now I'm doing this:  </p>
  
  <pre><code>sql = "select 1 as id, AES_ENCRYPT(my_field, '16-bytes encryption key') as field_enc from appname_table"
  encrypted_fields = MyModel.objects.raw(sql)
  </code></pre>
  
  <p>This gets me the field values after encryption and it works fine. The issue is that the AES algorithm encryption final result has many unprintable characters, it looks like this:  </p>
  
  <pre><code>encrypted_fields[3].field_enc
  '\x88\xc5\xe4\xa0c?\xf8\x16|^1JB\x83{\xdf'
  print(encrypted_fields[3].field_enc)
  ���c?�|^1JB�{�
  </code></pre>
  
  <p>So, now when I try to take this same value to decrypt it, the mysql replies with an error that says </p>
  
  <blockquote>
    <p>"OperationalError: (1300, "Invalid utf8 character string:
    '\x88\xC5\xE4\xA0c'")"</p>
  </blockquote>
  
  <p>I guess this is because I tried to send unprintable characters to the mysql query.  </p>
  
  <p>So, how do I approach this?<br>
  Please note that I have to use the MySQL functions because I encrypted some database fields using these functions so I need to decrypt them with the same function because Crypto's AES doesn't get the same results. Crypto keeps asking that the text to be encrypted has to be 16 bytes long like the key, while mysql doesn't require that.  </p>
  
  <p>I also tried to see if mysql use some kind of padding for the text before encryption but it doesn't say what characters they pad on their <a href="https://dev.mysql.com/doc/refman/8.0/en/encryption-functions.html#function_aes-encrypt" rel="nofollow noreferrer">webpage</a>:  </p>
  
  <blockquote>
    <p>The str and crypt_str arguments can be any length, and padding is
    automatically added to str so it is a multiple of a block as required
    by block-based algorithms such as AES. This padding is automatically
    removed by the AES_DECRYPT() function</p>
  </blockquote>