title: Why does something encrypted in PHP not match the same string encrypted in Ruby?
body: <p>Here are my requirements:</p>
  
  <p>I need to encrypt a string in PHP using AES encryption (including a random iv), Base64 encode it, then URL-encode it so that it can be passed as a URL parameter.</p>
  
  <p>I am trying to get the same result in both PHP and Ruby, but I can't make it work.</p>
  
  <p>Here is my PHP code:</p>
  
  <pre><code>function encryptData($data,$iv){
      $cipher = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');
      $iv_size = mcrypt_enc_get_iv_size($cipher);
      if (mcrypt_generic_init($cipher, 'g6zys8dlvvut6b1omxc5w15gnfad3jhb', $iv) != -1){
          $cipherText = mcrypt_generic($cipher,$data );
          mcrypt_generic_deinit($cipher);
          return $cipherText;
      }
      else {
          return false;
      }
  }
  $data = 'Mary had a little lamb';
  $iv = '96b88a5f0b9efb43';
  $crypted_base64 = base64_encode(encryptData($data, $iv));
  </code></pre>
  
  <p>Here is my Ruby code:</p>
  
  <pre><code>module AESCrypt
    def AESCrypt.encrypt(data, key, iv)
      aes = OpenSSL::Cipher::Cipher.new("aes-256-cbc")
      aes.encrypt
      aes.key = key
      aes.iv = iv
      aes.update(data) + aes.final      
    end
  end
  
  plaintext = "Mary had a little lamb"
  iv = "96b88a5f0b9efb43"
  @crypted = AESCrypt::encrypt(plaintext, "g6zys8dlvvut6b1omxc5w15gnfad3jhb", iv)
  @crypted_base64 = Base64.encode64(@crypted)
  @crypted_base64_url = CGI.escape(@crypted_base64)
  </code></pre>
  
  <p>The infuriating thing is that both code samples produce <em>similar</em> but not identical hashes. For example, the above code generates (base64 encoded, not URL encoded):</p>
  
  <p>PHP: <strong><code>/aRCGgLBMOOAarjjtfTW2Qg2OtbPDLhx3KmgfgMzDJU=</code></strong></p>
  
  <p>Ruby: <strong><code>/aRCGgLBMOOAarjjtfTW2XIZhZ9VjBx8PdozxSL8IE0=</code></strong></p>
  
  <p>Can anyone explain what I'm doing wrong here? Also, it is easier for me (since I am a Ruby guy, not PHP usually) to fix the Ruby code rather than the PHP code. So if you wanted to provide a solution in Ruby that would pair well with PHP, I would be most appreciative. </p>
  
  <p>Oh, and also, in production the iv really will be random, but for this example I set it to be permanently the same so that output could be compared.</p>
  
  <p><strong>EDIT:</strong></p>
  
  <p>Thanks to Eugen Rieck's answer, I arrived at a solution. Ruby pads the blocks, but PHP does not, and you have to do it manually. Change the PHP code to the following, and you get encrypted strings that the above Ruby code can decipher easily:</p>
  
  <pre><code>$iv = '96b88a5f0b9efb43';
  $data = 'Mary had a little lamb';
  
  function encryptData($data,$iv){
      $key = 'g6zys8dlvvut6b1omxc5w15gnfad3jhb';
      $padded_data = pkcs5_pad($data);
      $cryptogram = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $padded_data, MCRYPT_MODE_CBC, $iv);
      return $cryptogram;
  }
  
  function pkcs5_pad ($text, $blocksize){
      $pad = $blocksize - (strlen($text) % $blocksize);
      return $text . str_repeat(chr($pad), $pad);
  }
  </code></pre>