Problem: code below seems to correctly AES 256-encrypt, but when decrypting the first 16 bytes are non-readable "bytes", or not decrypted, or other. The text after the first 16 bytes is correctly decrypted.
I've seen lots of postings on this problem where when you decrypt AES 256, the first 16 bytes are still, well, bytes not text. I've tried things suggested here like combining the IV bytes to the encrypted bytes before Base64Encodeing, but that didn't work. I also made sure that my two web methods (encrypt and decrypt) use the same IV bytes.
My standalone logic (a Java Application) works as expected. After many head-banging hours and searching and trying things I though I would ask some of the experts here.
I would appreciate any suggestions as to what could be wrong with the code below.
Two web services GET methods shown below, one for encrypt and the other for decrypt.
Thanks in advance,
get("/AESEncrypt/:stringToEncrypt/:Base64SecretKey", (request, response) ->
{
String myKey = request.params("secretKey");
byte[] ivBytes = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
// assume encoded since string could be any characters
String str2Encrypt = URLDecoder.decode(request.params("stringToEncrypt"), "UTF-8");
//Salt please.
String salt = "somesalt";
final byte[] saltBytes = salt.getBytes("UTF-8");
// Use SHA 256.
final SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
final PBEKeySpec spec = new PBEKeySpec(
myKey.toCharArray(),
saltBytes,
65536,
256);
final SecretKey secretKey = factory.generateSecret(spec);
final SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");
//encrypt the message
final Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secret);
final AlgorithmParameters params = cipher.getParameters();
final byte[] encryptedTextBytes = cipher.doFinal(str2Encrypt.getBytes("UTF-8"));
return Base64.encodeBase64String(encryptedTextBytes);
});
//-----------
get("/AESDecrypt/:stringToDecrypt/:decryptKey", (request, response) ->
{
String base64Key = request.params("decryptKey");
String strToDecrypt =request.params("stringToDecrypt");
String decryptedString = null;
//Salt please.
String salt = "somesalt";
final byte[] saltBytes = salt.getBytes("UTF-8");
// Derive the key
final SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
final PBEKeySpec spec = new PBEKeySpec(
base64Key.toCharArray(),
saltBytes,
65536,
256
);
final SecretKey secretKey = factory.generateSecret(spec);
final SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");
// Decrypt the message
final Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
final AlgorithmParameters params = cipher.getParameters();
// byte[] ivBytes = params.getParameterSpec(IvParameterSpec.class).getIV();
byte[] ivBytes = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(ivBytes));
byte[] decryptedTextBytes = null;
try
{
decryptedTextBytes = cipher.doFinal(Base64.decodeBase64(strToDecrypt));
}
catch (IllegalBlockSizeException e)
{
e.printStackTrace();
}
catch (BadPaddingException e)
{
e.printStackTrace();
}
return new String(decryptedTextBytes);
});