Pseudo Random Number Generator and Bitcoin

I’ve stumbled upon two implementations of bitcoin libraries that generate new bitcoin addresses based on a secret. To generate that secret, the first one is using time as seed to srand(), the second one is using its own random generator which is not cryptographically secure (it’s open source, so quite easy to reverse engineer it and get the full set of generated secrets). I contacted the authors of these libraries in the hope they’ll fix that. An attacker could easily find some (or all) valid private keys these libraries generated.

Reminder: on your computer time is discrete. Using srand(time(0)) is very common, and if you’re using it for your new procedural generated game, it’s good enough, but when it comes to generate bitcoin addresses: be careful. Example:

srand(time(0));
int secret = rand();
char *address = bitcoin_address(secret);

In that case, time(0) is very discrete since it only has a one second resolution. Say that code has been published on January 1st, 2011. You can list all private keys generated by that code until today:

int january_1_2011 = 1293840000;
for (int i = january_1_2011; i < time(0); i++) {
  srand(i);
  int secret = rand();
  char *address = bitcoin_address(secret);
}

That’s only 146 927 544 keys (number of seconds from January 1st, 2011 to today), millions of bitcoin private keys can be easily tested and money transferred to the attacker.

So if you ever have to use a random function when you work on a Bitcoin project:

  • Make sure you understand PRNGs.
  • Never use default language implementation of random – they’re never cryptographically secure.
  • Never trust the OS.
  • Make sure to seed with high resolution data (and search for “Entropy Gathering”) if you ever have to seed yourself.