ipfs / kubo

An IPFS implementation in Go
https://docs.ipfs.tech/how-to/command-line-quick-start/
Other
16.13k stars 3.01k forks source link

RSA key generation does not deplete entropy pool #911

Closed vitzli closed 9 years ago

vitzli commented 9 years ago

Maybe it's not a bug, but compared to gpg, IPFS: 1) generates 4096 bit key-pair too fast; 2) does not deplete entropy pool during key generation, it often happens with gpg. OS: Debian Jessie 32-bit, 512 MB RAM inside virtualbox VM; I'm checking available entropy via /proc/sys/kernel/random/entropy_avail, entropy drops a little (about 100 bits) but stays there, while gpg eats all available entropy (drops to 40 bits, process takes about 5 minutes and HDD activity is required to feed the pool). Here is the log, I combined entropy output, time, and ipfs generation into one file, long version at https://gist.github.com/vitzli/f6fa7338cbc2bf4eb553:

2015-03-10 08:04:15 994
2015-03-10 08:04:16 946
2015-03-10 08:04:16 Starting key generation
initializing ipfs node at /home/user/.go-ipfs
generating 4096-bit RSA keypair...2015-03-10 08:04:17 956
2015-03-10 08:04:18 957
2015-03-10 08:04:19 969
2015-03-10 08:04:20 970
...
2015-03-10 08:04:27 844
2015-03-10 08:04:28 844
...
2015-03-10 08:05:08 855
2015-03-10 08:05:09 862
...
2015-03-10 08:05:13 885
done
peer identity: QmcuSFxTqgxA7QGbDWXk7Bu5qUiogxJoPfPp8EQSnfpM4j
to get started, enter:

    ipfs cat /ipfs/QmV9E5oNhFDWeRV8NQ91G7vp3pvff2S4UYkn89T5koSzqo/readme

2015-03-10 08:05:14 895
2015-03-10 08:05:15 909
2015-03-10 08:05:16 855
2015-03-10 08:05:17 859

real    1m1.220s
user    0m26.560s
sys 0m31.596s
2015-03-10 08:05:18 Key generation ended
2015-03-10 08:05:18 864
2015-03-10 08:05:19 879
jbenet commented 9 years ago

@vitzli great find! as mentioned in the security notes, our state of crypto is very far from secure right now-- we need to make a long list of things to check (and eventually have an independent audit of the whole thing).

If you'd like to make a document ./dev/crypto-notes.md with an Important Notes section, and mention this there, that would be great

vitzli commented 9 years ago

This issue seems to be caused by crypto/rand implementation in the Go programming language:

  1. in UNIX-like operating system it uses /dev/urandom device:

    // Easy implementation: read from /dev/urandom.
    // This is sufficient on Linux, OS X, and FreeBSD.

    For OS X that would use 160-bit Yarrow PRNG based on SHA-1 key, for FreeBSD - 256-bit Yarrow algorithm. For both operating systems /dev/random and /dev/urandom are equal.

  2. in Linux it falls back to urandom in several cases:

    // Test whether we should use the system call or /dev/urandom.
    // We'll fall back to urandom if:
    // - the kernel is too old (before 3.17)
    // - the machine has no entropy available (early boot + no hardware
    //   entropy source?) and we want to avoid blocking later.

    The first clause would be used for several production-class operationg systems.

  3. in Windows it uses Windows CryptGenRandom API.

It seems that there is a consensus that using /dev/urandom instead of /dev/random is safe:

  1. Wikipedia on /dev/random
  2. Security.stackexchange.com
  3. Myths about /dev/urandom

BUT:www.gossamer-threads.com on large entropy consumption:

Why does gpg use so much entropy from /dev/random? … 1) If you don't do anything special then two keys are generated (mainkey and subkey). … So we see: If high quality entropy is required then gpg reads (128+128+44)/16=18.75 times as much entropy from /dev/random as demanded.


Which /dev/random - there are hundreds of variants of that device all with other glitches. Thus GnuPG has always used /dev/random only as a source of entropy to seed its own RNG:

This random number generator is loosely modelled after the one described in Peter Gutmann's paper: "Software Generation of Practically Strong Random Numbers".@footnote{Also described in chapter 6 of his book "Cryptographic Security Architecture", New York, 2004, ISBN 0-387-95387-6.}

A pool of 600 bytes is used and mixed using the core RIPE-MD160 hash transform function. Several extra features are used to make the robust against a wide variety of attacks and to protect against failures of subsystems. The state of the generator may be saved to a file and initially seed form a file.

Depending on how Libgcrypt was build the generator is able to select the best working entropy gathering module. It makes use of the slow and fast collection methods and requires the pool to initially seeded form the slow gatherer or a seed file. An entropy estimation is used to mix in enough data from the gather modules before returning the actual random output. Process fork detection and protection is implemented.

GPG uses ~/.gnupg/random_seed but it needs to creater it first. For generating keys it also makes sure to put in a lot of new entropy just to be safe. Better be safe than sorry (cf. the recent NetBSD problem). Salam-Shalom, Werner