Reputation: 43
We use BouncyCastle PBEWITHSHA256AND256BITAES-CBC-BC to encrypt data with our java application and store the encrypted result in a MySql Database.
Example Code:
StandardPBEStringEncryptor configurationEncryptor = new StandardPBEStringEncryptor();
configurationEncryptor.setAlgorithm("PBEWITHSHA256AND256BITAES-CBC-BC");
configurationEncryptor.setProviderName("BC");
configurationEncryptor.setSaltGenerator(new RandomSaltGenerator());
configurationEncryptor.setKeyObtentionIterations(1000);
configurationEncryptor.setPassword("aTestPassword");
String input = "A Test String!";
String cypherText = configurationEncryptor.encrypt(input);
String plainText = configurationEncryptor.decrypt(cypherText);
System.out.println("Input:" + input + " cypher:" + cypherText + " plain:" + plainText);
Output:
Input:A Test String! cypher:DhCSPbCWcZ76TUD/dDeGczlHbI9dQJyB2lKAiL7dDEk= plain:A Test String!
The cypher string above is a base64 encoded string which we store in our database.
I would now like to attempt to decrypt the cypher string stored in our database using the AES utilities provided by MySql.
I am trying to understand how the BC provider concatenates the encrypted data so that I can split it up and recreate the required parameters to enable me to decrypt the data with other tools - in this case MySql's AES_DECRYPT function.
Inspecting the code I can see that the first 16bytes of the cypher text (when base 64 decoded) is the salt, I am unsure where the init vector (IV) is stored in the remainder of the cypher text data.
If we can parse out the IV, salt and encrypted value from the string, then it should be possible to use external tools to decrypt the data.
A sample Mysql AES usage is as follows:
SET block_encryption_mode = 'aes-256-cbc';
SET @key_str = SHA2('aTestPassword',256);
SET @init_vector = RANDOM_BYTES(16);
SET @crypt_str = AES_ENCRYPT('A Test String!',@key_str,@init_vector);
SELECT AES_DECRYPT(@crypt_str,@key_str,@init_vector);
Output:
A Test String!
I would like to know how to parse the BouncyCastle cypher text to obtain its component parts, and also how to use the salt to generate the correct key hash with the number of iterations specified for use by Mysql to decrypt the data.
Any help much appreciated!
Upvotes: 0
Views: 1277
Reputation: 6414
This answer is not a solution in code but will help you in finding the code.
First: you are NOT using Bouncy Castle to en-/decrypt directly - of course the cipher is used as provider for the en-/decryption.
The library that does the complete en-/decryption is JASYPT and here we can find answers for your question.
Base for my research is the GitHub https://github.com/jboss-fuse/jasypt/tree/master/jasypt/src/main/java/org/jasypt/encryption/pbe and I'm starting with "StandardPBEStringEncryptor.java":
As we are trying to understand the encryption in use I found
// The StandardPBEByteEncryptor that will be internally used.
private final StandardPBEByteEncryptor byteEncryptor;
and later the encrypt-method:
...
// The StandardPBEByteEncryptor does its job.
byte[] encryptedMessage = this.byteEncryptor.encrypt(messageBytes);
...
if (this.stringOutputTypeBase64) {
encryptedMessage = this.base64.encode(encryptedMessage);
result = new String(encryptedMessage,ENCRYPTED_MESSAGE_CHARSET);
} else {
result = CommonUtils.toHexadecimal(encryptedMessage);
}
As you get a Base64-encoded string this class just returns the encryptedMessage in Base64-encding.
Let's see the base class "StandardPBEByteEncryptor.java":
Searching for ivInUse:
// Initialization Vector to be used for encryption and decryption.
private byte[] ivInUse = null;
...
// Initialize Initialization Vector
this.ivInUse = new byte[algorithmBlockSize];
That means we do have a static IV of 16 bytes length (blocklength for AES) filled with "x00".
salt:
The DefaultSaltLength is set to 8 but when using a block cipher the salt length equals to the cipher block size (for AES 16):
// The salt size for the chosen algorithm is set to be equal
// to the algorithm's block size (if it is a block algorithm).
final int algorithmBlockSize = this.encryptCipher.getBlockSize();
if (algorithmBlockSize > 0) {
this.saltSizeBytes = algorithmBlockSize;
}
The salt is generated with the saltGenerator and after encryption it is concatenated with the ciphertext in the form salt|encryptedMessage
:
encrypt:
...
// Finally we build an array containing both the unencrypted salt
// and the result of the encryption. This is done only
// if the salt generator we are using specifies to do so.
if (this.saltGenerator.includePlainSaltInEncryptionResults()) {
// Insert unhashed salt before the encryption result
return CommonUtils.appendArrays(salt, encryptedMessage);
}
The number of iterations is given by initialization (1000).
Last part to solve is the algorithm for the cipher-init and when using OpenJava 11 I find:
PBEWithHmacSHA256AndAES_256
that (hopefully) works in CBC-mode.
Upvotes: 1