AES encryption method equivalent to MySQL aes_encrypt () function

I want to write an AES encryption method that should be equivalent to mysql aes_encrypt .

I am trying to write, but this is not correct because mysql does not provide the correct data.

What should I do to understand this?

 Cipher cipher = Cipher.getInstance("AES"); cipher.init(Cipher.ENCRYPT_MODE, keySpec); byte[] encryptedTextBytes = cipher.doFinal(message .getBytes("UTF-8")); String k = new String(encryptedTextBytes); System.out.println("KKKKK"+k); 
+1
source share
4 answers

MySQL AES implementation gives headaches to many people. This is mainly due to the way MySQL handles the encryption key. The encryption key is split into 16-byte blocks, and MySQL will be XOR bytes from one block with the bytes in the previous block. If the user key is less than 16 bytes long, then the key is essentially padded with zero bytes to get up to 16 bytes. The way the key is processed by MySQL aes_encrypt ().

The value to be encrypted is also processed by populating the data with PKCS7. You can learn all about PKCS7 @ http://en.wikipedia.org/wiki/Padding_%28cryptography%29#PKCS7 , but all it does is input pads so they are in 16-byte blocks. A byte filled with data is equivalent to the number of padding bytes added.

In short, you need to process the encryption key as MySQL does, and fill in your input with PKCS7.

Refer to the following post by Michael Simmons, for example, code in Java: http://info.michael-simons.eu/2011/07/18/mysql-compatible-aes-encryption-decryption-in-java/

+6
source

I had to do this a few years ago using a BouncyCastle. As Allen Puzich’s answer says, two problems are mysql key generation and PKCS7 add-on. BouncyCastle will handle the add-on for you using the PaddedBufferedBlockCipher , but you will need to generate the key yourself. Here is the code for this:

 /** * Use password to generate a MySQL AES symmetric key * @param passwd Password String to use. * @param keyLength Must be evenly divisible by 8. * @return Key for use with MySQL AES encrypt/decrypt fuctions. */ public static KeyParameter getMySqlAESPasswdKey(String passwd, int keyLength) { byte[] pword = passwd.getBytes(); byte[] rawKey = new byte[keyLength/8]; int j = 0; for (int i = 0; i < pword.length; i++, j++) { if(j==rawKey.length) { j = 0; } rawKey[j] = pword[i]; } return new KeyParameter(rawKey); } 

Note that the default keyLength for mysql is 128.

Using the above method to create a KeyParameter , you can complete encryption / decryption as follows.

 /** * Password based encryption using AES with MySql style key generation. * @param toEncrypt Unencrypted byte array. * @param key A KeyParameter generated with the getMySqlAESPasswdKey() method. * @return Encrypted byte array. * @throws InvalidCipherTextException If provided key cannot be used with this method on the provided data. */ public static byte[] mysqlAesPasswdEncrypt (byte [] toEncrypt, KeyParameter key) throws InvalidCipherTextException { BufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new AESFastEngine()); cipher.init(true, key); byte[] result = new byte[cipher.getOutputSize(toEncrypt.length)]; int len = cipher.processBytes(toEncrypt, 0, toEncrypt.length, result, 0); cipher.doFinal(result, len); return result; } /** * Password based decryption using AES with MySql style key generation. * @param toDecrypt Encrypted byte array. * @param key A KeyParameter generated with the getMySqlAESPasswdKey() method. * @return Unencrypted byte array. * @throws InvalidCipherTextException If provided key cannot be used with this method on the provided data. */ public static byte[] mysqlAesPasswdDecrypt (byte [] toDecrypt, KeyParameter key) throws InvalidCipherTextException { BufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new AESFastEngine()); cipher.init(false, key); byte[] result = new byte[cipher.getOutputSize(toDecrypt.length)]; int len = cipher.processBytes(toDecrypt, 0, toDecrypt.length, result, 0); cipher.doFinal(result, len); return stripTrailingZeros(result); } /** * Strip trailling zeros from the end of decrypted byte arrays. * @param data Data to strip. * @return Stripped data. */ public static byte[] stripTrailingZeros(byte[] data) { int lastData = data.length-1; for (int i = data.length-1; i >= 0; i--) { if(data[i]!=(byte)0) { lastData = i; break; } } byte[] data2 = new byte[lastData+1]; System.arraycopy(data, 0, data2, 0, lastData+1); return data2; } 
+1
source

Thanks for understanding, it finally worked out correctly, here is a simple version of python:

 from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import padding import codecs def encrypt(data, key): key = key + b"\0" * (16 - len(key) % 16) padder = padding.PKCS7(128).padder() data = padder.update(data) + padder.finalize() alg = algorithms.AES(key) cipher = Cipher(alg, modes.ECB(), default_backend()) encryptor = cipher.encryptor() ct = encryptor.update(data) + encryptor.finalize() return ct if __name__ == '__main__': enc = encrypt(b'123456', b'1234567890') print(codecs.encode(enc, 'hex')) 
0
source

I would recommend using the Bouncy Castle Java cryptographic APIs. BC is widely regarded as a great crypto toolkit, and if you want, it can connect to the Java API as a cryptography provider. I know that does not directly answer your question, but I have never seen anyone have problems with Bouncy Castle.

-1
source

Source: https://habr.com/ru/post/1211282/


All Articles