4

I'm trying to migrate some legacy PHP code to ruby, and I've encountered a problem with some 3DES encryption. This is the PHP implementation using mcrypt:

function encrypt_3DES($message, $key){

    $bytes = array(0,0,0,0,0,0,0,0); //byte [] IV = {0, 0, 0, 0, 0, 0, 0, 0}
    $iv = implode(array_map("chr", $bytes)); //PHP 4 >= 4.0.2

    $ciphertext = mcrypt_encrypt(MCRYPT_3DES, $key, $message, MCRYPT_MODE_CBC, $iv); 
    return $ciphertext;
}

and this is my ruby code:

def encrypt_3DES(message, key)
  des=OpenSSL::Cipher.new('des3')
  des.encrypt
  des.key = key
  des.update(message)+des.final
end

However results are slightly different (base64 encoded):

//PHP
ZpgH7NWpRx+Mi6tDBZ9q2Q==

# Ruby
ZpgH7NWpRx/usGDIsQ+A8A==

As you can see it's the lowest portion of the string's bytes that differs. Any pointers are much appreciated.

sjaime
  • 1,480
  • 9
  • 16

2 Answers2

3

I answer my own question.

It was an issue about how openssl and mcrypt implementations use padding. My cryptography knowledge isn't too deep, but I found a usable code sample here http://opensourcetester.co.uk/2012/11/29/zeros-padding-3des-ruby-openssl/

#ENCRYPTION
block_length = 8
des.padding = 0 #Tell Openssl not to pad
des.encrypt
json = '{"somekey":"somevalue"}'
json += "\0" until json.bytesize % block_length == 0 #Pad with zeros
edata = des.update(json) + des.final 
b64data = Base64.encode64(edata).gsub("\n",'')

Basically, ruby openssl will use PKCS padding, while mcrypt uses 0 padding. So in our code I had to tell openssl not to pad the string with des.padding = 0 and then do the padding manually: json += "\0" until json.bytesize % block_length == 0.

Those are the important bits that were missing in my original implementation.

sjaime
  • 1,480
  • 9
  • 16
0

Could the PHP combination of MCRYPT_3DES and MCRYPT_MODE_CBC not be equivalent to the ruby OpenSSL library's 3des (or des-ede3-cbc). There are examples of other mismatches.

Try one of the other modes, such as des-ede-cbc or des-cbc (See full list here)

Community
  • 1
  • 1
ReggieB
  • 8,100
  • 3
  • 38
  • 46
  • Thanks for your answer, but in the end it turned to be a different issue about how ruby openssl and php mcrypt use padding for block ciphers (see my answer) – sjaime Nov 16 '15 at 12:54
  • @sjaime your solution is interesting. I can see that being worth knowing about in the future. – ReggieB Nov 16 '15 at 13:18