title: ColdFusion Decrypt AES128 PKCS7Padding CBC
body: <p>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.</p>
  
  <p>First the string needs to converted to binary:</p>
  
  <pre class="lang-coldfusion prettyprint-override"><code>&lt;cfset b64 = ToBinary(enc)/&gt;
  </code></pre>
  
  <p>Then we create a java byte buffer:</p>
  
  <pre class="lang-coldfusion prettyprint-override"><code>&lt;cfset objByteBuffer = CreateObject(
    "java",
    "java.nio.ByteBuffer") /&gt;
  </code></pre>
  
  <p>Then we initialize a buffer for the salt and a buffer for the data that needs to be decrypted.</p>
  
  <pre class="lang-coldfusion prettyprint-override"><code>&lt;cfset objBufferA = objByteBuffer.Allocate(
    JavaCast( "int", 16 )) /&gt;
  
  &lt;cfset objBufferB = objByteBuffer.Allocate(  
    JavaCast( "int", (Len(b64)-16) )) /&gt;
  </code></pre>
  
  <p>Then we fill the buffers with our bytes.</p>
  
  <pre class="lang-coldfusion prettyprint-override"><code>&lt;cfset objBufferA.Put(
    b64,
    JavaCast( "int", 0 ),
    JavaCast( "int", 16 )) /&gt;
  
  &lt;cfset objBufferB.Put(
    b64,
    JavaCast( "int", 16 ),
    JavaCast( "int", (Len(b64)-16) )) /&gt;
  
  &lt;cfset ivStringBin = objBufferA.Array()/&gt;
  &lt;cfset dataStringBin = objBufferB.Array()/&gt;
  </code></pre>
  
  <p>Because the decrypt function takes a hexadecimal string we need to encode it to hex.</p>
  
  <pre class="lang-coldfusion prettyprint-override"><code>&lt;!--- create byteArray output stream ---&gt;
  &lt;cfset baos = createObject("java", "java.io.ByteArrayOutputStream")&gt;
  &lt;!--- write the byteArray stored in the DB to the output stream ---&gt;
  &lt;cfset baos.write(ivStringBin)&gt;
  &lt;!--- convert binary content to text string ---&gt;
  &lt;cfset ivString=BinaryEncode(baos.toByteArray(),"hex")/&gt;
  
  &lt;!--- create byteArray output stream ---&gt;
  &lt;cfset baos2 = createObject("java", "java.io.ByteArrayOutputStream")&gt;
  &lt;!--- write the byteArray stored in the DB to the output stream ---&gt;
  &lt;cfset baos2.write(dataStringBin)&gt;
  &lt;!--- convert binary content to text string ---&gt;  
  
  &lt;cfset dataString=BinaryEncode(baos2.toByteArray(),"hex")/&gt;
  </code></pre>
  
  <p><strong>Should be:</strong></p>
  
  <pre class="lang-coldfusion prettyprint-override"><code>&lt;cfset dataString=BinaryEncode(baos2.toByteArray(),"base64")/&gt;
  </code></pre>
  
  <p>Now I'm not sure what to do with the key, but it appears to be required to be in a hexadecimal string format.</p>
  
  <pre class="lang-coldfusion prettyprint-override"><code>&lt;cfset key = BinaryEncode(ToBinary("{16 chars, [0-9a-zA-Z+/]}")/&gt;
  </code></pre>
  
  <p><strong>Should be:</strong></p>
  
  <pre class="lang-coldfusion prettyprint-override"><code>&lt;cfset key = "{32 chars, [0-9A-Z]}"/&gt;
  </code></pre>
  
  <p>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 </p>
  
  <pre class="lang-coldfusion prettyprint-override"><code>var zbPadding = CreateObject('java', 'org.bouncycastle.crypto.paddings.ZeroBytePadding').init();
  </code></pre>
  
  <p>to</p>
  
  <pre class="lang-coldfusion prettyprint-override"><code>var zbPadding = CreateObject('java', 'org.bouncycastle.crypto.paddings.PKCS7Padding').init();
  </code></pre>
  
  <p>according to the <a href="http://www.bouncycastle.org/docs/docs1.6/index.html" rel="nofollow">Bouncy Castle docs </a>.</p>
  
  <p>With all this I get the error: </p>
  
  <pre class="lang-coldfusion prettyprint-override"><code>"Key length not 128/160/192/224/256 bits."
  </code></pre>
  
  <p>I will be trying off and on but I am completely stuck, I can't figure out what I am doing wrong.</p>
  
  <p>Edit 1:</p>
  
  <p>I got it working! </p>
  
  <ul>
  <li>The dataString needed to be in <b>base64</b> instead of hex.</li>
  <li>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 <kbd>BinaryEncode(ToBinary())</kbd> function doesn't do its job. So I used a string to hex tool to convert it and then subsequently got 32 chars.</li>
  </ul>
  
  <p>Edit 2:
  Also, to install Bouncy Castle I followed the <a href="http://tales-of-coldfusion.blogspot.com/2007/07/strong-encryption-in-mx7.html" rel="nofollow">bouncy castle installe instructions</a> and downloaded jce from the bottom of the <a href="http://www.oracle.com/technetwork/java/javase/downloads/index.html" rel="nofollow">java downloads </a> page.</p>