I have data encrypted in ColdFusion which I am trying to decrypt in Ruby. I can’t get the output to match though.
On the ColdFusion side I have something like this:
<cfset key = 'DiYVka4mAYk=' />
<cfset str = 'hello' />
<cfset enc = encrypt(str, key, 'des', "base64") />
<cfset dec = decrypt(enc, key, 'des', "base64") />
<cfoutput>
#str# <!--- 'hello' --->
<br />
#enc# <!--- '3rNKAnEu+VA=' --->
<br />
#dec# <!--- 'hello' --->
</cfoutput>
The same, implemented in Ruby:
require 'openssl'
require 'base64'
str = 'hello'
key = 'DiYVka4mAYk='
des = OpenSSL::Cipher.new('des')
des.encrypt
des.key = key
data = des.update(str) + des.final
enc = Base64.encode64(data)
des.decrypt
des.key = key
dec = des.update(Base64.decode64(enc)) + des.final
puts str # => 'hello'
puts enc # => 'wVQs6NjOZwM='
puts dec # => 'hello'
Both work, but the encrypted strings are different. So passing encrypted data between ColdFusion and Ruby is not going to work.
The key was generated using ColdFusion’s generateSecretKey() function. It looks Base64 encoded, so I tried setting the key like this in Ruby:
key = Base64.decode64('DiYVka4mAYk=')
Again, the code works but the encrypted string is different.
Is there anything I am missing regards key encoding?
Also, I thought maybe there is more info implied when setting the algorithm to ‘des’ in ColdFusion. So I tried creating the Cipher in ruby with the following:
- des
- des-cbc
- des-cfb
- des-ecb
- des-ede
- des-ede-cbc
- des-ede-cfb
- des-ede-ofb
- des-ofb
Again, some variation in the encrypted string. But none matching the original ColdFusion version.
Note: the ColdFusion encryption has been in use for a long time, so I can’t make any edits on that side. The ‘fix’ must be in Ruby.
As asked, I’ll transfer my comment to an answer:
You have to ensure that the cipher modes, IVs, and padding match from both ends.
The Ruby defaults in 1.8.7 and 1.9.3 are ECB and no IV, and PCKS padding. The ColdFusion defaults are the same.
However it appears that in ruby 1.9.2, or in your particular environment, the default cipher mode is not ECB, which is changing the output. As you commented, setting the cipher mode to ECB manually (OpenSSL::Cipher.new(“DES-ECB”)) fixes the issue.