Copy link to clipboard
Copied
Hiyas.
So I'm trying to get encrypt/decrypt to work for AES 256, with both 32byte key and 32byte IVorSalt. (Yup-new java security files v6 installed)
'IF' I 32byte key but dont use a IV at all, I get a nice looking AES 256 result. (I can tell it's AES 256 by looking the length of the encrypted string)
'IF' I use a 32byte key and 16bit salt, I get a AES 128 result (I know- as per docs theyre both s'posed to the same size, but the docs are wrong).
But when i switch to using both a 32byte key AND a 32byte salt I get the error below.
Has anyone 'EVER' gotten encrypt to work for them using AES 256 32byte key and 32byte salt? Is this a bug in CF? Or Java? Or I am doing something wrong?
<!--- ////////////////////////////////////////////////////////////////////////// Here's the Code ///////////////////////////////////////////////////////////////////////// --->
<cfset theAlgorithm = "Rijndael/CBC/PKCS5Padding" />
<cfset gKey = "hzj+1o52d9N04JRsj3vTu09Q8jcX+fNmeyQZSDlZA5w="><!--- these 2 are the same --->
<!---<cfset gKey = ToBase64(BinaryDecode("8738fed68e7677d374e0946c8f7bd3bb4f50f23717f9f3667b2419483959039c", "Hex"))>--->
<cfset theIV = BinaryDecode("7fe8585328e9ac7b7fe8585328e9ac7b7fe8585328e9ac7b7fe8585328e9ac7b","hex")>
<!---<cfset theIV128 = BinaryDecode("7fe8585328e9ac7b7fe8585328e9ac7b","hex")>--->
<cffunction name="DoEncrypt" access="public" returntype="string" hint="Fires when the application is first created.">
<cfargument name="szToEncrypt" type="string" required="true"/>
<cfset secretkey = gKey>
<cfset szReturn=encrypt(szToEncrypt, secretkey, theAlgorithm, "Base64", theIV)>
<cfreturn szReturn>
</cffunction>
<cffunction name="DoDecrypt" access="public" returntype="string" hint="Fires when the application is first created.">
<cfargument name="szToDecrypt" type="string" required="true"/>
<cfset secretkey = gKey>
<cfset szReturn=decrypt(szToDecrypt, secretkey, theAlgorithm, "Base64",theIV)>
<cfreturn szReturn>
</cffunction>
<cfset szStart = form["toencrypt"]>
<cfset szStart = "Test me!">
<cfset szEnc = DoEncrypt(szStart)>
<cfset szDec = DoDecrypt(szEnc)>
<cfoutput>#szEnc# #szDec#</cfoutput>
Whether or not you are doing something wrong depends on what you are trying to do.
When it comes to so-called AES 256 there are two options as to what this can mean.
1. In most of the programming world, AES 256 means AES crypto with a 128-bit block size and a 256-bit key. The CBC Initialization vector should be the same size as the block, not the same size as the key. So it should be 128-bit
2. In some parts of the programming world (primarily PHP) AES 256 is Rijndael crypto with a 256-bit block
...Copy link to clipboard
Copied
Whether or not you are doing something wrong depends on what you are trying to do.
When it comes to so-called AES 256 there are two options as to what this can mean.
1. In most of the programming world, AES 256 means AES crypto with a 128-bit block size and a 256-bit key. The CBC Initialization vector should be the same size as the block, not the same size as the key. So it should be 128-bit
2. In some parts of the programming world (primarily PHP) AES 256 is Rijndael crypto with a 256-bit block size. The problem here is that this is NOT AES. It uses the MCRYPT_RIJNDAEL_256 algorithm. Rijndael is the algorithm on which AES was built, but not everything that is Rijndael is AES.
So if what you want is AES 256-bit crypto, then using a 256-bit key with a 128-bit IV is the correct way to do it. AES *only* has 128-bit block sizes. So this is neither a bug in Java or CF.
If you actually need 256-bit block sizes, then I would guess you are probably trying to interoperate with a system that used PHP for crypto. If that is the case, I believe you will need to dig down into Java and do the crypto the hard way to support it. You may also need to add a new JCA/JCE Crypto provider if none of the standard providers included with CF have MCRYPT_RIJNDAEL_256.
Good luck,
Jason
Copy link to clipboard
Copied
Hi Robo ![]()
Thanks for explaination.
I was operating under the 'mis'conception that AES256 implied 32byte key AND salt.
.Net was more than happy to use 32byte values for both, so it was confusing when CF was choking even after I update the JS policy files.
And thank you itisdesign also!
Good work on the code mods! I had seen the lib you mentioned. Maybe for another project that would be the way to go ![]()
Copy link to clipboard
Copied
Hi edevmachine,
This Bouncy Castle Encryption CFC supports Rijndael w/ 256-bit block size. (big thanks to Jason here and all who helped w/ that, btw!)
Example:
<cfscript>
BouncyCastleCFC = new path.to.BouncyCastle();
string = "ColdFusion Rocks!";
key = binaryEncode(binaryDecode(generateSecretKey("Rijndael", 256), "base64"), "hex");//the CFC takes hex'd key
ivSalt = binaryEncode(binaryDecode(generateSecretKey("Rijndael", 256), "base64"), "hex");//the CFC takes hex'd ivSalt
encrypted = BouncyCastleCFC.doEncrypt(string, key, ivSalt);
writeOutput(BouncyCastleCFC.doDecrypt(encrypted, key, ivSalt));
</cfscript>
Related links for anyone interested in adding 256-bit block size Rijndael support into ColdFusion:
- An explanation of how to install the Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files in...
- An explanation of how to install the Bouncy Castle Crypto package into ColdFusion (near bottom, under the "Installing additional security providers" heading)
- An explanation of how to connect the Bouncy Castle classes together
- Bouncy Castle's doc for the Rijndael Engine
And here is the full CFC as posted in the StackOverflow discussion:
<cfcomponent displayname="Bounce Castle Encryption Component" hint="This provides bouncy castle encryption services" output="false">
<cffunction name="createRijndaelBlockCipher" access="private">
<cfargument name="key" type="string" required="true" >
<cfargument name="ivSalt" type="string" required="true" >
<cfargument name="bEncrypt" type="boolean" required="false" default="1">
<cfargument name="blocksize" type="numeric" required="false" default=256>
<cfscript>
// Create a block cipher for Rijndael
var cryptEngine = createObject("java", "org.bouncycastle.crypto.engines.RijndaelEngine").init(arguments.blocksize);
// Create a Block Cipher in CBC mode
var blockCipher = createObject("java", "org.bouncycastle.crypto.modes.CBCBlockCipher").init(cryptEngine);
// Create Padding - Zero Byte Padding is apparently PHP compatible.
var zbPadding = CreateObject('java', 'org.bouncycastle.crypto.paddings.ZeroBytePadding').init();
// Create a JCE Cipher from the Block Cipher
var cipher = createObject("java", "org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher").init(blockCipher,zbPadding);
// Create the key params for the cipher
var binkey = binarydecode(arguments.key,"hex");
var keyParams = createObject("java", "org.bouncycastle.crypto.params.KeyParameter").init(BinKey);
var binIVSalt = Binarydecode(ivSalt,"hex");
var ivParams = createObject("java", "org.bouncycastle.crypto.params.ParametersWithIV").init(keyParams, binIVSalt);
cipher.init(javaCast("boolean",arguments.bEncrypt),ivParams);
return cipher;
</cfscript>
</cffunction>
<cffunction name="doEncrypt" access="public" returntype="string">
<cfargument name="message" type="string" required="true">
<cfargument name="key" type="string" required="true">
<cfargument name="ivSalt" type="string" required="true">
<cfscript>
var cipher = createRijndaelBlockCipher(key=arguments.key,ivSalt=arguments.ivSalt);
var byteMessage = arguments.message.getBytes();
var outArray = getByteArray(cipher.getOutputSize(arrayLen(byteMessage)));
var bufferLength = cipher.processBytes(byteMessage, 0, arrayLen(byteMessage), outArray, 0);
var cipherText = cipher.doFinal(outArray,bufferLength);
return toBase64(outArray);
</cfscript>
</cffunction>
<cffunction name="doDecrypt" access="public" returntype="string">
<cfargument name="message" type="string" required="true">
<cfargument name="key" type="string" required="true">
<cfargument name="ivSalt" type="string" required="true">
<cfscript>
var cipher = createRijndaelBlockCipher(key=arguments.key,ivSalt=arguments.ivSalt,bEncrypt=false);
var byteMessage = toBinary(arguments.message);
var outArray = getByteArray(cipher.getOutputSize(arrayLen(byteMessage)));
var bufferLength = cipher.processBytes(byteMessage, 0, arrayLen(byteMessage), outArray, 0);
var originalText = cipher.doFinal(outArray,bufferLength);
return createObject("java", "java.lang.String").init(outArray);
</cfscript>
</cffunction>
<cfscript>
function getByteArray(someLength)
{
byteClass = createObject("java", "java.lang.Byte").TYPE;
return createObject("java","java.lang.reflect.Array").newInstance(byteClass, someLength);
}
</cfscript>
</cfcomponent>
Thanks!,
-Aaron
Get ready! An upgraded Adobe Community experience is coming in January.
Learn more