> From: owner-openssl-us...@openssl.org On Behalf Of pkumarn > Sent: Thursday, 15 March, 2012 14:18 > To: openssl-users@openssl.org > Subject: Need help on using RAND_bytes()
Aside: your message is not very clear but it appears your problem is really C programming in general, not RAND_bytes or even OpenSSL in particular. > I am using RAND_bytes() to generate 32 byte random number > (code snippet > below). From here what i see if when access alt_value[0] it > gives me "b2". > So basically these array has got 64 bytes. > > unsigned char salt_value[33]; > RAND_bytes(salt_value, 32); Aside: always check the return from RAND_bytes before using it. It can sometimes fail, and cryptosystems that use data which is intended to be random but actually isn't random get broken. > sample o/p: > b2ee922055a3adc17fdd5980db39ad343f73cb0ecca0b92dd8af6e2f4ef433c1 > Output how? That looks like hex, but no single output operation in C will produce hex for an array of unsigned char. > unsigned char temp_salt[32]; > > Now i need to copy these into different array of 32 bytes and > when i do that > only 32 bytes are copied and when i access temp_salt[0], i get "b" ; > temp_salt[1] = "2" and so on... > Copy how? You can copy any C object (i.e. data in memory) as bytes with memcpy. Make sure you get the size right, and in particular don't copy more data into an object than the size of that object; that causes bugs which may or may not be recognized and sometimes security breaches. You can copy scalars with assignment, and since here you have two arrays with the same element type, you could just do for( i = 0; i < 32; i++ ) b [i] = a [i]; where i is in scope as a suitable integer type, or in C99 (or C++) you can declare i local to the loop for( int i = 0; i < 32; i++ ) b [i] = a[i]; In general it's better to avoid magic numbers in code and instead use sizeof the object and/or a #define'd macro, but to keep this example simple I didn't, especially since you declared temp_salt [33] not [32] for no obvious reason. For an array which is or may be very large, use size_t or unsigned long (or C99 unsigned long long) to avoid overflow. You can copy a struct (or union, or in C++ a class with the default assignment operator) with assignment, and that struct can contain an array (of fixed size; in C99 you can have a variable length 'suffix' to a struct called FAM = Flexible Array Member, but it isn't included in sizeof and isn't included in assignment). If you instead WANT to convert byte values to hex, or back, you can do each byte with [sf]printf with %02x or %02X format and [sf]scanf with %2x or %2X or strtol with radix=16 on a null-terminated copy or extract; or just do the nibbles as hex digits individually like for( i = 0; i < 32; i++ ){ a[i*2+0] = hexdigits [b[i] >> 4]; // on rare systems with byte more than 8 bits would need & 0xF // but on those systems you don't want 2-char hex anyway a[i*2+1] = hexdigits [b[i] & 0xF]; } and similarly for input but you often need to add error handling. > I also tried copying salt_value to a file and then read it > back but again > when i use fgets() to read 32 bytes, it runs into same problem... > fgets() is designed for newline-terminated lines. Random or otherwise arbitrary data can contain bytes which happen to be newlines, and make fgets() wrong. Also fgets() doesn't return the length read, so you normally reconstruct it with strlen(), and that doesn't work if the binary data includes bytes which happen to be nulls. Moreover, standard C defines two types of files (or technically streams to files): text and binary. Binary files can store and read back all bytes, but text files are only required to work for the characters supported by the implementation. On Unix these file types are the same, but on other systems they may not be; in particular on Windows text files usually write C newline as two bytes CR LF, but read those two bytes back as one newline and may discard lone CR. For binary data use fwrite and fread (or [f]putc and [f]getc loops) on a binary file/stream. (Note stdout stderr stdin are text streams by default, and only in C99 is there a portable way of changing that, although C90 implementations where the difference matters often have a nonportable way.) Or if you need to store or transmit binary data in something that is otherwise text format, like an email or UI display, you need to convert it to hex and back as above, or some other character-based format. Base64 as defined by PEM is very popular, especially in some of the crypto functions OpenSSL supports like SMIME; the older base64 from UUCP also works; and I've seen base32 and base94/95 used. ______________________________________________________________________ OpenSSL Project http://www.openssl.org User Support Mailing List openssl-users@openssl.org Automated List Manager majord...@openssl.org