From: T P Date: 2012-06-11T09:43:20+09:00 Subject: Re: OpenSSL: Determining initialization vector (IV) created using OpenSSL::Cipher::Cipher#pkcs5_keyivgen with one argument --e89a8f3ba30d9be00204c2279c73 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Hi Martin, On Sun, Jun 10, 2012 at 5:48 PM, Martin Bo=DFlet < martin.bosslet@googlemail.com> wrote: > > salt is initialized as null, but later set in the line > > > salt =3D (unsigned char *)RSTRING_PTR(vsalt); > > The Ruby String vsalt's value is assigned to salt there. > > Except I believe that is inside the if block that checks whether or not vsalt was passed in or not: if(!NIL_P(vsalt)){ ... } So that wouldn't get set, I believe. I should have explained my reasoning in the original message to be clear. Maybe that isn't what NIL_P is doing though or that when an argument isn't passed in it gets a non NULL value? Perhaps NIL (in Ruby/C API) and NULL (in C) are different? I probably should have also mentioned that the actual call in encrypted_strings gem that we indirectly call is: cipher.pkcs5_keyivgen(password), only one argument is passed in. > > (b) at some point I would love to learn how to debug this myself. i.e. > setup > > my environment to trace the C code in the Ruby MRI runtime so I can fis= h > for > > myself next time. > > You may simply use gdb or if you prefer some comfort, I frequently use Netbeans to debug > Ruby C code. > > > If the salt variable is NULL then what is the IV used in this case? I > need > > th IV for the Scala code otherwise I cannot decrypt what the Ruby code = is > > encrypting. Also I found a highly related StackOverflow question on thi= s > > [2], but the solution involves not using pkcs5_keyivgen method at all a= nd > > setting a known random IV on the OpenSSL::Cipher::Cipher object so it > > doesn't answer my question sadly as I am not in a position to do this > > migration yet. > > You shouldn't require the actual key and IV used to do password-based > encryption. What you would normally do on the receiving end is to go > through the same steps as you did when encrypting the initial message, > using the same password, salt and iterations that the encrypting party > used. In Java, this would look something like > > ----- start source > > //These three need to be exactly the same as the ones used in Ruby > char[] password =3D ... > byte[] salt =3D ... > int count =3D ... > > PBEParamterSpec params =3D new PBEParameterSpec(salt, count); > PBEKeySpec keySpec =3D new PBEKeySpec(password); > SecretKeyFactory keyFac =3D SecretKeyFactory.getInstance("PBEWithMD5AndDE= S"); > SecretKey key =3D keyFac.generateSecret(keySpec); > Cipher cipher =3D Cipher.getInstance("PBEWithMD5AndDES"); > pbeCipher.init(Cipher.DECRYPT_MODE, key, params); > //now decrypt > > ----- end source > > Figuring out what the key and iv are that were generated would sort of > defeat the purpose of password-based encryption. Although not > impossible, it would definitely result in a lot more work. > > For your migration to using PBKDF2, I just added some notes on > how to use it yesterday [1]. I also gave an example on SO how we > did similar upgrading of password schemes in the past [2]. It talks > about moving from MD5 to bcrypt but applies to arbitrary algorithms. > I hope this still helps you in the process! > Thanks, I will definitely use that for reference in our longer-term plans. Great idea with the two concurrent values! I think I figured out a workaround anyway for the short-term deliverable that can't wait for a migration path like that in the meantime. Testing now and will post if successful. Thanks! :) --e89a8f3ba30d9be00204c2279c73 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable
Hi Martin,

On Sun, Jun 10, 2012 at= 5:48 PM, Martin Bo=DFlet <martin.bosslet@googlemail.com&g= t; wrote:

salt is initialized as null, but later set in the line

=A0
=
=A0salt =3D (unsigned char *)RSTRING_PTR(vsalt);=A0
=

The Ruby String vsalt's value is assigned to salt there.

Except I believe that is insi= de the if block that checks whether or not vsalt was passed in or not:
=A0
if(!NIL_P(vsalt)){
...
}

So that wouldn't get set, I believe. I should have expla= ined my reasoning in the original message to be clear. Maybe that isn't= what NIL_P is doing though or that when an argument isn't passed in it= gets a non NULL value? Perhaps NIL (in Ruby/C API) and NULL (in C) are dif= ferent?

I probably should have also mentioned that the actual c= all in encrypted_strings gem that we indirectly call is: cipher.pkcs5_keyiv= gen(password), only one argument is passed in.
=A0
> (b) at some point I would love to learn how to debug this myself. i.e.= setup
> my environment to trace the C code in the Ruby MRI runtime so I can fi= sh for
> myself next time.

=A0
You may simply use gdb= or if you prefer some comfort, I frequently use=A0
Netbeans to debug
Ruby C code.

> If the salt variable is NULL then what is the IV used in this case? I = need
> th IV for the Scala code otherwise I cannot decrypt what the Ruby code= is
> encrypting. Also I found a highly related StackOverflow question on th= is
> [2], but the solution involves not using pkcs5_keyivgen method at all = and
> setting a known random IV on the OpenSSL::Cipher::Cipher object so it<= br> > doesn't answer my question sadly as I am not in a position to do t= his
> migration yet.

You shouldn't require the actual key and IV used to do password-b= ased
encryption. What you would normally do on the receiving end is to go
through the same steps as you did when encrypting the initial message,
using the same password, salt and iterations that the encrypting party
used. In Java, this would look something like

----- start source

//These three need to be exactly the same as the ones used in Ruby
char[] password =3D ...
byte[] salt =3D ...
int count =3D ...

PBEParamterSpec params =3D new PBEParameterSpec(salt, count);
PBEKeySpec keySpec =3D new PBEKeySpec(password);
SecretKeyFactory keyFac =3D SecretKeyFactory.getInstance("PBEWithMD5An= dDES");
SecretKey key =3D keyFac.generateSecret(keySpec);
Cipher cipher =3D Cipher.getInstance("PBEWithMD5AndDES");
pbeCipher.init(Cipher.DECRYPT_MODE, key, params);
//now decrypt

----- end source

Figuring out what the key and iv are that were generated would sort of
defeat the purpose of password-based encryption. Although not
impossible, it would definitely result in a lot more work.

For your migration to using PBKDF2, I just added some notes on
how to use it yesterday [1]. I also gave an example on SO how we
did similar upgrading of password schemes in the past [2]. It talks
about moving from MD5 to bcrypt but applies to arbitrary algorithms.
I hope this still helps you in the process!

=
Thanks, I will definitely use that for reference in our longer-term pl= ans. Great idea with the two concurrent values!

I think I figured out a workaround anyway for the short-term deliverable th= at can't wait for a migration path like that in the meantime. Testing n= ow and will post if successful.

Thanks! :)
--e89a8f3ba30d9be00204c2279c73--