AES/GCM/NoPadding - Working Code

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>

wanna file a PR against the Lucee 7 branch with some example testcases for

https://luceeserver.atlassian.net/browse/LDEV-904

i.e. take this as a template and save it as LDEV904.CFC in a PR

I have just added reporting back the supported algorithms for rand() etc

https://luceeserver.atlassian.net/browse/LDEV-5771