> 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