Hacker News new | ask | show | jobs
by mike-cardwell 4442 days ago
Interestingly enough, I have actually been working on writing a DNS client library in C++ with Boost ASIO this very afternoon. I was going to get my source of random data using the following C++11 standard library code. I would really appreciate any comments from people here if there is anything wrong with what I'm doing:

  #include <random>
  std::uniform_int_distribution<uint32_t> dist;

  // Seed a Mersenne twister PRNG with random data:
  std::mt19937 eng;
  std::random_device rd;
  eng.seed(dist(rd));

  // Now to generate random numbers, simply:
  uint32_t random_number = dist(eng);
2 comments

I don't know what DNS uses the randomness for, but if a malicious attacker can gain from guessing the randomness, don't use MT, as the state can be extracted from MT by observing a relatively small number of outputs.
Ah. You appear to be right. I'm glad I asked now.

[edit] I'm going to skip using the Mersenne twister engine and just use std::random_device for all random data, instead of as a seed. It seems on Linux at least that random_device is basically /dev/urandom. I assume the source will be sane on other OS's too.

The C++ standard gives little guarantees for the quality of std::random_device. As I remember, MinGW on Windows uses the Mersenne Twister with a hardcoded seed for it.

boost::random_device, on the other hand, has better guarantees: it is only implemented where there's a decent entropy source.

Thanks for the info. Seeing as I'm already using boost, that sounds very useful.
Please don't do this. This exact approach is what caused the problems described in the article.

If you need secure random numbers, do what you had above (though in light of other comments, perhaps consider a different algo besides MT).

This is a recommendation that says that a developer should actually consider using the Mersenne Twister for secure random numbers to avoid a potential performance problem.
I believe you would use it to determine a random outgoing port to use to contact the DNS server; this prevents spoofing. However, the port space is only 16-bits, so how you map the outputs of the MT into that space would have the biggest impact -- but you're right that's it's probably best to avoid it entirely.
You also use it for randomising the 16 bit ID in the request packet, and you can use it for randomly capitalizing letters in the qname (0x20 bit encoding). Both of these to help protect against spoofing.

    std::random_device rd;
    std::mt19937 rng(rd()); //Construct with random seed. 
    uint32_t random_number = dist(rng);
Since only the seed value comes from `rd` you should be fine if you suspected the results from the article would affect you. What was most likely happening in the article was constant use of `rd` without a prng.