几年前我不得不使用 BouncyCastle 做到这一点。正如 Alen Puzic 的回答中所述,这两个问题是 mysql 密钥生成和 PKCS7 填充。BouncyCastle 将使用他们为您处理填充,PaddedBufferedBlockCipher
但您需要自己生成密钥。这是执行此操作的代码:
/**
* 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);
}
请注意,keyLength
mysql 的默认值为 128。
使用上述方法生成,KeyParameter
您可以通过以下方式完成加密/解密。
/**
* 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;
}