Discussion:
OpenSSL::Cipher decrypt returns 'wrong final block length'
Ram
2009-02-26 06:34:41 UTC
Permalink
I just want to encrypt a string submitted through a form before saving
it to the DB. And then decrypt it again when I need to retrieve and
use it.

Im trying to use the OpenSSL::Cipher library. I have the following
module for encryption/decryption
[code]
require 'openssl'

module AESCrypt
# Decrypts a block of data (encrypted_data) given an encryption key
# and an initialization vector (iv). Keys, iv's, and the data
# returned are all binary strings. Cipher_type should be
# "AES-256-CBC", "AES-256-ECB", or any of the cipher types
# supported by OpenSSL. Pass nil for the iv if the encryption type
# doesn't use iv's (like ECB).
#:return: => String
#:arg: encrypted_data => String
#:arg: key => String
#:arg: iv => String
#:arg: cipher_type => String
def AESCrypt.decrypt(encrypted_data, key, iv, cipher_type="aes-256-
cbc")
aes = OpenSSL::Cipher::Cipher.new(cipher_type)
aes.decrypt
aes.key = key
aes.iv = iv if iv != nil
aes.update(encrypted_data) + aes.final
end

# Encrypts a block of data given an encryption key and an
# initialization vector (iv). Keys, iv's, and the data returned
# are all binary strings. Cipher_type should be "AES-256-CBC",
# "AES-256-ECB", or any of the cipher types supported by OpenSSL.
# Pass nil for the iv if the encryption type doesn't use iv's (like
# ECB).
#:return: => String
#:arg: data => String
#:arg: key => String
#:arg: iv => String
#:arg: cipher_type => String
def AESCrypt.encrypt(data, key, iv, cipher_type="aes-256-cbc")
aes = OpenSSL::Cipher::Cipher.new(cipher_type)
aes.encrypt
aes.key = key
aes.iv = iv if iv != nil
aes.update(data) + aes.final
end
end
[/code]
And here is the model code where I encrypt and decrypt the string.
[code]
def encrypt_cc_pass
return if cc_pass.blank?
self.cc_pass_key = Time.now.to_s
self.cc_pass_iv = Date.today.to_s
self.encrypted_cc_pass = AESCrypt.encrypt(cc_pass, cc_pass_key,
cc_pass_iv)
end

def decrypted_cc_pass
AESCrypt.decrypt(encrypted_cc_pass, cc_pass_key, cc_pass_iv)
end
[/code]

And this is the error I get

wrong final block length in:config/initializers/aes_crypt.rb:20:in
`final'

Anyone know what im doing wrong here?
Also, Im not able to understand the inners of encryption here. Is
there any gem with good documentation or simpler usage?
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
To post to this group, send email to rubyonrails-talk-/***@public.gmane.org
To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/***@public.gmane.org
For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en
-~----------~----~----~----~------~----~------~--~---
Michael Graff
2009-02-26 11:16:37 UTC
Permalink
I'm going to seem rude probably, but it's still true.

You are dabbling in crypto and you don't know what you're doing.
Stop, and find someone who does.
From what I read, you're trying to encrypt credit card data. Before
you leak all the data from your database by using the _current time_
-- one of the weakest possible keys and IV values out there -- talk to
someone, hire a consultant, or at least read 'applied cryptography.'
AESCrypt.encrypt("this", "X" * 32, "I" * 32)
=> "this"

Your code works. Your lack of understanding about the algorithm you
are using, the meaning of a key in that context, how to securely
generate one, and how important a secure IV is, has bitten you.

Storing the key, IV, and encrypted data in a database is exactly the
same as storing the unencrypted data. It will stop casual browsing.
If that is what you are trying to do, there are far easier methods,
such as converting the whole thing into base64 or hex or something.
If you believe your code actually adds security...

--Michael
I just want to encrypt a string submitted through a form before saving
it to the DB. And then decrypt it again when I need to retrieve and
use it.
Im trying to use the OpenSSL::Cipher library. I have the following
module for encryption/decryption
[code]
require 'openssl'
module AESCrypt
 # Decrypts a block of data (encrypted_data) given an encryption key
 # and an initialization vector (iv).  Keys, iv's, and the data
 # returned are all binary strings.  Cipher_type should be
 # "AES-256-CBC", "AES-256-ECB", or any of the cipher types
 # supported by OpenSSL.  Pass nil for the iv if the encryption type
 # doesn't use iv's (like ECB).
 #:return: => String
 #:arg: encrypted_data => String
 #:arg: key => String
 #:arg: iv => String
 #:arg: cipher_type => String
 def AESCrypt.decrypt(encrypted_data, key, iv, cipher_type="aes-256-
cbc")
   aes = OpenSSL::Cipher::Cipher.new(cipher_type)
   aes.decrypt
   aes.key = key
   aes.iv = iv if iv != nil
   aes.update(encrypted_data) + aes.final
 end
 # Encrypts a block of data given an encryption key and an
 # initialization vector (iv).  Keys, iv's, and the data returned
 # are all binary strings.  Cipher_type should be "AES-256-CBC",
 # "AES-256-ECB", or any of the cipher types supported by OpenSSL.
 # Pass nil for the iv if the encryption type doesn't use iv's (like
 # ECB).
 #:return: => String
 #:arg: data => String
 #:arg: key => String
 #:arg: iv => String
 #:arg: cipher_type => String
 def AESCrypt.encrypt(data, key, iv, cipher_type="aes-256-cbc")
   aes = OpenSSL::Cipher::Cipher.new(cipher_type)
   aes.encrypt
   aes.key = key
   aes.iv = iv if iv != nil
   aes.update(data) + aes.final
 end
end
[/code]
And here is the model code where I encrypt and decrypt the string.
[code]
 def encrypt_cc_pass
   return if cc_pass.blank?
   self.cc_pass_key = Time.now.to_s
   self.cc_pass_iv = Date.today.to_s
   self.encrypted_cc_pass = AESCrypt.encrypt(cc_pass, cc_pass_key,
cc_pass_iv)
 end
 def decrypted_cc_pass
   AESCrypt.decrypt(encrypted_cc_pass, cc_pass_key, cc_pass_iv)
 end
[/code]
And this is the error I get
wrong final block length in:config/initializers/aes_crypt.rb:20:in
`final'
Anyone know what im doing wrong here?
Also, Im not able to understand the inners of encryption here. Is
there any gem with good documentation or simpler usage?
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
To post to this group, send email to rubyonrails-talk-/***@public.gmane.org
To unsubscribe from this group, send email to rubyonrails-talk+***@googlegroups.com
For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en
-~----------~----~----~----~------~----~------~--~---
Ram
2009-02-26 11:37:41 UTC
Permalink
Michael,

I do agree with you in that I really have little to no idea of
cryptography. Think I mentioned that in the OP itself. And I simply
left out the complex IV and key for the sake of making this post a
little more readable. Also, I have been reading up a bit and I hear
the same of what you say in that its safer to store the iv and key in
a database of their own. Thanks for that..

Well, the point though is that im getting an error that I dont have a
solution for. And I think im giving bad input to the encrypt and
decrypt methods and thats exactly what im trying to get someone to
bring me up to speed with. Even in your example, im guessing you're
generating a 32 bit something....? Well the real key and iv in my code
are generated like this

Digest::SHA1.hexdigest("whatever").unpack('a2'*32).map{|x| x.hex}.pack
('c'*32)

Now I DID pick this up from the net so im not completely sure what
this does either.

I would appreciate it if you could establish the basics that I need to
know here.
Ive been trying to find relevant ROR specific documentation for the
OpenSSL gem but none that are understandable so far. Will look for
'applied cryptography'.
Thanks for the response.
Post by Michael Graff
I'm going to seem rude probably, but it's still true.
You are dabbling in crypto and you don't know what you're doing.
Stop, and find someone who does.
From what I read, you're trying to encrypt credit card data.  Before
you leak all the data from your database by using the _current time_
-- one of the weakest possible keys and IV values out there -- talk to
someone, hire a consultant, or at least read 'applied cryptography.'
Post by Ram
AESCrypt.encrypt("this", "X" * 32, "I" * 32)
=> "this"
Your code works.  Your lack of understanding about the algorithm you
are using, the meaning of a key in that context, how to securely
generate one, and how important a secure IV is, has bitten you.
Storing the key, IV, and encrypted data in a database is exactly the
same as storing the unencrypted data.  It will stop casual browsing.
If that is what you are trying to do, there are far easier methods,
such as converting the whole thing into base64 or hex or something.
If you believe your code actually adds security...
--Michael
Post by Ram
I just want to encrypt a string submitted through a form before saving
it to the DB. And then decrypt it again when I need to retrieve and
use it.
Im trying to use the OpenSSL::Cipher library. I have the following
module for encryption/decryption
[code]
require 'openssl'
module AESCrypt
 # Decrypts a block of data (encrypted_data) given an encryption key
 # and an initialization vector (iv).  Keys, iv's, and the data
 # returned are all binary strings.  Cipher_type should be
 # "AES-256-CBC", "AES-256-ECB", or any of the cipher types
 # supported by OpenSSL.  Pass nil for the iv if the encryption type
 # doesn't use iv's (like ECB).
 #:return: => String
 #:arg: encrypted_data => String
 #:arg: key => String
 #:arg: iv => String
 #:arg: cipher_type => String
 def AESCrypt.decrypt(encrypted_data, key, iv, cipher_type="aes-256-
cbc")
   aes = OpenSSL::Cipher::Cipher.new(cipher_type)
   aes.decrypt
   aes.key = key
   aes.iv = iv if iv != nil
   aes.update(encrypted_data) + aes.final
 end
 # Encrypts a block of data given an encryption key and an
 # initialization vector (iv).  Keys, iv's, and the data returned
 # are all binary strings.  Cipher_type should be "AES-256-CBC",
 # "AES-256-ECB", or any of the cipher types supported by OpenSSL.
 # Pass nil for the iv if the encryption type doesn't use iv's (like
 # ECB).
 #:return: => String
 #:arg: data => String
 #:arg: key => String
 #:arg: iv => String
 #:arg: cipher_type => String
 def AESCrypt.encrypt(data, key, iv, cipher_type="aes-256-cbc")
   aes = OpenSSL::Cipher::Cipher.new(cipher_type)
   aes.encrypt
   aes.key = key
   aes.iv = iv if iv != nil
   aes.update(data) + aes.final
 end
end
[/code]
And here is the model code where I encrypt and decrypt the string.
[code]
 def encrypt_cc_pass
   return if cc_pass.blank?
   self.cc_pass_key = Time.now.to_s
   self.cc_pass_iv = Date.today.to_s
   self.encrypted_cc_pass = AESCrypt.encrypt(cc_pass, cc_pass_key,
cc_pass_iv)
 end
 def decrypted_cc_pass
   AESCrypt.decrypt(encrypted_cc_pass, cc_pass_key, cc_pass_iv)
 end
[/code]
And this is the error I get
wrong final block length in:config/initializers/aes_crypt.rb:20:in
`final'
Anyone know what im doing wrong here?
Also, Im not able to understand the inners of encryption here. Is
there any gem with good documentation or simpler usage?
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
To post to this group, send email to rubyonrails-talk-/***@public.gmane.org
To unsubscribe from this group, send email to rubyonrails-talk+***@googlegroups.com
For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en
-~----------~----~----~----~------~----~------~--~---
Michael Graff
2009-02-26 11:59:03 UTC
Permalink
(There is a bit of hand-waving in this reply, but it'll get you started.)

AES-256-CBC means this: AES algorithm. Block size 256-bits.
Cipher-block-chaining.

What this describes is a system where your data is encrypted in a
256-bit block, which GENERALLY means you need a 256-bit key. The
documentation for the Ruby OpenSSL system is, as near as I can tell,
non-existent. However, looking up the openssl library for C will tell
you a lot -- Ruby just calls the C library your system has installed.

In this case, AES-256-CBC requires a 256-bit key and IV. (IV is
"initialization vector" and is generally a random value. Its purpose
is to make the same plaintext encrypt to different cyphertext.)

In my example, I generated 32-character long strings using the format:
"X" * 32. This
will make a string with 32-X's in it. Probably not all that secure,
but works for an example. :)

If you are running on a Unix system with /dev/random, and it has
sufficient "real" randomness, you can use it to generate your IVs, and
in your implementation, keys.

File.open("/dev/random") do |rnd|
key = rnd.read(32)
iv = rnd.read(32)
end

If you are unable to use /dev/random, you could use /dev/urandom, but
understand what the difference is. /dev/random is probably strong
(check with your system docs) and unless random data is available,
will "block" -- not return until there is. /dev/urandom is
pseudo-random, and will return always. However, it will use what
little randomness exists and stretch it out.

Note that your system is a lot like the method the
restful_authentication plugin does. restful_authentication uses a
global, per-application "secret" that is used much like a key, and a
per-user "salt" which is used as an IV. Its only purpose is to make
the password "mypassword" look different across users. The main
difference is that you can get the data back, while
restful_authentication is a one-way thing -- you can't recover a
password from what it stores.

For your purposes, you can probably generate a one-time "secure"
secret key, much like restful_authentication does, and store it in a
global. You would then generate per-item IVs of length 256-bits (32
characters) and store those, along with the encrypted CC info.

This is much more important to do if you have your application on one
server and the database on another. The database itself does not have
all the bits needed to open the data. Unfortunately, most people will
break into your web server, not your database engine.

As for what your digest thing does, it appears to "stretch" the
passphrase out from an ASCII format to something much longer. This is
commonly referred to as "key crunching" and does not make a more
secure key than just padding the value out by duplicating the
passphrase until it is long enough. That is, the digest thing is more
or less the same as using the string:
"whateverwhateverwhateverwhatever". The difference is that you can
look at the readable one and know it is a very bad key to use, while
9755571c6b7df2cdb1dddaaae2b399b7 almost looks random. (It's not.)

--Michael
Post by Ram
Michael,
I do agree with you in that I really have little to no idea of
cryptography. Think I mentioned that in the OP itself. And I simply
left out the complex IV and key for the sake of making this post a
little more readable. Also, I have been reading up a bit and I hear
the same of what you say in that its safer to store the iv and key in
a database of their own. Thanks for that..
Well, the point though is that im getting an error that I dont have a
solution for. And I think im giving bad input to the encrypt and
decrypt methods and thats exactly what im trying to get someone to
bring me up to speed with. Even in your example, im guessing you're
generating a 32 bit something....? Well the real key and iv in my code
are generated like this
Digest::SHA1.hexdigest("whatever").unpack('a2'*32).map{|x| x.hex}.pack
('c'*32)
Now I DID pick this up from the net so im not completely sure what
this does either.
I would appreciate it if you could establish the basics that I need to
know here.
Ive been trying to find relevant ROR specific documentation for the
OpenSSL gem but none that are understandable so far. Will look for
'applied cryptography'.
Thanks for the response.
Post by Michael Graff
I'm going to seem rude probably, but it's still true.
You are dabbling in crypto and you don't know what you're doing.
Stop, and find someone who does.
From what I read, you're trying to encrypt credit card data.  Before
you leak all the data from your database by using the _current time_
-- one of the weakest possible keys and IV values out there -- talk to
someone, hire a consultant, or at least read 'applied cryptography.'
Post by Ram
AESCrypt.encrypt("this", "X" * 32, "I" * 32)
=> "this"
Your code works.  Your lack of understanding about the algorithm you
are using, the meaning of a key in that context, how to securely
generate one, and how important a secure IV is, has bitten you.
Storing the key, IV, and encrypted data in a database is exactly the
same as storing the unencrypted data.  It will stop casual browsing.
If that is what you are trying to do, there are far easier methods,
such as converting the whole thing into base64 or hex or something.
If you believe your code actually adds security...
--Michael
Post by Ram
I just want to encrypt a string submitted through a form before saving
it to the DB. And then decrypt it again when I need to retrieve and
use it.
Im trying to use the OpenSSL::Cipher library. I have the following
module for encryption/decryption
[code]
require 'openssl'
module AESCrypt
 # Decrypts a block of data (encrypted_data) given an encryption key
 # and an initialization vector (iv).  Keys, iv's, and the data
 # returned are all binary strings.  Cipher_type should be
 # "AES-256-CBC", "AES-256-ECB", or any of the cipher types
 # supported by OpenSSL.  Pass nil for the iv if the encryption type
 # doesn't use iv's (like ECB).
 #:return: => String
 #:arg: encrypted_data => String
 #:arg: key => String
 #:arg: iv => String
 #:arg: cipher_type => String
 def AESCrypt.decrypt(encrypted_data, key, iv, cipher_type="aes-256-
cbc")
   aes = OpenSSL::Cipher::Cipher.new(cipher_type)
   aes.decrypt
   aes.key = key
   aes.iv = iv if iv != nil
   aes.update(encrypted_data) + aes.final
 end
 # Encrypts a block of data given an encryption key and an
 # initialization vector (iv).  Keys, iv's, and the data returned
 # are all binary strings.  Cipher_type should be "AES-256-CBC",
 # "AES-256-ECB", or any of the cipher types supported by OpenSSL.
 # Pass nil for the iv if the encryption type doesn't use iv's (like
 # ECB).
 #:return: => String
 #:arg: data => String
 #:arg: key => String
 #:arg: iv => String
 #:arg: cipher_type => String
 def AESCrypt.encrypt(data, key, iv, cipher_type="aes-256-cbc")
   aes = OpenSSL::Cipher::Cipher.new(cipher_type)
   aes.encrypt
   aes.key = key
   aes.iv = iv if iv != nil
   aes.update(data) + aes.final
 end
end
[/code]
And here is the model code where I encrypt and decrypt the string.
[code]
 def encrypt_cc_pass
   return if cc_pass.blank?
   self.cc_pass_key = Time.now.to_s
   self.cc_pass_iv = Date.today.to_s
   self.encrypted_cc_pass = AESCrypt.encrypt(cc_pass, cc_pass_key,
cc_pass_iv)
 end
 def decrypted_cc_pass
   AESCrypt.decrypt(encrypted_cc_pass, cc_pass_key, cc_pass_iv)
 end
[/code]
And this is the error I get
wrong final block length in:config/initializers/aes_crypt.rb:20:in
`final'
Anyone know what im doing wrong here?
Also, Im not able to understand the inners of encryption here. Is
there any gem with good documentation or simpler usage?
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
To post to this group, send email to rubyonrails-talk-/***@public.gmane.org
To unsubscribe from this group, send email to rubyonrails-talk+***@googlegroups.com
For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en
-~----------~----~----~----~------~----~------~--~---
Ram
2009-02-26 12:30:16 UTC
Permalink
Phew! That was a LOT of new information all at once!
Thanks a lot for the crash course! :)
The restful_authentication analogy helped and I get what you mean by
thats one-way.
Now about your suggestion for generating a one-time key and storing it
in a global variable, not having decided on the hosting yet, I was
wondering if its still secure if both the database and the application
were on the SAME server. Or is it best to keep the IV/key on a
separate server?
Oh and yes, the Digest thing.. what you said helped me understand
better. :)
By the way, I tried your test code above on IRB and I dont get the
same encrypted string. Here're the results..
Post by Michael Graff
AESCrypt.encrypt("this","X" * 32,"I" * 32)
OpenSSL::CipherError: wrong final block length
from /Users/fire/Sites/Vinay/ROR/RealApps/fi_rest_auth/config/
initializers/aes_crypt.rb:20:in `final'
from /Users/fire/Sites/Vinay/ROR/RealApps/fi_rest_auth/config/
initializers/aes_crypt.rb:20:in `decrypt'
from (irb):2

Im guessing the ? marks suggest something?
Thanks again for the guidance Michael. Appreciate it :).
Post by Michael Graff
(There is a bit of hand-waving in this reply, but it'll get you started.)
AES-256-CBC means this:  AES algorithm. Block size 256-bits.
Cipher-block-chaining.
What this describes is a system where your data is encrypted in a
256-bit block, which GENERALLY means you need a 256-bit key.  The
documentation for the Ruby OpenSSL system is, as near as I can tell,
non-existent.  However, looking up the openssl library for C will tell
you a lot -- Ruby just calls the C library your system has installed.
In this case, AES-256-CBC requires a 256-bit key and IV.  (IV is
"initialization vector" and is generally a random value.  Its purpose
is to make the same plaintext encrypt to different cyphertext.)
 "X" * 32.  This
will make a string with 32-X's in it.  Probably not all that secure,
but works for an example.   :)
If you are running on a Unix system with /dev/random, and it has
sufficient "real" randomness, you can use it to generate your IVs, and
in your implementation, keys.
  File.open("/dev/random") do |rnd|
    key = rnd.read(32)
    iv = rnd.read(32)
  end
If you are unable to use /dev/random, you could use /dev/urandom, but
understand what the difference is.  /dev/random is probably strong
(check with your system docs) and unless random data is available,
will "block" -- not return until there is.  /dev/urandom is
pseudo-random, and will return always.  However, it will use what
little randomness exists and stretch it out.
Note that your system is a lot like the method the
restful_authentication plugin does.  restful_authentication uses a
global, per-application "secret" that is used much like a key, and a
per-user "salt" which is used as an IV.  Its only purpose is to make
the password "mypassword" look different across users.  The main
difference is that you can get the data back, while
restful_authentication is a one-way thing -- you can't recover a
password from what it stores.
For your purposes, you can probably generate a one-time "secure"
secret key, much like restful_authentication does, and store it in a
global.  You would then generate per-item IVs of length 256-bits (32
characters) and store those, along with the encrypted CC info.
This is much more important to do if you have your application on one
server and the database on another.  The database itself does not have
all the bits needed to open the data.  Unfortunately, most people will
break into your web server, not your database engine.
As for what your digest thing does, it appears to "stretch" the
passphrase out from an ASCII format to something much longer.  This is
commonly referred to as "key crunching" and does not make a more
secure key than just padding the value out by duplicating the
passphrase until it is long enough.  That is, the digest thing is more
"whateverwhateverwhateverwhatever".  The difference is that you can
look at the readable one and know it is a very bad key to use, while
9755571c6b7df2cdb1dddaaae2b399b7 almost looks random.  (It's not.)
--Michael
Michael,
I do agree with you in that I really have little to no idea of
cryptography. Think I mentioned that in the OP itself. And I simply
left out the complex IV and key for the sake of making this post a
little more readable. Also, I have been reading up a bit and I hear
the same of what you say in that its safer to store the iv and key in
a database of their own. Thanks for that..
Well, the point though is that im getting an error that I dont have a
solution for. And I think im giving bad input to the encrypt and
decrypt methods and thats exactly what im trying to get someone to
bring me up to speed with. Even in your example, im guessing you're
generating a 32 bit something....? Well the real key and iv in my code
are generated like this
Digest::SHA1.hexdigest("whatever").unpack('a2'*32).map{|x| x.hex}.pack
('c'*32)
Now I DID pick this up from the net so im not completely sure what
this does either.
I would appreciate it if you could establish the basics that I need to
know here.
Ive been trying to find relevant ROR specific documentation for the
OpenSSL gem but none that are understandable so far. Will look for
'applied cryptography'.
Thanks for the response.
Post by Michael Graff
I'm going to seem rude probably, but it's still true.
You are dabbling in crypto and you don't know what you're doing.
Stop, and find someone who does.
From what I read, you're trying to encrypt credit card data.  Before
you leak all the data from your database by using the _current time_
-- one of the weakest possible keys and IV values out there -- talk to
someone, hire a consultant, or at least read 'applied cryptography.'
Post by Ram
AESCrypt.encrypt("this", "X" * 32, "I" * 32)
=> "this"
Your code works.  Your lack of understanding about the algorithm you
are using, the meaning of a key in that context, how to securely
generate one, and how important a secure IV is, has bitten you.
Storing the key, IV, and encrypted data in a database is exactly the
same as storing the unencrypted data.  It will stop casual browsing.
If that is what you are trying to do, there are far easier methods,
such as converting the whole thing into base64 or hex or something.
If you believe your code actually adds security...
--Michael
Post by Ram
I just want to encrypt a string submitted through a form before saving
it to the DB. And then decrypt it again when I need to retrieve and
use it.
Im trying to use the OpenSSL::Cipher library. I have the following
module for encryption/decryption
[code]
require 'openssl'
module AESCrypt
 # Decrypts a block of data (encrypted_data) given an encryption key
 # and an initialization vector (iv).  Keys, iv's, and the data
 # returned are all binary strings.  Cipher_type should be
 # "AES-256-CBC", "AES-256-ECB", or any of the cipher types
 # supported by OpenSSL.  Pass nil for the iv if the encryption type
 # doesn't use iv's (like ECB).
 #:return: => String
 #:arg: encrypted_data => String
 #:arg: key => String
 #:arg: iv => String
 #:arg: cipher_type => String
 def AESCrypt.decrypt(encrypted_data, key, iv, cipher_type="aes-256-
cbc")
   aes = OpenSSL::Cipher::Cipher.new(cipher_type)
   aes.decrypt
   aes.key = key
   aes.iv = iv if iv != nil
   aes.update(encrypted_data) + aes.final
 end
 # Encrypts a block of data given an encryption key and an
 # initialization vector (iv).  Keys, iv's, and the data returned
 # are all binary strings.  Cipher_type should be "AES-256-CBC",
 # "AES-256-ECB", or any of the cipher types supported by OpenSSL.
 # Pass nil for the iv if the encryption type doesn't use iv's (like
 # ECB).
 #:return: => String
 #:arg: data => String
 #:arg: key => String
 #:arg: iv => String
 #:arg: cipher_type => String
 def AESCrypt.encrypt(data, key, iv, cipher_type="aes-256-cbc")
   aes = OpenSSL::Cipher::Cipher.new(cipher_type)
   aes.encrypt
   aes.key = key
   aes.iv = iv if iv != nil
   aes.update(data) + aes.final
 end
end
[/code]
And here is the model code where I encrypt and decrypt the string.
[code]
 def encrypt_cc_pass
   return if cc_pass.blank?
   self.cc_pass_key = Time.now.to_s
   self.cc_pass_iv = Date.today.to_s
   self.encrypted_cc_pass = AESCrypt.encrypt(cc_pass, cc_pass_key,
cc_pass_iv)
 end
 def decrypted_cc_pass
   AESCrypt.decrypt(encrypted_cc_pass, cc_pass_key, cc_pass_iv)
 end
[/code]
And this is the error I get
wrong final block length in:config/initializers/aes_crypt.rb:20:in
`final'
Anyone know what im doing wrong here?
Also, Im not able to understand the inners of encryption here. Is
there any gem with good documentation or simpler usage?
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
To post to this group, send email to rubyonrails-talk-/***@public.gmane.org
To unsubscribe from this group, send email to rubyonrails-talk+***@googlegroups.com
For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en
-~----------~----~----~----~------~----~------~--~---
Michael Graff
2009-02-26 13:04:46 UTC
Permalink
Storing the key at all where someone can get to is insecure. You
really need to question if you should store CC info at all. What
purpose do you need to store it for? If recurring charges, most
processing centers will allow you to schedule that sort of thing and
not have to store the CC info locally. If logging, can you perhaps
store only the last few digits of the card?

If you are storing it "just in case" but don't expect to use it, I
would use a public key system, such as RSA. In RSA, you keep one of
the keys (the public one) on the server, and it encrypts data. To get
it out, you need the private key. People can hack away but so long as
they don't have the private key, they cannot read your data. (more
hand waving here, it IS possible, but we're entering into the world of
theoretical quantum computing here.)

The numerous times I've had to handle CC data I was explicitly
forbidden to store the numbers (card, expiry date, or CCV) other than
the last 6 digits of the card. I could store anything returned from
the processor though, like auth numbers, status codes, etc. This was
in all our cases sufficient to reverse charges (if needed) or to bill
in a recurring manner.

As for the examples, I think your "irb" is hiding data from you. Try
something like:

x = AESCrypt.encrypt(...)
AESCrypt.decrypt(x, ...)

I think your output is the same as mine, you just have ? marks where I
have some \301 escaped characters.

--Michael

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
To post to this group, send email to rubyonrails-talk-/***@public.gmane.org
To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/***@public.gmane.org
For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en
-~----------~----~----~----~------~----~------~--~---

Loading...