You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
randomBytes uses OpenSSL as its random number generator. It would be wiser and less errorprone to use a system RNG like urandom on Unix platforms, getrandom syscall on Linux and CryptGenRandom on Windows.
These are userspace CSPRNGs. You want to use the kernel’s CSPRNG, because:
The kernel has access to raw device entropy.
It can promise not to share the same state between applications.
A good kernel CSPRNG, like FreeBSD’s, can also promise not to feed you random data before it’s seeded.
Additionally, OpenSSL's userspace PRNG has caused issues in other languages (PHP under Apache for sure) because it's not fork-safe, which caused random numbers to repeat. (Combine this with the consequences of nonce reuse for most stream ciphers and boom your cryptosystem loses all privacy.)
Reacted by Stephen Oliver, Ondrej Mosnáček, Quinn Wilton, Dennis de Greef, 0xBADF00D, Tobias Feller, Stephen Walker-Weinshenker, Jarek Samic, Kyhwana Pardus, Jamie and 5 more
OpenSSL's PRNG is seeded from /dev/{,s,u}random, can get entropy from entropy-collecting daemons, and forking is not an issue for node.js. So far I'm not seeing a compelling reason to switch.
@paragonie-scott That's does not look like a good reasoning. Could you please be more calm? ;-)
Reacted by Jens
Reacted by rc4, Ackermann Yuriy, Lura Skye, Mae Kennedy, 0xBADF00D, Christopher Davis, Kevin Mark, Rajmund Csombordi, Nick, Stephen Walker-Weinshenker and 13 more
Reacted by kelvin knighton, Pete Nykänen, Phileas Lebada, Ian Stapleton Cordasco, tetyys, Marcos Bérgamo, Jarek Samic and Artur Ergashev
@bnoordhuis Trying to find specific reasons to explain away potential issues is not a good approach to security-related matters. The issues exist, and there's no way to predict how Node will evolve - for example, if fork-safety might start to matter due to future changes, at which point people will likely have forgotten about this specific issue.
We should be striving for the optimally secure implementation (within technical constraints), instead of attempting to 'defend' the current implementation when there are known edge cases / issues with it.
Reacted by Jan Gerlinger, Logan Bell, Pierre-Yves Gérardy, Ondrej Mosnáček, Peter Faiman, Justin Barber, Quinn Wilton, Jason Axley, Oliver Bestwalter, Dennis de Greef and 12 more
I do not yet have a strong opinion on this. I called @joepie91 and @paragonie-scott here because they expressed similar considerations as @speakeasypuncture in an IRC chat earlier.
@bnoordhuis, as I understand their points, the reasons here are:
System PRNG is good for this, is known to be stable and hasn't caused many security issues.
Adding a user-space PRNG of top of that doesn't make it more secure, but it makes it more prone to errors.
OpenSSL isn't actually a very high code quality product.
Using OpenSSL PRNG caused serious security issues for some projects, namely for Debian, Android and PHP (that latter is still not fixed, btw), though that was mostly their fault. Those issues are not directly applicable to Node.js, but this gives an uneasy feeling.
There seems to be no reason not to ditch OpenSSL PRNG and reduce the possible errors.
Everyone — did I miss anything?
Reacted by Jan Gerlinger, Brian M Hunt, Ackermann Yuriy, Jason Axley and Linus Unnebäck
Again: I do not yet have a strong opinion on this.
I would like to hear what would the drawbacks of this change be, and is there something where (or why) OpenSSL PRNG could be better than the system PRNG.
Excluding the fact that it's already used, of course — that also isn't a good enough argument, this won't even be a semver-major change. It's not documented that crypto.randomBytes() uses OpenSSL.
Node's crypto.randomBytes may not be cryptographically secure.
Operating systems expose a "system" RNG (Cryptographically Secure Pseudo-Random Number Generator or CSPRNG) which offers the best source of randomness on the system.
Rather than use the system RNG, Node.js relies on OpenSSL for crypto.randomBytes.
OpenSSL can be no more secure than the system RNG, and may be less secure. OpenSSL's use of a user-space CSPRNG on top of the kernel's CSPRNG is unnecessary and simply adds a layer of vulnerability.
I do not believe anyone has claimed that OpenSSL's CSPRNG is currently broken, although @ChALkeRpointed out some reasons why it might not be trustworthy.
Proposal
Node should consider an alternative implementation for random numbers that is definitely derived securely.
@azetsays that libsodium is a better option for random numbers than OpenSSL is, because libsodium underwent a review.
@FiloSottilehere and @ircmaxellhere add that avoiding reliance on a user-space CSPRNG, whether derived from a kernel CSPRNG or not, would reduce Node's attack surface.
Arguments against
The major arguments from the Node maintainers (and I may be reading between the lines a little bit) appear to be:
@bnoordhuishere and @sam-githubhere: if Node's security is broken because of issues in OpenSSL, it seems like the right answer is to pursue enhancements to OpenSSL. @shigekihere says that efforts along these lines are underway.
Code inertia. The OpenSSL-based implementation works. Changing the implementation to one derived from another library means investing time and energy into development and maintenance.
Peer pressure
@azetsaid Python uses the system CSPRNG rather than a user-space CSPRNG.
@bnoordhuisindicated that implementing PRNG logic in Node directly seemed undesirable.
My impressions
This proposal seems unlikely to result in motion from the Node maintainers until the OpenSSL API is available.
It seems like adopting libsodium would lead to unnecessary code churn because the OpenSSL API is on its way, albeit perhaps slowly.
In the interim, if security-conscious developers don't trust OpenSSL, they can use an npm module or an add-on that accesses platform-specific sources of randomness directly.
Reacted by Forest Mars, Tony Quetano, Nicholas Sherlock, Robert Kieffer, b1ue, Kevin Brown and Soroush
There's an upstream proposal to make OpenSSL create the equivalent of libsodium's randombytes_sysrandom() (which uses the OS's CSPRNG) which Node could then use instead of the userspace PRNG. This isn't close-worthy, it's stalled until OpenSSL does something.
Swapping out one userspace PRNG for another userspace PRNG is not a fix. Bypassing the userspace and using the OS's CSPRNG is the solution.
This isn't close-worthy, it's stalled until OpenSSL does something.
It's not actionable at the moment and won't be for a long time to come. Inactionable items clog up the bug tracker so I'll close this out for now. We can revisit when we upgrade to an openssl version that supports this new API.
Thanks for summarizing, but I don't think that captures the point. We are not advocating for reimplementing something that's in a library (for whatever reason), but for removing the library entirely. The library implements a user-space CSPRNG on top of kernel entropy, it might be good or bad, doesn't matter, we are arguing for not using one at all.
What you say is valid about primitives, which have to be implemented somewhere, but here we are talking about removing a layer from a system, where each layer is an independent point of failure.
As for "they are the ones that know about security", OpenSSL is bound by a lot of legacy, BoringSSL and libsodium are widely regarded as secure modern implementations, and those use the kernel CSPRNG.
Reacted by Scott, James C. (Jamie) Davis, AJ Jordan, Abigail O'Rourke, Eden Tyler-Moss and Charmander
Activity
bnoordhuis commentedon Mar 19, 2016
Instead of linking to a blog post, please summarize the pros and cons here.
ChALkeR commentedon Mar 19, 2016
Perhaps @joepie91 or @paragonie-scott would be interested to elaborate that here.
paragonie-scott commentedon Mar 19, 2016
From "a blog post":
Additionally, OpenSSL's userspace PRNG has caused issues in other languages (PHP under Apache for sure) because it's not fork-safe, which caused random numbers to repeat. (Combine this with the consequences of nonce reuse for most stream ciphers and boom your cryptosystem loses all privacy.)
A safer bet would be to adopt what PHP 7's
random_bytes()does:https://github.com/php/php-src/blob/e8f056e535813bf864743626c3a208ceafee70b9/ext/standard/random.c#L83-L186
bnoordhuis commentedon Mar 19, 2016
OpenSSL's PRNG is seeded from /dev/{,s,u}random, can get entropy from entropy-collecting daemons, and forking is not an issue for node.js. So far I'm not seeing a compelling reason to switch.
ChALkeR commentedon Mar 19, 2016
@paragonie-scott That's does not look like a good reasoning. Could you please be more calm? ;-)
joepie91 commentedon Mar 19, 2016
@bnoordhuis Trying to find specific reasons to explain away potential issues is not a good approach to security-related matters. The issues exist, and there's no way to predict how Node will evolve - for example, if fork-safety might start to matter due to future changes, at which point people will likely have forgotten about this specific issue.
We should be striving for the optimally secure implementation (within technical constraints), instead of attempting to 'defend' the current implementation when there are known edge cases / issues with it.
This post addresses that further.
ChALkeR commentedon Mar 19, 2016
I do not yet have a strong opinion on this. I called @joepie91 and @paragonie-scott here because they expressed similar considerations as @speakeasypuncture in an IRC chat earlier.
@bnoordhuis, as I understand their points, the reasons here are:
Everyone — did I miss anything?
ChALkeR commentedon Mar 19, 2016
Again: I do not yet have a strong opinion on this.
I would like to hear what would the drawbacks of this change be, and is there something where (or why) OpenSSL PRNG could be better than the system PRNG.
Excluding the fact that it's already used, of course — that also isn't a good enough argument, this won't even be a semver-major change. It's not documented that
crypto.randomBytes()uses OpenSSL.ChALkeR commentedon Mar 19, 2016
/cc @nodejs/crypto.
ChALkeR commentedon Mar 19, 2016
@mscdex I'm not sure if this is a «feature request», it looks like a proposal to change the implementation of
crypto.randomBytes()to me.joepie91 commentedon Mar 19, 2016
@ChALkeR Your summary seems accurate to me.
paragonie-scott commentedon Mar 19, 2016
Also, random number generators are hot-swappable without compatibility concerns, only security concerns.
147 remaining items
unix,win: add uv_randbytes
davisjam commentedon Mar 13, 2018
[Edited arguments for and against based on feedback]
I'm going to attempt to summarize the conversation and arguments that have happened on this issue. Sorry if I missed your post, I can amend.
Preliminaries
@speakeasypuncture initially opened this issue.
Per @joepie91, this issue is about Node's
crypto.randomBytes. (Statement).Issue statement
Node's
crypto.randomBytesmay not be cryptographically secure.crypto.randomBytes.I do not believe anyone has claimed that OpenSSL's CSPRNG is currently broken, although @ChALkeR pointed out some reasons why it might not be trustworthy.
Proposal
Node should consider an alternative implementation for random numbers that is definitely derived securely.
Arguments against
The major arguments from the Node maintainers (and I may be reading between the lines a little bit) appear to be:
Peer pressure
My impressions
paragonie-scott commentedon Mar 13, 2018
There's an upstream proposal to make OpenSSL create the equivalent of libsodium's
randombytes_sysrandom()(which uses the OS's CSPRNG) which Node could then use instead of the userspace PRNG. This isn't close-worthy, it's stalled until OpenSSL does something.Swapping out one userspace PRNG for another userspace PRNG is not a fix. Bypassing the userspace and using the OS's CSPRNG is the solution.
bnoordhuis commentedon Mar 13, 2018
It's not actionable at the moment and won't be for a long time to come. Inactionable items clog up the bug tracker so I'll close this out for now. We can revisit when we upgrade to an openssl version that supports this new API.
ChALkeR commentedon Mar 13, 2018
@bnoordhuis How are we going to remember to revisit it, then?
Perhaps introducing a separate label for temporary-inactionable items that were closed just because of that is needed so we don't forget to revisit?
bnoordhuis commentedon Mar 13, 2018
We go over the changelog with a fine-tooth comb whenever we upgrade (at least I do) so it's unlikely that such a change would go unnoticed.
I'm not completely opposed.
FiloSottile commentedon Mar 14, 2018
Thanks for summarizing, but I don't think that captures the point. We are not advocating for reimplementing something that's in a library (for whatever reason), but for removing the library entirely. The library implements a user-space CSPRNG on top of kernel entropy, it might be good or bad, doesn't matter, we are arguing for not using one at all.
What you say is valid about primitives, which have to be implemented somewhere, but here we are talking about removing a layer from a system, where each layer is an independent point of failure.
As for "they are the ones that know about security", OpenSSL is bound by a lot of legacy, BoringSSL and libsodium are widely regarded as secure modern implementations, and those use the kernel CSPRNG.
davisjam commentedon Mar 14, 2018
@FiloSottile Thanks, I've amended my post. Holler if you're still unhappy with my representations.
atoponce commentedon Feb 24, 2022
What's the current status with this issue?
technion commentedon Feb 25, 2022
@atoponce I could well have made a mistake somewhere, but tracing randomBytes appears to land here:
https://github.com/nodejs/node/blob/f69a4f61b2c133878159a9573ac438d58f8a05ac/src/crypto/crypto_random.cc
In which we first call RAND_status and then RAND_byes, these being OpenSSL functions.