Seeding boost::mt19937 with bytes from CryptoGenRandom

I have a C++ program that uses /dev/urandom on Unix systems to seed
boost::mt19937. I'm porting the program to Windows. I can get good, random
seed data on Windows similar to random seed data produced from /dev/urandom
on Unix systems like so:
HCRYPTPROV hProvider = 0;
BYTE randomBytes[8];
CryptAcquireContext(&hProvider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
CryptGenRandom(hProvider, sizeof(randomBytes), randomBytes);
CryptReleaseContext(hProvider, 0);
However, I'm running into trouble attempting to pass these randomBytes to
boost::mt19937. On Unix I do something similar to this:
uint64_t GetSeed()
{
uint64_t seed;
std::ifstream urandom;
urandom.open("/dev/urandom");
urandom.read(reinterpret_cast

Steven,
at first this solution seemed to me pretty cool. As far as I understand seed
will contain some value from stack. The only question is how probable is it,
that seed is always initialized with a different value?
Thanks,
Ovanes
On Thu, Feb 11, 2010 at 5:58 AM, Steven Watanabe

AMDG Ovanes Markarian wrote:
I was assuming that the code I wrote was prefixed with HCRYPTPROV hProvider = 0; BYTE randomBytes[8]; CryptAcquireContext(&hProvider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); CryptGenRandom(hProvider, sizeof(randomBytes), randomBytes); CryptReleaseContext(hProvider, 0); The memcpy should copy from randomBytes into seed. (Assuming I haven't forgotten the signature of memcpy.) In Christ, Steven Watanabe

The memcpy should copy from randomBytes into seed. (Assuming I haven't forgotten the signature of memcpy.)
Seems, like I forgot the signature... Another way to transfer the bytes would be: union bytes2seed { uint64_t seed_; char bytes_[sizeof(uint64_t)]; }; bytes2seed converter; Now one can pass &converter.bytes_[0] to CryptGenRandom. This does not require an additional memcpy call. Ovanes.

Steven, I know at least 2 books which describe this possibility and there is nothing stated about undefined behavior. I just double checked the ISO 2003 C++ Standards and did not find anything which disallows the presented approach. Can you point me to the paragraph in the Standard? Thanks, Ovanes

AMDG Ovanes Markarian wrote:
I know at least 2 books which describe this possibility and there is nothing stated about undefined behavior.
Unfortunately this is a very common mistake even among those who ought to know better.
The usual aliasing rules apply with only one exception (listed in 9.5): [Note: one special guarantee is made in order to simplify the use of unions: If a POD-union contains several POD-structs that share a common initial sequence (9.2), and if an object of this POD-union type contains one of the POD-structs, it is permitted to inspect the common initial sequence of any of POD-struct members; see 9.2. ] In Christ, Steven Watanabe

On Thu, Feb 11, 2010 at 7:39 PM, Steven Watanabe
Yes I read the paragraph as well. But as far as I understand my use case is legal (assumed uint64_t is POD), which I think it is. Or am I mistaken? This is what 9.2 Clause 16 states (you have a snippet from 9.5 which just refers to that one): "If a POD-union contains two or more POD-structs that share a common initial sequence, and if the PODunion object currently contains one of these POD-structs, it is permitted to inspect the common initial part of any of them. Two POD-structs share a common initial sequence if corresponding members have layoutcompatible types (and, for bit-fields, the same widths) for a sequence of one or more initial members." I understand that that it is allowed to use union for byte conversions of POD types. Regards, Ovanes

AMDG Ovanes Markarian wrote:
Yes I read the paragraph as well. But as far as I understand my use case is legal (assumed uint64_t is POD), which I think it is. Or am I mistaken?
It's legal for char or unsigned char to alias any type, so it would probably actually be okay in this specific case.
"Common initial sequence" means something like struct { int x; double y; }; struct { int x; float y; }; int x is common to the two structs. You can't use a union to convert between arbitrary PODs. In Christ, Steven Watanabe

Thank you Steven. While I do not have boost installed on this computer, the
code below compiles and runs as I would expect. Upon each execution, the
value of seed changes. I expect boost::mt19937 rng(seed); will work. And now
I have a very good random seed thanks to your advice.
Your friend,
Ed
#include <iostream>
#include
participants (3)
-
e m
-
Ovanes Markarian
-
Steven Watanabe