1

I have encrypted some plaintext using the openssl command line utility using a password:

echo -n "foo" | openssl enc -e -base64 -rc4 -nosalt -pass pass:secretkey

This returns:

ryW2

How can I decrypt this value using Ruby?

anothermh
  • 9,815
  • 3
  • 33
  • 52
Vishal Zambre
  • 320
  • 1
  • 10

3 Answers3

2

Finally with reference of Above in Ruby

Encode

def encrypt(str, key)
  cipher = OpenSSL::Cipher.new('RC4')
  cipher.key = OpenSSL::Digest.digest('md5', key)
  cipher.decrypt
  Base64.encode64(cipher.update(str) + cipher.final)
end

encrypt('This is Test', 'Test')
=> "JGmpM+ewGA79qaZH\n"

Decode

def decrypt(encrypted_string, key)
  decipher = OpenSSL::Cipher.new('RC4')
  decipher.key = OpenSSL::Digest.digest('md5', key)
  decipher.decrypt
  decipher.update(Base64.decode64(encrypted_string)) + decipher.final
end

decrypt("JGmpM+ewGA79qaZH\n", "Test")
=> "This is Test"
Vishal Zambre
  • 320
  • 1
  • 10
1

Here is the command you would need to enter to encrypt the string foo into some ciphertext:

echo -n "foo" | openssl enc -e -base64 -rc4 -nosalt -pass pass:secretkey -p

And this returns:

key=610A2EE688CDA9E724885E23CD2CFDEE
ryW2

ryW2 is your base64 encoded ciphertext.

We have added -p so we can see the key that is used for encryption.

-p is required because OpenSSL uses an internal function EVP_BytesToKey to convert the passphrase to a key and there is no equivalent Ruby method to do this. Accordingly, you'll have to use this key value directly in Ruby when encrypting or decrypting instead of the passphrase.

Decryption is just as straight-forward:

echo "ryW2" | openssl enc -d -base64 -rc4 -nosalt -pass pass:secretkey

This returns:

foo

Given all this, here is how you would encrypt this string using Ruby to get the same value:

require 'openssl'
require 'base64'

plaintext = 'foo'
cipher = OpenSSL::Cipher.new('rc4')
cipher.encrypt
# Use the key that was generated by EVP_BytesToKey
key = '610A2EE688CDA9E724885E23CD2CFDEE'
# Convert the key to a byte string
key_bytes = key.scan(/../).map { |x| x.hex.chr }.join
cipher.key = key_bytes
ciphertext = cipher.update(plaintext) + cipher.final
base64 = Base64.strict_encode64(ciphertext)

This returns the same value as OpenSSL on the command line:

ryW2

Decryption is fairly straightforward:

decipher = OpenSSL::Cipher.new('rc4')
decipher.decrypt
decipher.key = key_bytes
decrypted = decipher.update(ciphertext) + decipher.final

This returns the original plaintext:

foo

Ultimately, encryption and decryption is fairly straightforward as long as you know what EVP_BytesToKey will return for a given pass. You can read more about EVP_BytesToKey here:

anothermh
  • 9,815
  • 3
  • 33
  • 52
0

I wasn't happy that there is no built-in way to do this in Ruby. My other answer to this question is a functional workaround but it requires some time-consuming steps that I'm not crazy about. So I wrote a gem called evp_bytes_to_key that'll do it for you!

First install the gem:

gem install evp_bytes_to_key

Then generate your ciphertext:

echo -n "foo" | openssl enc -e -base64 -rc4 -nosalt -pass pass:secretkey

This returns:

ryW2

Then decrypt it in Ruby:

require 'evp_bytes_to_key'
require 'openssl'
require 'base64'

decipher = OpenSSL::Cipher.new('rc4')
decipher.decrypt
decipher.key = EvpBytesToKey::Key.new('secretkey', nil, 128, 0).key
ciphertext = Base64.strict_decode64('ryW2')
plaintext = decipher.update(ciphertext) + decipher.final

This returns the original plaintext:

foo

More examples for using this gem can be found in the README.

anothermh
  • 9,815
  • 3
  • 33
  • 52