> 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

Reply via email to