Reputation: 337
Ok, I'm using a raw SHA1 hash to seed a Mersenne Twister pseudo-random number generator the generator gives me the option to seed either with an unsigned long or a array of unsigned longs
the SHA1 class I'm using gives me the hash as a 20 byte array of unsigned chars
I figured I could recast this array of chars to an array of longs to get a working seed but how can I know how long the resulting array of longs is?
example code:
CSHA1 sha1;
sha1.Update((unsigned char*)key, size_key);
sha1.Final();
unsigned char* hash;
sha1.GetHash(hash);
// Seed the random with the key
MTRand mt((unsigned long*)hash, <size of array of longs>);
I'm hoping that there is no data loss (as in no bytes are dropped off) as I need this to remain cryptography secure
Upvotes: 0
Views: 1157
Reputation: 46981
Your library seems to assume 32-bit unsigned long
s, so there's no [more] harm in you doing the same. In fact, I'd go as far to assume 8-bit unsigned char
s and perhaps even unpadded, little-endian representations for both. So you could use a simple cast (though I'd use a reinterpret_cast
), or maybe @Gene's memcpy
sample for alignment.
Portable code*, however, should use <cstdint>
, the uint#_t
types therein and piecewise, by-value copying for conversion:
uint32_t littleEndianInt8sToInt32(uint8_t bytes[4]) {
return bytes[0] | (bytes[1] << 8) | (bytes[2] << 16) | (bytes[3] << 24);
}
...and better names. Sorry, it's getting late here :)
*: Though, of course, stdint
itself isn't very portable (>= C++11) and the exact-width types aren't guaranteed to be in it. Ironic.
Upvotes: 0
Reputation: 46990
You can say
sizeof(unsigned long) / sizeof(unsigned char)
to get the number of octets in a long.
However there are two potential problems with simply casting.
First, the array of chars might not be properly aligned. On some processors this can cause a trap. On others it just slows execution.
Second, you're asking for byte order problems if the program must work the same way on different architecutures.
You can solve both problems by copying the bytes into an array of longs explicitly. Untested code:
const int bytes_per_long = sizeof(unsigned long) / sizeof(unsigned char);
unsigned long hash_copy[key_length_in_bytes / bytes_per_long];
int i_hash = 0;
for (int i_copy = 0; i_copy < sizeof hash_copy / sizeof hash_copy[0]; i_copy++) {
unsigned long b = 0;
for (int i_byte = 0; i_byte < bytes_per_long; i_byte++)
b = (b << 8) | hash[i_hash++];
hash_copy[i_copy] = b;
}
// Now use hash_copy.
Upvotes: 1
Reputation: 185731
You can use len_of_chars * sizeof(char) / sizeof(long)
, where len_of_chars
is presumably 20.
Upvotes: 1