So I wanted to switch away from ‘AES/CBC/PKCS5Padding’ to the more secure ‘AES/GCM/NoPadding’ however Lucee throws an exception. I figured I’d share my code and maybe someone can update the core encrypt/decrypt functions in Lucee to support it.
<cfscript>
function JavaGCMParameterSpec (required string iv) {
var ivbytes = BinaryDecode(iV, "base64");
return (createObject("java", "javax.crypto.spec.GCMParameterSpec").init(ArrayLen(ivbytes) * 8, ivbytes));
}
function JavaSecretKeySpec (required string theKey, required string ec) {
return (createObject("java", "javax.crypto.spec.SecretKeySpec").init(BinaryDecode(theKey, "base64"), "AES"));
}
function AESEncrypt(required string es, required string ec, required string theKey, required string iv) {
var cipher = createObject("java", "javax.crypto.Cipher").getInstance(ec);
cipher.init(cipher.ENCRYPT_MODE, JavaSecretKeySpec(theKey,ec), JavaGCMParameterSpec(iv));
return (binaryEncode(cipher.doFinal(ToString(es).getBytes("UTF-8")), "base64" ));
}
function AESDecrypt(required string es, required string ec, required string theKey, required string iv) {
var cipher = createObject("java", "javax.crypto.Cipher").getInstance(ec);
cipher.init(cipher.DECRYPT_MODE, JavaSecretKeySpec(theKey,ec), JavaGCMParameterSpec(iv));
return (ToString(cipher.doFinal(BinaryDecode(es, "base64")), "UTF-8"));
}
function AESGenerateKey(required string algorithm, required number keyLength) {
var keyGenerator = createObject("java", "javax.crypto.KeyGenerator").getInstance(algorithm);
keyGenerator.init(keyLength, createObject("java", "java.security.SecureRandom"));
return(binaryEncode(keyGenerator.generateKey().getEncoded(),"base64"));
}
function AESGenerateIV(required number ivLength) {
var emptyarr = [];
for ( i = 1 ; i <= ivLength ; i++ ) {
arrayAppend( emptyarr, 0 );
}
var ivBytes = javaCast( "byte[]", emptyarr );
var secureRandom = createObject("java", "java.security.SecureRandom").getInstanceStrong();
secureRandom.nextBytes(ivBytes);
return(binaryEncode(ivBytes, "base64"));
}
algorithm = "AES";
ec = "AES/GCM/NoPadding";
keyLength = 256;
ivLength = 12;
TestString = "This is my test string";
newKey = AESGenerateKey(algorithm, keyLength);
WriteOutput("AES Key: " & newKey & "<br>");
newIV = AESGenerateIV(ivLength);
WriteOutput("IV: " & newIV & "<br>");
encrypteddata = AESEncrypt(TestString, ec, newKey, newIV);
WriteOutput("Encrypted Base64:: " & encrypteddata & "<br>");
decrypteddata = AESDecrypt(encrypteddata, ec, newKey, newIV);
WriteOutput("Decrypted String:: " & decrypteddata & "<br>");
</cfscript>