9

i need to do encryption and decryption in my rails app. Im trying to use ezcrypto, but whenever i do decryption i get this error.

OpenSSL::Cipher::CipherError in ProfilesController#show

wrong final block length

What would need to be changed to stop this error. I tried using another implementation of openssl like this (methods to be called from my model)

def encrypt_attr(unencrypted)
    c = OpenSSL::Cipher.new("aes-256-cbc")
    c.encrypt
    c.key = Digest::SHA1.hexdigest('pass')
    e = c.update(unencrypted)
    e << c.final
    return e
end

def decrypt_attr(encrypted_attr)
  if encrypted_attr != ""
    c = OpenSSL::Cipher::Cipher.new("aes-256-cbc")
    c.decrypt
    c.key = Digest::SHA1.hexdigest('pass')
    d = c.update(encrypted_attr)
    d << c.final
    return d
  end
end

It throws the exact same error on decryption. How should i do encryption and decryption and not get this openssl error.

4
  • hmm, my bad, you do have the same key in c.key Commented Dec 19, 2011 at 4:21
  • works for me. I'm getting this error only if encrypted_attr != e from encrypt_attr method. In this case you should use rescue in your decrypt_attr method Commented Dec 19, 2011 at 5:25
  • 1
    @jack, out of curiosity, if you are using cipher-block chaining, where is your initialization vector? See 5.3, Initialization Vectors, csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf Commented Dec 19, 2011 at 6:54
  • look at this stackoverflow.com/questions/2711709/… Commented Dec 19, 2011 at 7:26

3 Answers 3

18
require 'openssl'
require 'base64'

class AesEncryptDecrypt

  KEY = "EncryptDecryptGurudathBN"
  ALGORITHM = 'AES-128-ECB'

  def self.encryption(msg)
    begin
      cipher = OpenSSL::Cipher.new(ALGORITHM)
      cipher.encrypt()
      cipher.key = KEY
      crypt = cipher.update(msg) + cipher.final()
      crypt_string = (Base64.encode64(crypt))
      return crypt_string
    rescue Exception => exc
      puts ("Message for the encryption log file for message #{msg} = #{exc.message}")
    end
  end

  def self.decryption(msg)
    begin
      cipher = OpenSSL::Cipher.new(ALGORITHM)
      cipher.decrypt()
      cipher.key = KEY
      tempkey = Base64.decode64(msg)
      crypt = cipher.update(tempkey)
      crypt << cipher.final()
      return crypt
    rescue Exception => exc
      puts ("Message for the decryption log file for message #{msg} = #{exc.message}")
    end
  end
end

Encryption

irb(main):007:0> AesEncryptDecrypt.encryption('gurudath')
=> "rUPKObydUJd9cY9agm3Glw==\n"

Decryption

irb(main):008:0> AesEncryptDecrypt.decryption('rUPKObydUJd9cY9agm3Glw==')
=> "gurudath"
Sign up to request clarification or add additional context in comments.

3 Comments

what is padding mechanism, how to use PKCS5Padding to encrypt data in above program
Iam using same algorithm but my key is OpenSSL::PKey::RSA type, throwing no implicit conversion of OpenSSL::PKey::RSA into String exception when we set key as cipher.key = KEY
2

I know that the documentation is pretty sparse for Ruby's openssl package. However, if you would like to use cipher-block chaining, here is a brief snippet of code that outlines how to use the AES-256-CBC cipher:

require 'openssl'

# your data
raw  = 'the data to be encrypted goes here'
pwd  = 'secret'
salt = OpenSSL::Random.random_bytes(8)

# prepare cipher for encryption
e = OpenSSL::Cipher.new('AES-256-CBC')
e.encrypt
# next, generate a PKCS5-based string for your key + initialization vector 
key_iv = OpenSSL::PKCS5.pbkdf2_hmac_sha1(pwd, salt, 2000, e.key_len+e.iv_len)
key = key_iv[0, e.key_len]
iv  = key_iv[e.key_len, e.iv_len]

# now set the key and iv for the encrypting cipher
e.key = key
e.iv  = iv

# encrypt the data!
encrypted = '' << e.update(raw) << e.final
p encrypted

# and now we prepare to decrypt
d = OpenSSL::Cipher.new('AES-256-CBC')
d.decrypt
# now set the key and iv for the decrypting cipher
# this assumes that the password, salt, and iv are known,
# so then you would be able to generate the key as per above
d.key = key
d.iv  = iv

# decrypt the data!
decrypted = '' << d.update(encrypted) << d.final
p decrypted

This snippet is taken pretty much verbatim from the Japanese (original?) version of the Ruby standard library documentation on openssl. However, it does raise a few questions for you and your application design:

  1. You need to save the salt value. This is used along with the password to generate the key (you do not need to save the key).
  2. You need to save the iv initialization vector. This is used to start the very first block in the cipher-block chain. There is no need to encrypt this value, but this value should be generated for each and every message you encrypt.

Good luck!

Comments

0

I had the same problem as you and this is how I solved it:

  1. Your database column has to be: t.column :data, :binary, :limit => 10.megabyte.
  2. Use the exact code as this blog post.
  3. Choose AES-256-ECB
  4. Leave ivs as nil
  5. Choose a long key

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.