I need to decrypt a base64 encoded binary in string format [0-9a-zA-Z+/]. Part of this string consists of the ivSalt, which is the first 16 Bytes, or 128bits. The rest is data; everything was encrypted using AES with 128 key and in 128 CBC blocks and PKCS7Padding.
First the string needs to converted to binary:
<cfset b64 = ToBinary(enc)/>
Then we create a java byte buffer:
<cfset objByteBuffer = CreateObject(
"java",
"java.nio.ByteBuffer") />
Then we initialize a buffer for the salt and a buffer for the data that needs to be decrypted.
<cfset objBufferA = objByteBuffer.Allocate(
JavaCast( "int", 16 )) />
<cfset objBufferB = objByteBuffer.Allocate(
JavaCast( "int", (Len(b64)-16) )) />
Then we fill the buffers with our bytes.
<cfset objBufferA.Put(
b64,
JavaCast( "int", 0 ),
JavaCast( "int", 16 )) />
<cfset objBufferB.Put(
b64,
JavaCast( "int", 16 ),
JavaCast( "int", (Len(b64)-16) )) />
<cfset ivStringBin = objBufferA.Array()/>
<cfset dataStringBin = objBufferB.Array()/>
Because the decrypt function takes a hexadecimal string we need to encode it to hex.
<!--- create byteArray output stream --->
<cfset baos = createObject("java", "java.io.ByteArrayOutputStream")>
<!--- write the byteArray stored in the DB to the output stream --->
<cfset baos.write(ivStringBin)>
<!--- convert binary content to text string --->
<cfset ivString=BinaryEncode(baos.toByteArray(),"hex")/>
<!--- create byteArray output stream --->
<cfset baos2 = createObject("java", "java.io.ByteArrayOutputStream")>
<!--- write the byteArray stored in the DB to the output stream --->
<cfset baos2.write(dataStringBin)>
<!--- convert binary content to text string --->
<cfset dataString=BinaryEncode(baos2.toByteArray(),"hex")/>
Should be:
<cfset dataString=BinaryEncode(baos2.toByteArray(),"base64")/>
Now I'm not sure what to do with the key, but it appears to be required to be in a hexadecimal string format.
<cfset key = BinaryEncode(ToBinary("{16 chars, [0-9a-zA-Z+/]}")/>
Should be:
<cfset key = "{32 chars, [0-9A-Z]}"/>
ColdFusion doesn't itself support PKCS7Padding with CBC, I get an unsupported provider error. So I go and install BouncyCastle and I found a wonderful ColdFusion example of how to decrypt with PKCS5Padding Un-encrypting / re-encrypting a ColdFusion encrypted string in PHP">here. I added it to my code but I need PKCS7Padding so I changed
var zbPadding = CreateObject('java', 'org.bouncycastle.crypto.paddings.ZeroBytePadding').init();
to
var zbPadding = CreateObject('java', 'org.bouncycastle.crypto.paddings.PKCS7Padding').init();
according to the Bouncy Castle docs .
With all this I get the error:
"Key length not 128/160/192/224/256 bits."
I will be trying off and on but I am completely stuck, I can't figure out what I am doing wrong.
Edit 1:
I got it working!
- The dataString needed to be in base64 instead of hex.
- The key, when converted to hex using coldFusion is 24 [0-9A-F] chars representing 24x4=96 bits which is 12 Bytes. It needs to be 16 Bytes, so somehow the BinaryEncode(ToBinary()) function doesn't do its job. So I used a string to hex tool to convert it and then subsequently got 32 chars.
Edit 2: Also, to install Bouncy Castle I followed the bouncy castle installe instructions and downloaded jce from the bottom of the java downloads page.