Misc #17319
closedRename Random.urandom to os_random and document random data sources
Description
SecureRandom gets randomness from Random.urandom
, which is a confusing name because urandom
only uses /dev/urandom in some circumstances. On reading the secure_random.rb
code this morning I got very confused how it was supporting "win32" for example, because it appears to only use openssl and /dev/urandom.
I have renamed urandom
to os_random
. With this change, it is much more obvious from reading secure_random.rb
what is happening, in my opinion.
I have also added urandom
as an alias to os_random
so this is not a breaking change. I am not 100% sure I documented this alias correctly.
I have also updated the documentation for os_random
(was urandom
), SecureRandom
, and random_raw_seed
to reflect that there are multiple potential sources for random data, not just urandom, openssl, and win32.
Updated by zofrex (James Sanderson) about 4 years ago
Updated by shyouhei (Shyouhei Urabe) about 4 years ago
+1 for doc update. Naming wise, ruby is rather POSIX-centric. For instance it has IO.select which works on Windows as well.
Updated by shyouhei (Shyouhei Urabe) about 4 years ago
Also until very recently (until version 5.6), Linux kernel has had distinct /dev/random and /dev/urandom. Some people argued the difference between those two are important. If we rename the method to os_random
, that loses information about the randomness source. This doesn't sound very well.
Updated by zofrex (James Sanderson) about 4 years ago
I hear what you're saying about communicating that it is not coming from /dev/random
. It's hard to communicate all of that in a method name, because it will be a different source on different OSes or OS versions.
If we rename the method to os_random, that loses information about the randomness source
Only a very small amount of information, I think, because this method almost never uses /dev/urandom
in practice. getrandom()
was added to Linux in 3.17, in 2014, so very few people will be falling back on /dev/urandom
.
I am not attached to to the name os_random
, it was just the best I could come up with at the time. Perhaps more could be communicated about the source with something like os_best_random
, to imply Ruby is using the best available source of random data the OS provides? Or maybe os_nonblocking_random
, to communicate that it is using a non-blocking source? (I know that /dev/random
and /dev/urandom
are the same on Linux now but I think some other OSes still have a blocking source available)
Updated by nobu (Nobuyoshi Nakada) about 4 years ago
How about Random.raw_seed(size)
?
Updated by zofrex (James Sanderson) about 4 years ago
I don't think raw_seed
is name that does a good job of communicating what this method does and what it can be used for. I know this method is used to seed the OpenSSL random number generator, but its functionality is more broad than that.
I think that people reading "raw_seed" are likely to think that either this returns the seed for the RNG or perhaps that this method is only suitable for seeding another RNG, rather than using this method as an RNG. The latter case is somewhat plausible because on some systems there are RNG sources that aren't suitable for generating lots of random data, but can be used to seed a PRNG, so I think it's important to distinguish from that.
I think urandom
is probably a better name than raw_seed
because, although it doesn't always draw from urandom
, it does always draw from random number generators that have similar properties to urandom
(non-blocking, suitable for reading lots of data from).
I think os_random
or os_nonblocking_random
are still better names because they quickly tell anyone reading the source of SecureRandom
that it gets its numbers from the OS random number generator (if not from OpenSSL). That makes reviewing the code from a security point of view a lot easier, and I think that's a highly desirable design goal for code that is so critical to the security of applications.
Updated by Eregon (Benoit Daloze) about 4 years ago
zofrex (James Sanderson) wrote in #note-6:
I think that people reading "raw_seed" are likely to think that either this returns the seed for the RNG or perhaps that this method is only suitable for seeding another RNG, rather than using this method as an RNG. The latter case is somewhat plausible because on some systems there are RNG sources that aren't suitable for generating lots of random data, but can be used to seed a PRNG, so I think it's important to distinguish from that.
That's the point, it's not a good idea to use this API to generate an arbitrary number of random bytes.
Only to use it to seed a RNG. It's just slower, inefficient and apparently not more secure to read many bytes from /dev/urandom.
FWIW there is already Random.new_seed #=> Integer
.
The reference in the doc of Random.urandom
to man 7 random
seems to be:
While some safety margin above that minimum is reasonable, as a guard against flaws in the CSPRNG algorithm, no cryptographic primitive available today can hope to promise more than 256 bits of security, so if any program reads more than 256 bits (32 bytes) from the kernel random pool per invocation, or per reasonable reseed interval (not less than one minute), that should be taken as a sign that its cryptography is not skillfully implemented.
Updated by nobu (Nobuyoshi Nakada) about 4 years ago
- Subject changed from Rename Random::urandom to os_random and document random data sources to Rename Random.urandom to os_random and document random data sources
- Description updated (diff)
Updated by naruse (Yui NARUSE) about 4 years ago
- Related to Bug #9569: SecureRandom should try /dev/urandom first added
Updated by naruse (Yui NARUSE) about 4 years ago
- Status changed from Open to Rejected
As https://bugs.ruby-lang.org/issues/9569#note-58 says, the name urandom
insists it doesn't block.
Ruby often provide Unix emulation layer on Windows. I don't think this needs special treatment for Random.urandom.
Also you can easily suspect Random.urandom uses /dev/urandom
and Win32 in this context about secure_random.rb.
Updated by zofrex (James Sanderson) about 4 years ago
Thank for explaining the rationale behind the naming, I understand it now.
How would you feel about a patch just to update the documentation, and leave the method names as they are? The documentation still only lists openssl, urandom, and win32 as sources, I think it would be good to list all the potential sources for completeness.
Updated by naruse (Yui NARUSE) about 4 years ago
zofrex (James Sanderson) wrote in #note-11:
Thank for explaining the rationale behind the naming, I understand it now.
How would you feel about a patch just to update the documentation, and leave the method names as they are? The documentation still only lists openssl, urandom, and win32 as sources, I think it would be good to list all the potential sources for completeness.
You may already read, Random.urandom actually don't use /dev/urandom
on many OSes. On Linux it uses getrandom(2)
. On macOS it uses SecRandomCopyBytes
. On some new BSDs it uses arc4random_buf
. You can write down this list now. But who updates it when the implementation changes in the future.
Improving documentation is good. But we also need to care about maintainability. In the view of maintainability, "completeness" is bad smell.