(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

On Thu, Feb 26, 2009 at 5:37 AM, Ram <[email protected]> wrote:
>
> 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.
>
> On Feb 26, 4:16 pm, Michael Graff <[email protected]> wrote:
>> 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)
>>
>> => "\223\...@\233\323d\254u9]\241\351\031m\301\352">> 
>> AESCrypt.decrypt("\223\...@\233\323d\254u9]\241\351\031m\301\352", "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
>>
>> On Thu, Feb 26, 2009 at 12:34 AM, Ram <[email protected]> wrote:
>>
>> > 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 [email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at 
http://groups.google.com/group/rubyonrails-talk?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to