Thanks a lot Dave for pointing out few things which i need to take care. By
the way as this is not complete code, original code already has taken care
of few things.

Now coming to the original question, how do i make sure
PKCS5_PBKDF2_HMAC_SHA1() is generating the correct result of my i/p data? 
When i input RAND_bytes() data into PKCS5_PBKDF2_HMAC_SHA1(), i get a
different result but when the same is converted to ASCII (human readable
format), i get a different result. ... 

Any thoughts on this?




Dave Thompson-5 wrote:
> 
>> From: owner-openssl-us...@openssl.org On Behalf Of pkumarn
>> Sent: Monday, 19 March, 2012 03:06
> 
>> I am trying to use PKCS5_PBKDF2_HMAC_SHA1() and below is my 
>> sample program.
>> I wanted to make sure if my result of 
>> PKCS5_PBKDF2_HMAC_SHA1() is correct so
>> i verified the same with the below wesbite 
>> http://anandam.name/pbkdf2/ and i
>> see a different result... Am i using the API correctly?
>> I am having doubts if i am passing salt value correctly...
>> 
> That site is Javascript which treats the salt (and password) 
> directly as data. I don't know if or how browser(s) can 
> reliably enter data other than printable ASCII in a <form>; 
> it may very well depend on browser and locale settings.
> For simplicity if you want to interoperate with this PBKDF2 
> implementation I would therefore limit both salt and password 
> to printable ASCII 0x20-0x7E. (32 chars of salt, even restricted 
> to 5 or 6 bits entropy each, is far more than needed, especially 
> if you are deriving a 40-bit key as your code indicates.)
> 
>> #include <stdio.h>
>> #include <openssl/rand.h>
>> #include <types.h>
>> #include <string.h>
>> #include <stdio.h>
>> #include <string.h>
>> #include <stdlib.h>
>> 
>> #include <malloc.h>
>> 
>> #include <openssl/hmac.h>
>> #include <openssl/evp.h>
>> #include <openssl/engine.h>
>> #include <openssl/aes.h>
>> 
> Asides: malloc.h is not standard or portable; standardly 
> malloc() and related functions are in stdlib.h.
> types.h is not standard C (though sys/types.h is POSIX).
> Repeating string.h is clutter and may waste time.
> I would group openssl/rand.h with the other openssl/*.
> 
>> #include <proto.h>
>> #define KEY_LEN    32// 32 bytes - 256 bits
>> #define KEK_KEY_LEN   5
>> #define ITERATION   1000
>> 
>> //unsigned char salt_value[32]={"5d85947b4292ea6463faf6893451232"}; 
>> unsigned char salt_value[KEY_LEN];
>> unsigned char AESkey[KEY_LEN];
>> unsigned char XTSkey[KEY_LEN];
>> u8 fuse_key[KEY_LEN];
>> 
> Aside: using KEY_LEN as the length of the salt (which is not a key 
> of any kind) is somewhat confusing; suggest SALT_LEN instead.
> KEK_KEY_LEN is redundant, like "CPU unit"; suggest KEK_LEN.
>> 
>> void main()
> 
> main returning void is not standard and never has been, 
> and has no advantage whatsoever over the standard, int.
> 
>> {
>>    
>>     s32 i=0;
>>     s32 len =0;
>>      u8 *out;
>>     u8 *rspHMAC;
>>      const s8 pwd[] = "test";
>>      s8 rspPKCS5[KEK_KEY_LEN * 2];
>>      s32 ret;
>>       
> Note: these types are not standard or portable. C99 
> (still not implemented everywhere, even though C11 has 
> just come out) *may* have types of the form int8_t etc.
> However, below you treat pwd and rspPKCS5 below as arrays 
> of 'plain' char. 'Plain' char is unsigned on some systems, 
> so you would either have to make 's8' unsigned which is 
> confusing and likely to lead to bugs, or leave s8 signed 
> but convert all your accesses to be unsigned, which is 
> a good deal of extra work and easy to get wrong.
> 
>>      rspHMAC = (unsigned char *) malloc(sizeof(char) * KEY_LEN);
>>     out = (unsigned char *) malloc(sizeof(char) * KEK_KEY_LEN);
>>      
> The return from malloc never needs to be cast in valid C; in C++ 
> it does but in C++ you generally shouldn't use malloc at all.
> For these small fixed sizes, dynamic allocation is a waste of 
> effort and clutter. sizeof(char) is always 1 so it isn't needed, 
> although if you consistently follow the pattern of N*sizeof(E) 
> for all types it doesn't hurt to be consistent here.
> 
>>     RAND_bytes(salt_value, KEY_LEN);
>> 
>>      
>>     printf("\n salt_value[0] = %x; salt_value[31]= %x", salt_value[0],
>> salt_value[31]);
>>     printf("\n strlen(salt_value) = %d; sizeof(salt_value) = %d\n",
>> strlen(salt_value), sizeof(salt_value));
>>      //printf("\n salt_value = %s", salt_value);
>>      
> As I said before, RAND_bytes generates random bytes, 
> which can include null and then strlen() is too low;
> while your buffer didn't include a null terminator (nor room 
> for one) so in general strlen() could be too high -- although 
> here salt_value is file-scope static and very likely to be 
> followed in memory by the next file-scope static here AESkey 
> which appears to be unused and thus still zero, although some 
> implementations may follow salt_value by the next _referenced_ 
> external static and that may well contain nonnull bytes.
> 
> If you want a constant length, use a constant for length.
> If you want variable length, determine it and remember it.
> 
> But as above if you want to interoperate with the Javascript 
> on that website, it's probably easiest to limit yourself to 
> bytes which are printable ASCII characters. The simplest way 
> is just use columns 4 and 5 (0x40-0x5F). For that do:
>   if( RAND_bytes (salt_value,N) <= 0 ) /* ERROR! */
>   for( i = 0; i < N; i ++ ) 
>     salt_value[i] = (salt_value[i] & 0x1F) | 0x40; 
>     // parens redundant but shown for clarity
> As above, 32 chars of 5 bits entropy is more than needed 
> for security; 50-100 bits (10-20 x 5) is usually plenty 
> and usually more than the actual strength of the password.
> 
>>     for(i = 0; i < KEY_LEN; i++) {
>>         printf("%02x", salt_value[i]);
>>        
> Here you correctly use the constant length KEY_LEN, 
> to convert to hex. But for the Javascript above, 
> you don't want hex, you want actual bytes.
> 
>>      }
>> 
>>      ret = PKCS5_PBKDF2_HMAC_SHA1(pwd, strlen(pwd), salt_value,
>> strlen(salt_value), ITERATION, KEK_KEY_LEN, out);
>>     printf("\n PKCS#5 :");
>> 
> As above for strlen(salt_value). strlen(pwd) is okay 
> given you chose pwd to be valid C string (and further 
> a string of printable ASCII, good for that Javascript).
> In real use the password should not be hardcoded, nor 
> a single dictionary word or other easily guessable value; 
> I assume this code is just an example.
> 
>>     for(len = 0; len < KEK_KEY_LEN; len++){
>>         printf("%02x", out[len]);
>>        /* o/p of PKCS5 is stored in buf "out". This cannot be 
>> used directly
>> as each out[len] will have 2 char
>>        but for key gen, we need to consider each char of out 
>> as a value. -
>> Needs sentence reframing
>>          */
>>         sprintf(&rspPKCS5[len * 2], "%02x", out[len]);
>>    }
>> 
> This is unsafe as written. You KEK_KEY_LEN=5 bytes into 
> rspPKCS5[KEK_KEY_LEN*2] as two hex chars each, _plus 
> a null terminator_. Increase it by 1 (at least).
> 
>>      printf("\n");
>> }
>> 
>> Sample O/P:
>> 
>> salt_value[0] = e2; salt_value[31]= 12
>>  strlen(salt_value) = 32; sizeof(salt_value) = 32
>> e258017933f3e629a4166cece78f3162a3b0b7edb2e94c93d76fe6c38198ea12
>>  PKCS#5 :7d7ec9f411
>> 
>> Website result:
>> The derived 40-bit key is: a5caf6a0d3
>> 
>> 
>> 
> 
> ______________________________________________________________________
> OpenSSL Project                                 http://www.openssl.org
> User Support Mailing List                    openssl-users@openssl.org
> Automated List Manager                           majord...@openssl.org
> 
> 

-- 
View this message in context: 
http://old.nabble.com/How-to-use-PKCS5_PBKDF2_HMAC_SHA1%28%29-tp33529423p33536514.html
Sent from the OpenSSL - User mailing list archive at Nabble.com.

______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
User Support Mailing List                    openssl-users@openssl.org
Automated List Manager                           majord...@openssl.org

Reply via email to