title: How to make Ruby AES-256-CBC and PHP MCRYPT_RIJNDAEL_128 play well together
body: <p>I'm generating data to send from a Ruby stack to a PHP stack.  I'm using the OpenSSL::Cipher library on the Ruby side and the 'mcrypt' library in PHP.  When I encrypt using 'aes-256-cbc' (256-bit block size) in Ruby I need to use MCRYPT_RIJNDAEL_128 (128-bit block size) in PHP to decrypt it.  I suspect the Ruby code that is broken, because the cipher.iv_len is 16; I believe it should be 32:</p>
  
  <pre><code>&gt;&gt; cipher = OpenSSL::Cipher::Cipher.new('aes-128-cbc')
  =&gt; #&lt;OpenSSL::Cipher::Cipher:0x3067c5c&gt;
  &gt;&gt; cipher.key_len
  =&gt; 16
  &gt;&gt; cipher.iv_len
  =&gt; 16
  &gt;&gt; cipher = OpenSSL::Cipher::Cipher.new('aes-256-cbc')
  =&gt; #&lt;OpenSSL::Cipher::Cipher:0x306de18&gt;
  &gt;&gt; cipher.key_len
  =&gt; 32
  &gt;&gt; cipher.iv_len
  =&gt; 16
  </code></pre>
  
  <p>So here's my test.  On the Ruby side, first I generate the key and iv:</p>
  
  <pre><code>&gt;&gt; cipher = OpenSSL::Cipher::Cipher.new('aes-256-cbc')
  &gt;&gt; cipher.encrypt
  &gt;&gt; iv = cipher.random_iv
  &gt;&gt; iv64 = [iv].pack("m").strip
  =&gt; "vCkaypm5tPmtP3TF7aWrug=="
  &gt;&gt; key = cipher.random_key
  &gt;&gt; key64 = [key].pack("m").strip
  =&gt; "RIvFgoi9xZaHS/0Bp0J9WDRyND6Z7jrd3btiAfcQ8Y0="
  </code></pre>
  
  <p>Then I use those keys to do the encryption:</p>
  
  <pre><code>&gt;&gt; plain_data = "Hi, Don, this is a string."
  &gt;&gt; cipher = OpenSSL::Cipher::Cipher.new('aes-256-cbc')
  &gt;&gt; cipher.encrypt
  &gt;&gt; cipher.key = Base64.decode64(key64)
  &gt;&gt; cipher.iv = Base64.decode64(iv64)
  &gt;&gt; encrypted_data = cipher.update(plain_data)
  &gt;&gt; encrypted_data &lt;&lt; cipher.final
  &gt;&gt; crypt64 = [encrypted_data].pack("m").strip
  =&gt; "5gfC/kJcnAV2fJI0haxnLcdraIKWgtu54UoznVxf8K0="
  </code></pre>
  
  <p>Here's the PHP decryption:</p>
  
  <pre><code>$ruby_crypt = "5gfC/kJcnAV2fJI0haxnLcdraIKWgtu54UoznVxf8K0=";
  $encrypted_data = base64_decode($ruby_crypt);
  $key = base64_decode("RIvFgoi9xZaHS/0Bp0J9WDRyND6Z7jrd3btiAfcQ8Y0=");
  $iv = base64_decode("vCkaypm5tPmtP3TF7aWrug==");
  $result = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $encrypted_data, MCRYPT_MODE_CBC, $iv);
  $unencrypt = rtrim($result, "\x00..\x1F");
  print "\nUnencrypted token:\n'$unencrypt'\n";
  
  RESULT:
  Unencrypted token:
  'Hi, Don, this is a string.'
  </code></pre>
  
  <p>I'd prefer to use the longer block size.  Clearly I'm misunderstanding the APIs.  Help?</p>