Which Cipher in Ruby OpenSSL API is equivalent to DES_ecb2_encrypt()? - ruby
Which Cipher in Ruby's OpenSSL API is equivalent to the OpenSSL C function DES_ecb2_encrypt()?
I see the following ciphers:
irb(main):003:0> OpenSSL::Cipher.ciphers
=> ["AES-128-CBC", "AES-128-CFB", "AES-128-CFB1", "AES-128-CFB8", "AES-128-ECB",
"AES-128-OFB", "AES-192-CBC", "AES-192-CFB", "AES-192-CFB1", "AES-192-CFB8",
"AES-192-ECB", "AES-192-OFB", "AES-256-CBC", "AES-256-CFB", "AES-256-CFB1",
"AES-256-CFB8", "AES-256-ECB", "AES-256-OFB", "AES128", "AES192", "AES256",
"BF", "BF-CBC", "BF-CFB", "BF-ECB", "BF-OFB", "CAMELLIA-128-CBC", "CAMELLIA-128-CFB",
"CAMELLIA-128-CFB1", "CAMELLIA-128-CFB8", "CAMELLIA-128-ECB", "CAMELLIA-128-OFB",
"CAMELLIA-192-CBC", "CAMELLIA-192-CFB", "CAMELLIA-192-CFB1", "CAMELLIA-192-CFB8",
"CAMELLIA-192-ECB", "CAMELLIA-192-OFB", "CAMELLIA-256-CBC", "CAMELLIA-256-CFB",
"CAMELLIA-256-CFB1", "CAMELLIA-256-CFB8", "CAMELLIA-256-ECB", "CAMELLIA-256-OFB",
"CAMELLIA128", "CAMELLIA192", "CAMELLIA256", "CAST", "CAST-cbc", "CAST5-CBC",
"CAST5-CFB", "CAST5-ECB", "CAST5-OFB", "DES", "DES-CBC", "DES-CFB", "DES-CFB1",
"DES-CFB8", "DES-ECB", "DES-EDE", "DES-EDE-CBC", "DES-EDE-CFB", "DES-EDE-OFB",
"DES-EDE3", "DES-EDE3-CBC", "DES-EDE3-CFB", "DES-EDE3-CFB1", "DES-EDE3-CFB8",
"DES-EDE3-OFB", "DES-OFB", "DES3", "DESX", "DESX-CBC", "RC2", "RC2-40-CBC",
"RC2-64-CBC", "RC2-CBC", "RC2-CFB", "RC2-ECB", "RC2-OFB", "RC4", "RC4-40", "SEED",
"SEED-CBC", "SEED-CFB", "SEED-ECB", "SEED-OFB", "aes-128-cbc", "aes-128-cfb",
"aes-128-cfb1", "aes-128-cfb8", "aes-128-ecb", "aes-128-ofb", "aes-192-cbc",
"aes-192-cfb", "aes-192-cfb1", "aes-192-cfb8", "aes-192-ecb", "aes-192-ofb",
"aes-256-cbc", "aes-256-cfb", "aes-256-cfb1", "aes-256-cfb8", "aes-256-ecb",
"aes-256-ofb", "aes128", "aes192", "aes256", "bf", "bf-cbc", "bf-cfb", "bf-ecb",
"bf-ofb", "blowfish", "camellia-128-cbc", "camellia-128-cfb", "camellia-128-cfb1",
"camellia-128-cfb8", "camellia-128-ecb", "camellia-128-ofb", "camellia-192-cbc",
"camellia-192-cfb", "camellia-192-cfb1", "camellia-192-cfb8", "camellia-192-ecb",
"camellia-192-ofb", "camellia-256-cbc", "camellia-256-cfb", "camellia-256-cfb1",
"camellia-256-cfb8", "camellia-256-ecb", "camellia-256-ofb", "camellia128",
"camellia192", "camellia256", "cast", "cast-cbc", "cast5-cbc", "cast5-cfb",
"cast5-ecb", "cast5-ofb", "des", "des-cbc", "des-cfb", "des-cfb1", "des-cfb8",
"des-ecb", "des-ede", "des-ede-cbc", "des-ede-cfb", "des-ede-ofb", "des-ede3",
"des-ede3-cbc", "des-ede3-cfb", "des-ede3-cfb1", "des-ede3-cfb8", "des-ede3-ofb",
"des-ofb", "des3", "desx", "desx-cbc", "rc2", "rc2-40-cbc", "rc2-64-cbc", "rc2-cbc",
"rc2-cfb", "rc2-ecb", "rc2-ofb", "rc4", "rc4-40", "seed", "seed-cbc", "seed-cfb",
"seed-ecb", "seed-ofb"]
I basically need the Ruby equivalent of this function call in C:
DES_ecb2_encrypt((const_DES_cblock *)data, (DES_cblock *)data, &des_key1, &des_key2, 1);
I've never used this method, but it looks like it does 2 key 3DES encryption using des_key1 for the final encryption instead of a 3rd key. This is keying option 2 for 3DES. It looks like the option des-ede probably does what you want.
encrypt = OpenSSL::Cipher::Cipher.new("des-ede")
encrypt.encrypt
encrypt.key= des_key1+des_key2
ct = encrypt.update(plain_text) + encrypt.final
And of course a decrypt
decrypt = OpenSSL::Cipher::Cipher.new("des-ede")
decrypt.decrypt
decrypt.key= des_key1+des_key2
pt = decrypt.update(ct) + decrypt.final
I hate to answer my own question here, but I found the solution.
I had an encrypted piece of data which was encrypted with this C-code:
DES_ecb3_encrypt(input,output, key1, key2, key1, 1)
which according to the Tripple-DES documentation does this:
cipher_text =Encrypt(key1,Decrypt(key2,Encrypt(key1,plain_text)))
to decode the cipher_text in Ruby, I did this:
decrypt.OpenSSL::Cipher::Cipher.new('des-ede3')
decrypt.decrypt
decrypt.key = key1 + key2 + key1
plain_text = decrypt(cipher_text) # gives correct result, but decrypt.final gives errors
# plain_text = decrypt(cipher_text) + decrypt.final # DOES NOT WORK
# => OpenSSL::Cipher::CipherError: wrong final block length ; WHY??
I'd appreciate if somebody could comment on:
why decypt.final causes an error, although the result is correct
Related
Ruby openssl encryption with DES-CBC incorrect result
I am trying to replicate the encryption result from here in Ruby using OpenSSL: https://emvlab.org/descalc/?key=18074F7ADD44C903&iv=18074F7ADD44C903&input=4E5A56564F4C563230313641454E5300&mode=cbc&action=Encrypt&output=25C843BA5C043FFFB50F76E43A211F8D Original string = "NZVVOLV2016AENS" String converted to hexadecimal = "4e5a56564f4c563230313641454e53" iv = "18074F7ADD44C903" key = "18074F7ADD44C903" Expected result = "9B699B4C59F1444E8D37806FA9D15F81" Here is my ruby code: require 'openssl' require "base64" include Base64 iv = "08074F7ADD44C903" cipher = "08074F7ADD44C903" def encode(string) puts "Attempting encryption - Input: #{string}" encrypt = OpenSSL::Cipher.new('DES-CBC') encrypt.encrypt encrypt.key = ["18074F7ADD44C903"].pack('H*') #.scan(/../).map{|b|b.hex}.pack('c*') encrypt.iv = ["18074F7ADD44C903"].pack('H*') result = encrypt.update(string) + encrypt.final puts "Raw output: #{result.inspect}" unpacked = result.unpack('H*')[0] puts "Encrypted key is: #{unpacked}" puts "Encrypted Should be: 9B699B4C59F1444E8D37806FA9D15F81" return unpacked end res = encode("NZVVOLV2016AENS") Output: Encrypted key is: 9b699b4c59f1444ea723ab91e89c023a Encrypted Should be: 9B699B4C59F1444E8D37806FA9D15F81 Interestingly, the first half of the result is correct, and the last 16 digits are incorrect.
The web site uses Zero padding by default, while the Ruby code uses PKCS#7 padding by default. Ruby does not seem to support Zero padding, so disable the default padding and implement Zero padding yourself. Zero padding pads to the next full block size with 0x00 values. The block size for DES is 8 bytes. If the last block of the plaintext is already filled, no padding is done: def zeroPad(string, blocksize) len = string.bytes.length padLen = (blocksize - len % blocksize) % blocksize string += "\0" * padLen return string end In the encode() function (which should better be called encrypt() function) the following lines must be added before encryption: encrypt.padding = 0 # disable PKCS#7 padding string = zeroPad(string, 8) # enable Zero padding The modified Ruby code then gives the same ciphertext as the web site. Note that DES is insecure, also it' s insecure to use the key as IV (as well as a static IV). Furthermore, Zero padding is unreliable in contrast to PKCS#7 padding.
How to extract the IV vector generated by encrypt method from encrypted_strings
I'm having troubles to extract the IV generated with the encrypt method from encrypted_strings library for a specific password I provide. From the documentation, I see that this method generates a key and iv based on a password using a C library that calls the same method as openssl to generate the key and iv: EVP_BytesToKey. What I'm trying to do is to be able to print the IV for any password I specify so I can port the encryption to another language. Can you think of any method to extract/print this IV vector from a password? These are the details of the algorithm, mode and padding this library uses: ALGO: DES-EDE3 MODE: CBC PADDING: PKCS5 The ruby script below prints out the encrypted message but no clue which iv was used. #!/usr/bin/ruby require 'encrypted_strings' data = 'Whackabad' password = 'bAJLyifeUJUBFWdHzVbykfDmPHtLKLMzViHW9aHGmyTLD8hGYZ' encrypted_data = data.encrypt(:symmetric, :password => password) printf "Data: #{data}\n" printf "Encrypted Data: #{encrypted_data}" I tried to use openssl as it allows me to print the iv and key generated using -p option but it uses a PKCS7 padding instead of PKCS5. So if I run the command below, doesn't print the same encrypted string as the ruby code above. echo -n 'Whackabad' | openssl enc -des-ede3-cbc -nosalt -a -k bAJLyifeUJUBFWdHzVbykfDmPHtLKLMzViHW9aHGmyTLD8hGYZ NOTE: -a: base64 encode, -k: password, and echo -n: removes the new line from the string so its exactly the same size as the ruby in string. If I add -nopad option, I don't know how to pad the output to get exactly the same encrypted result. Any help would be much appreciated
PKCS7 padding is basically the same as PKCS5. The reason you get a different result on the command line is that it only uses a single hash iteration, where the function used by encrypted_strings does 2048 iterations by default. The function used, EVP_BytesToKey is described in the OpenSSL wiki, which include details of the algorithm. Reproducing it in Ruby might look something like this (using MD5 and 2048 iterations): def hash(d, count) count.times do d = OpenSSL::Digest.digest('md5', d) end d end password = 'bAJLyifeUJUBFWdHzVbykfDmPHtLKLMzViHW9aHGmyTLD8hGYZ' bytes = '' last = '' # For des-ede3-cbc, 24 byte key + 8 byte IV = 32 bytes. while bytes.length < 32 last = hash(last + password, 2048) bytes << last end key = bytes[0...24] iv = bytes[24..-1] You can use these values to decrypt the result of your code (add require 'base64' first): # This is the result of your code: encrypted_data = "AEsDXVcgh2jsTjlDgh+REg==" # enrypted_strings produces base64 encoded results, so we decode first encrypted_data = Base64.decode64(encrypted_data) cipher = OpenSSL::Cipher.new('des-ede3-cbc') cipher.decrypt cipher.key = key cipher.iv = iv plain = cipher.update(encrypted_data) + cipher.final puts plain #=> "Whackabad"
DES3 encryption: ruby openssl::cipher vs. oracle dbms_obfuscation_toolkit
I have a legacy application written in PL/SQL that encrypts and decrypts data using 3DES. Now I need to perform similar encryption from a ruby app. Eventually the resulting hash will need to be decrypted by the same PL/SQL application using its existing algorithm. The problem is that I'm obtaining different encrypted results in PL/SQL and Ruby and I don't know why. First here is exactly how the PL/SQL encryption works: From Oracle's docs about DBMS_OBFUSCATION_TOOLKIT http://docs.oracle.com/cd/B19306_01/appdev.102/b14258/d_obtool.htm "Oracle's implementation of 3DES supports either a 2-key or 3-key implementation, in outer cipher-block-chaining (CBC) mode." Function signature: DBMS_OBFUSCATION_TOOLKIT.DES3Encrypt( input_string IN VARCHAR2, key_string IN VARCHAR2, encrypted_string OUT VARCHAR2, which IN PLS_INTEGER DEFAULT TwoKeyMode iv_string IN VARCHAR2 DEFAULT NULL); Note about the parameter which: "If = 0, (default), then TwoKeyMode is used. If = 1, then ThreeKeyMode is used." This helped me choose the cipher in the ruby version. Here is how the application makes that call: set serveroutput on; declare v_encrypted varchar2(100); begin dbms_obfuscation_toolkit.des3encrypt( input_string => 'abcdefgh', -- data to encrypt key_string => '16_byte_string_k', -- 16 byte = 128 bit key needed by DES3Encrypt encrypted_string => v_encrypted, iv_string => 'xxxxxxxx'); -- initialization vector dbms_output.put_line( lower(utl_raw.cast_to_raw(v_encrypted)) ); -- prints 23ff779e88e2dbe1 end; Second here is what I'm trying in Ruby: OpenSSL::Cipher docs: http://www.ruby-doc.org/stdlib-1.9.3/libdoc/openssl/rdoc/OpenSSL/Cipher.html OpenSSL docs to give me the cipher name: From http://www.openssl.org/docs/apps/enc.html "des-ede-cbc Two key triple DES EDE in CBC mode" require 'openssl' cipher = OpenSSL::Cipher.new('des-ede-cbc') cipher.encrypt input = 'abcdefgh' cipher.key = '16_byte_string_k' cipher.iv = 'xxxxxxxx' # i noticed that cipher.update returns same length hash as PL/SQL # if called without cipher.final, but you are not supposed to do that #encrypted = cipher.update(input) encrypted = cipher.update(input) + cipher.final hex_representation = encrypted.unpack("H*") puts hex_representation # prints a5cfc96485d7203eb929c28ceb9fcd53 As shown in the code the ruby version computes a different hash value. Why? What needs to change to make them consistent? Points I'm unsure about: Whether des-ede-cbc is in fact the same as what Oracle does. Whether utl_raw.cast_to_raw and unpack("H*") will do the same thing to the encrypted binary data. What exactly cipher.final appends and if there's any equivalent way to append that data in PL/SQL. Note: I am aware that DES is insecure and that AES has superseded it. My use case does not require these hashes to be unbreakable. The important requirement is to make the hashes consistent so that the PL/SQL app can decrypt hashes generated by the ruby app.
Let's go digging! ['des-cbc', 'des', 'des-cfb', 'des-ofb', 'des-ecb', 'des-ede-cbc', 'des-ede', 'des-ede-cfb', 'des-ede-ofb', 'des-ede3-cbc', 'des-ede3', 'des3', 'des-ede3-cfb', 'des-ede3-ofb', 'desx'].each do |flavour| begin c = OpenSSL::Cipher.new flavour c.encrypt c.key = '16_byte_string_k' c.iv = 'xxxxxxxx' str = 'abcdefgh' enc = c.update(str) + c.final puts "#{flavour} gives us #{enc.unpack('H*')}" rescue => e puts "#{flavour} didn't work because #{e.message}" end end The results: des-cbc gives us ["a5cfc96485d7203eb929c28ceb9fcd53"] des gives us ["a5cfc96485d7203eb929c28ceb9fcd53"] des-cfb gives us ["d898369e91589ae8"] des-ofb gives us ["d898369e91589ae8"] des-ecb gives us ["de8579b342a528b6143594946045d91a"] des-ede-cbc gives us ["23ff779e88e2dbe1c009dc3105d8ff88"] des-ede gives us ["0e589e3d85ac83efbb271a2e4a77cf4e"] des-ede-cfb gives us ["1618988004b6a948"] des-ede-ofb gives us ["1618988004b6a948"] des-ede3-cbc didn't work because key length too short des-ede3 didn't work because key length too short des3 didn't work because key length too short des-ede3-cfb didn't work because key length too short des-ede3-ofb didn't work because key length too short desx didn't work because key length too short des-ede-cbc gives you a match--at least the first part matches. The question is, why is the encrypted body longer? I'm going to bet this is the correct content and the PL/SQL version is truncated somehow--I'll see if I can figure it out. Edit: nope, it's the padding. When you set the padding to 0 on the cipher, you get the same results as the PL/SQL version, e.g. ['des-cbc', 'des', 'des-cfb', 'des-ofb', 'des-ecb', 'des-ede-cbc', 'des-ede', 'des-ede-cfb', 'des-ede-ofb', 'des-ede3-cbc', 'des-ede3', 'des3', 'des-ede3-cfb', 'des-ede3-ofb', 'desx'].each do |flavour| begin c = OpenSSL::Cipher.new flavour c.encrypt c.key = '16_byte_string_k' c.iv = 'xxxxxxxx' c.padding = 0 # This is the important part! str = 'abcdefgh' enc = c.update(str) + c.final puts "#{flavour} gives us #{enc.unpack('H*')}" rescue => e puts "#{flavour} didn't work because #{e.message}" end end ... des-ede-cbc gives us ["23ff779e88e2dbe1"] ... You will need to compare the two algorithms with different lengths of input string now. Take a look at the documentation for the padding method here: http://www.ruby-doc.org/stdlib-2.0.0/libdoc/openssl/rdoc/OpenSSL/Cipher.html
We had the same problem with one important difference: Our database procedure did not specify an initialization vector (IV) when encrypting the passwords. Omitting the IV in ruby did not lead to the same result as omitting it in the Oracle procedure call, so both seemed to use different "default" IVs. The default Oracle IV is "0123456789abcdef" hex decoded as some guys figured out here: https://community.oracle.com/thread/1528090 In Ruby you can set it like this: ['des-cbc', 'des', 'des-cfb', 'des-ofb', 'des-ecb', 'des-ede-cbc', 'des-ede', 'des-ede-cfb', 'des-ede-ofb', 'des-ede3-cbc', 'des-ede3', 'des3', 'des-ede3-cfb', 'des-ede3-ofb', 'desx'].each do |flavour| begin c = OpenSSL::Cipher.new flavour c.encrypt c.key = '16_byte_string_k' c.iv = ['0123456789abcdef'].pack('H*') # Required if no IV is set in Oracle! c.padding = 0 str = 'abcdefgh' enc = c.update(str) + c.final puts "#{flavour} gives us #{enc.unpack('H*')}" rescue => e puts "#{flavour} didn't work because #{e.message}" end end
How do I refactor OpenSSL pkcs5_keyivgen in ruby?
I have been using the following code in my app for the past year and have 200k record using this code: options = { :algorithm => 'aes-256-cbc', :value => "changethis", :key => "secretkey" } cipher = OpenSSL::Cipher::Cipher.new(options[:algorithm]) cipher.send(:encrypt) cipher.pkcs5_keyivgen(options[:key]) result = cipher.update(options[:value]) result << cipher.final # => "x\xED\x14s\xFD\x0E\x97\xC5\x996[M\x1E\x94\xDEI" I am required (by business) to refactor the pkcs5_keyivgen part, to do it correctly: For example, options = { :algorithm => 'aes-256-cbc', :value => "changethis", :key => "secretkey" } cipher = OpenSSL::Cipher::Cipher.new(options[:algorithm]) cipher.send(:encrypt) cipher.key = '' # ??? 1) How does pkcs5_keyivgen in above code generate key, or does it just use my options[:key] cipher.iv = '' # ??? 2) How does pkcs5_keyivgen in above code generate iv result = cipher.update(options[:value]) result << cipher.final I have to figure out how pkcs5_keyivgen sets key and iv. ideas here? We are using ruby-1.9.3-p286 and encryptor-1.1.3 I saw this question and this question, but they haven't help me solve the problem.
Was trying to solve this problem, but I think there is no easy solution or i just can't see one). Pkcs5_keyivgen() is deprecated and implements non-standard pass key derivation for AES 256. From this docs and this source code Pkcs5_keyivgen (pass, SALT = nil, num = 2048, digest = "MD5") -> nil Generates some key and IV from salt and pass. No salt in your case. Generation method is defined in v1.5 PKCS #5 (deprecated) So you are looking for "Password Based Key Derivation Function". PBKDF1 Pkcs5_keyivgen() function calls EVP_BytesToKey() from Openssl and EVP_BytesToKey() generates key bytes for larger key size in a non-standard way So MD5 generates hash of size EVP_MAX_MD_SIZE (16 + 20) // 16 for MD5 But AES key(32) + IV(16) sizes > EVP_MAX_MD_SIZE, so AES 256 will need multiple hashes to generate random key and IV. Here is source code of algorithm in C And here is nice pseudo-code explanation of the EVP_BytesToKey() If you really want to re-implement PBKDF1 here is also RTC2898 standard for PBKDF1 But i don't think that it is a good idea to implement crypto yourself
Encrypting/decrypting 3DES in Ruby
I have a key.bin file which content is something along the lines of: -12, 110, 93, 14, -48, ... This is being used by a service to decrypt 3DES content, but I need to encrypt it via Ruby. I've tried loads of scenarios with how to set the key and what to do with it, but to no avail as of yet: Tried splitting the key by , and converting each number to hex, concatenating the hex values to make the key Tried converting the number string to binary Tried converting the resulting hex to binary I assume what I need to do is something simple like: des = OpenSSL::Cipher::Cipher.new('des3') des.decrypt des.key = mistery # this step is where i'm having problems at final = des.update(encrypted) + des.final Any ideas on what I should do with this key? Key sample: -62,-53,124,-110,37,-88,-48,31,-57,93,70,-101,44,69,-88,-57,-123,-99,118,-119,110,55,11,14 Data sample: NEb2b9sYXgod6mTvaRv+MRsTJvIiTTI9VjnDGcxjxcN5qBH7FXvxYI6Oj16FeKKsoQvjAmdju2SQ ifJqPJTl97xeEbjdwm+W8XJnWs99ku85EznVBhzQxI1H2jPiZIcrqIVCWdd/OQun7AjK4w2+5yb7 DPN2OiCIEOz2zK6skJrBw3oTEHpXrSEhydOYxqI+c5hC4z3k5nktN6WSVLIo8EAjwenHPMDxboWF ET8R+QM5EznVBhzQxI1H2jPiZIcrqIVCWdd/OQun7AjK4w2+5yb7DPN2OiCIFqk4LRwEVq16jvKE vjz6T4/G34kx6CEx/JdZ1LdvxC3xYQIcwS0wVnmtxorFm4q5QQFHzNKQ5chrGZzDkFzAogsZ2l2B vcvlwgajNGHmxuVU83Ldn1e5rin7QqpjASqeDGFQHkiSbp4x6axVce2OGgfFpZdzCM7y6jLPpOlX LOC/Bs1vTwMzcBNRB/Fo4nsX9i4It8Spm228XQNUpQe4i9QGe/4AyKIhHoM8DkXwPZ6rWp0W0UMe keXjg41cED1JwjAAQSP3RYITB78bu+CEZKPOt2tQ2BvSw55mnFcvjIAYVQxCHliQ4PwgceHrnsZz 5aagC0QJ3oOKw9O0dlkVE3IM6KTBMcuZOZF19nCqxMFacQoDxjJY8tOJoN0Fe4Boz2FPyuggfLz9 yhljVJhxqOlTd8eA34Ex8SdC+5NDByAMumjzcPcXL8YVpSN85gytfd+skXhz3npmJ0dmZZOouu0Z vMmlaCqw96Sy0L1mHLKbjqmZ/W57OBNRB/Fo4nsX9i4It8Spm228XQNUpQe4i9QGe/4AyKIhHoM8 DkXwPZ5tXdq1dRG6IaS51oNzFFlOoP3wTJuOTpj+zQOBMMOi4ENFyyEwYbG/qE+uY8rVwBOUHv9b Yd9byvOZbnHDuf4oaWRZ+4K3s2NkEblDF9wU6Mb0ZqnLEJsypjrorH1cNIodIDu8nME1nD5bIDF6 XNrWC6pk6AV6eYQvNJw2QDz0RBD15fz/fAXCvbaCLDnhBKpLXrRbQdV+jxx2ipeC2ceMLLRFRPuR B+ycYht65lWh4jNjoEsBXGFKiT0bSX6Lx/ZQD3twJWbML8ifRhw7SW0jOkUF+dAfXYNaD6nqA6Xq TkcsDGaJsVq8wwCIWNh6tDRSw7ba4c391147kmnqEgXdKmmnEzUfHtpRw88C0/u0qj809hB4qB0B lxj/87aDo4VOz9S4jjtk849CxtA/a9+532A4YlXjsPt/f0KZ2drAGEr1VSWzaLh/sMwP5tznmPaK uozS6C74gMNdhtNMFz0HONcYecS0hg4lrdRyljROgzC33QoBIHbQXJrG0OXE3+81uhJwusEnFaD9 8Eybjk6YeNk3oxL3C5fx/xXgFmhcLLGdxRe/am0jqA1gV6MyQFUKtzdnNOUYpHkYXT9Ea7YYln4Q D96Z9AI5EznVBhzQxI1H2jPiZIcrqIVCWdd/OQun7AjK4w2+5yb7DPN2OiCIFqk4LRwEVq16jvKE vjz6T4/G34kx6CEx/JdZ1LdvxC3iEcYTrEH9kKhPrmPK1cATlB7/W2HfW8rzmW5xw7n+KGlkWfuC t7NjZBG5QxfcFOjG9GapyxCbMqY66Kx9XDSKHSA7vJzBNZw+WyAxelza1guqZOgFenmElSgtUOo7 TEunuphaMIEQgo0udojG6dm2FtRmA4yntNCnCDzGTY72nrFBz3EZmVXGEm6X3Xd5Ito=
Got it working! Here's how: Decryption def read_key(key_file) File.read(key_file).split(',').map { |x| x.to_i }.pack('c*') end des = OpenSSL::Cipher::Cipher.new('des-ede3') des.decrypt des.key = read_key('key.bin') result = des.update(decoded) + des.final Encryption def read_key(key_file) File.read(key_file).split(',').map { |x| x.to_i }.pack('c*') end des2 = OpenSSL::Cipher::Cipher.new('des-ede3') des2.encrypt des2.key = read_key('key.bin') result = des2.update(result) + des2.final puts Base64.encode64(result)