3
votes

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.

1
You should post that as an answer and accept it. Maybe include an (abbreviated) code snippet to help others.Leigh

1 Answers

1
votes

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.