3

I swear, this seems to be changing every time I check the MSDN documentation. When I coded my executable Microsoft was suggesting to use RtlGenRandom API to generate cryptographically strong random numbers.

Now when I'm checking documentation for RtlGenRandom, the note there suggests using CryptGenRandom instead. But then another note for CryptGenRandom states this:

Important: This API is deprecated. New and existing software should start using Cryptography Next Generation APIs. Microsoft may remove this API in future releases.

So can someone show an example in C of how to use those "Cryptography Next Generation APIs" to generate a byte array of random numbers that Microsoft recommends now?

5
  • 1
    There's 3 examples here: msdn.microsoft.com/en-us/library/windows/desktop/… Did you try them out? Commented Feb 20, 2018 at 0:02
  • 1
    BCryptGenRandom Commented Feb 20, 2018 at 0:03
  • @RetiredNinja: Did you? Commented Feb 20, 2018 at 0:27
  • @RbMm: Very nice. Thank you. I guess doing BCryptGenRandom(NULL, buffer, sizeof(buffer), BCRYPT_USE_SYSTEM_PREFERRED_RNG); would be the way now. hah? It doesn't say anything about its cryptographic strength though. Commented Feb 20, 2018 at 0:29
  • Lol... I know what you mean. It only gets worse when you start working on Microsoft's mobile and phone platforms. Also see Random numbers for Windows Phone 8 and Windows Store 8? Commented Feb 22, 2018 at 3:43

1 Answer 1

10

It does not really matter, on Windows XP and later the default providers end up calling the same function. The RNG on 2000 and unpatched XP mainly use SHA1+RC4 internally and it has some security issues.

I just did some experiments on Windows 8 and this is what I found:

  • RtlGenRandom (AKA advapi32!SystemFunction036) calls CRYPTBASE!SystemFunction036 >>> bcryptPrimitives!ProcessPrng >>> bcryptPrimitives!AesRNG*.
  • CryptGenRandom calls CRYPTSP!CryptGenRandom >>> %provider%!CPGenRandom >>> CRYPTBASE!SystemFunction036. %provider% was rsaenh or dssenh in my tests but could possibly be a different implementation if you specifically ask for a 3rd-party provider.
  • BCryptGenRandom calls bcryptPrimitives!MSCryptGenRandom >>> bcryptPrimitives!GenRandomAes >>> bcryptPrimitives!AesRNG* with the BCRYPT_RNG_ALGORITHM CNG Algorithm Identifier (BCRYPT_RNG_DUAL_EC_ALGORITHM ends up in bcryptPrimitives!GenRandomDualEcc instead).

This is of course undocumented implementation details that could change but I don't really think you need to worry about which function you pick. If your target is Vista+ you can use BCrypt. CryptGenRandom will never be removed, it would break too many applications and you should pick it if you support < Vista.

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks for sharing your research. My implementation is basically LoadLibrary()+GetProcAddr() for newer APIs, otherwise fallback to XP ones. Hmm, interesting. I wish Microsoft documented how exactly they're using AES to generate random numbers.
A good encryption algorithm produces cipher text "indistinguishable from random noise". The entropy pool in the old implementation is filled with data from sources listed in a comment @ blogs.msdn.microsoft.com/michael_howard/2005/01/14/… The AES implementation might use similar sources for its key & data, I did not really care so I did not step that deep into the implementation.
What bugs me the most about Microsoft implementation of crypto is that they treat it as some sort of a black box, coupled with a bunch of confusing and contradicting documentation. And the only way we can know what they're doing is by reversing it. So yeah, I appreciate your efforts! As for that link you gave from 2005, idk, man. It's an awful old for crypto. I'm sure in 2005 most of software on the market was stiff "satisfied" with calling C's rand() as a PRNG.
I also tried reading all the docs from their suggested CNG APIs, and idk. I think I'll stick with Intel's hardware-based RDRAND and RDSEED where supported. There's more and more CPUs these days that will have support for it. It involves writing some asm code but it's worth it. Otherwise, possibly a fallback to the PRNG from a library, such as Crypto++. Otherwise WinAPIs for the sake of crypto -- still suck. Even on Win10.
crypto.stackexchange.com/questions/10486/… both answers there answer that the RNG is SP800-90 AES-CTR-DRBG

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.