New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use system random generator in crypto #5798

Closed
speakeasypuncture opened this Issue Mar 19, 2016 · 152 comments

Comments

Projects
None yet
@speakeasypuncture

speakeasypuncture commented Mar 19, 2016

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.

@bnoordhuis

This comment has been minimized.

Show comment
Hide comment
@bnoordhuis

bnoordhuis Mar 19, 2016

Member

Instead of linking to a blog post, please summarize the pros and cons here.

Member

bnoordhuis commented Mar 19, 2016

Instead of linking to a blog post, please summarize the pros and cons here.

@ChALkeR

This comment has been minimized.

Show comment
Hide comment
@ChALkeR

ChALkeR Mar 19, 2016

Member

Perhaps @joepie91 or @paragonie-scott would be interested to elaborate that here.

Member

ChALkeR commented Mar 19, 2016

Perhaps @joepie91 or @paragonie-scott would be interested to elaborate that here.

@paragonie-scott

This comment has been minimized.

Show comment
Hide comment
@paragonie-scott

paragonie-scott Mar 19, 2016

From "a blog post":

Why not {SecureRandom, OpenSSL, havaged, &c}?

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.)

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

paragonie-scott commented Mar 19, 2016

From "a blog post":

Why not {SecureRandom, OpenSSL, havaged, &c}?

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.)

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

This comment has been minimized.

Show comment
Hide comment
@bnoordhuis

bnoordhuis Mar 19, 2016

Member

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.

Member

bnoordhuis commented 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

This comment has been minimized.

Show comment
Hide comment
@ChALkeR

ChALkeR Mar 19, 2016

Member

@paragonie-scott That's does not look like a good reasoning. Could you please be more calm? ;-)

Member

ChALkeR commented Mar 19, 2016

@paragonie-scott That's does not look like a good reasoning. Could you please be more calm? ;-)

@joepie91

This comment has been minimized.

Show comment
Hide comment
@joepie91

joepie91 Mar 19, 2016

Contributor

@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.

Contributor

joepie91 commented 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

This comment has been minimized.

Show comment
Hide comment
@ChALkeR

ChALkeR Mar 19, 2016

Member

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:

  1. System PRNG is good for this, is known to be stable and hasn't caused many security issues.
  2. Adding a user-space PRNG of top of that doesn't make it more secure, but it makes it more prone to errors.
  3. OpenSSL isn't actually a very high code quality product.
  4. 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.
  5. There seems to be no reason not to ditch OpenSSL PRNG and reduce the possible errors.

Everyone — did I miss anything?

Member

ChALkeR commented 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:

  1. System PRNG is good for this, is known to be stable and hasn't caused many security issues.
  2. Adding a user-space PRNG of top of that doesn't make it more secure, but it makes it more prone to errors.
  3. OpenSSL isn't actually a very high code quality product.
  4. 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.
  5. There seems to be no reason not to ditch OpenSSL PRNG and reduce the possible errors.

Everyone — did I miss anything?

@ChALkeR ChALkeR added the security label Mar 19, 2016

@ChALkeR

This comment has been minimized.

Show comment
Hide comment
@ChALkeR

ChALkeR Mar 19, 2016

Member

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.

Member

ChALkeR commented 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

This comment has been minimized.

Show comment
Hide comment
@ChALkeR
Member

ChALkeR commented Mar 19, 2016

@ChALkeR

This comment has been minimized.

Show comment
Hide comment
@ChALkeR

ChALkeR Mar 19, 2016

Member

@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.

Member

ChALkeR commented 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

This comment has been minimized.

Show comment
Hide comment
@joepie91

joepie91 Mar 19, 2016

Contributor

@ChALkeR Your summary seems accurate to me.

Contributor

joepie91 commented Mar 19, 2016

@ChALkeR Your summary seems accurate to me.

@paragonie-scott

This comment has been minimized.

Show comment
Hide comment
@paragonie-scott

paragonie-scott Mar 19, 2016

Also, random number generators are hot-swappable without compatibility concerns, only security concerns.

paragonie-scott commented Mar 19, 2016

Also, random number generators are hot-swappable without compatibility concerns, only security concerns.

@indutny

This comment has been minimized.

Show comment
Hide comment
@indutny

indutny Mar 20, 2016

Member

I'm -1 on this, no compelling reasons for me.

Member

indutny commented Mar 20, 2016

I'm -1 on this, no compelling reasons for me.

@joepie91

This comment has been minimized.

Show comment
Hide comment
@joepie91

joepie91 Mar 20, 2016

Contributor

@indutny Please refer back to this comment in particular, plus several others in the thread. There is a lack of reasons not to do this (insofar anybody has stated them, that is), while there are documented reasons to do it.

If you feel that there is a reason not to do it, then please share it - but "no compelling reasons for me" really isn't a sufficient argument for a security-related matter. Even a small defect can have disastrous consequences.

Contributor

joepie91 commented Mar 20, 2016

@indutny Please refer back to this comment in particular, plus several others in the thread. There is a lack of reasons not to do this (insofar anybody has stated them, that is), while there are documented reasons to do it.

If you feel that there is a reason not to do it, then please share it - but "no compelling reasons for me" really isn't a sufficient argument for a security-related matter. Even a small defect can have disastrous consequences.

@indutny

This comment has been minimized.

Show comment
Hide comment
@indutny

indutny Mar 20, 2016

Member

@joepie91 sure, sorry for too short reply.

What about systems with "good" PRNG? How many of them are there? Do we have to carry both implementations to support them?

Member

indutny commented Mar 20, 2016

@joepie91 sure, sorry for too short reply.

What about systems with "good" PRNG? How many of them are there? Do we have to carry both implementations to support them?

@joepie91

This comment has been minimized.

Show comment
Hide comment
@joepie91

joepie91 Mar 20, 2016

Contributor

@indutny Thanks for the elaboration.

As I understand it (and please correct me if not), OpenSSL depends on the system PRNG to begin with. I'm not aware of any platforms (of those supported by Node, that is) where OpenSSL can provide a better PRNG than the one that the system offers natively.

It should thus be possible to just remove OpenSSL's PRNG from the equation entirely, and rely purely on the system PRNG, as PHP has done.

Contributor

joepie91 commented Mar 20, 2016

@indutny Thanks for the elaboration.

As I understand it (and please correct me if not), OpenSSL depends on the system PRNG to begin with. I'm not aware of any platforms (of those supported by Node, that is) where OpenSSL can provide a better PRNG than the one that the system offers natively.

It should thus be possible to just remove OpenSSL's PRNG from the equation entirely, and rely purely on the system PRNG, as PHP has done.

@indutny

This comment has been minimized.

Show comment
Hide comment
@indutny

indutny Mar 20, 2016

Member

@joepie91 do you suggest to use this randomness for TLS protocol as well? I'm not sure if it is possible, though.

Member

indutny commented Mar 20, 2016

@joepie91 do you suggest to use this randomness for TLS protocol as well? I'm not sure if it is possible, though.

@joepie91

This comment has been minimized.

Show comment
Hide comment
@joepie91

joepie91 Mar 20, 2016

Contributor

While that would probably be nice (albeit requiring more investigation), I don't think that's doable. As far as I know, OpenSSL's other functionality relies internally on its own PRNG with no ability to change that - unless we want to get rid of OpenSSL entirely, which would be a separate proposal (and likely not viable at this stage, given the lack of well-tested alternatives).

So, this specific proposal would concern the "user-facing" randomBytes method only.

Contributor

joepie91 commented Mar 20, 2016

While that would probably be nice (albeit requiring more investigation), I don't think that's doable. As far as I know, OpenSSL's other functionality relies internally on its own PRNG with no ability to change that - unless we want to get rid of OpenSSL entirely, which would be a separate proposal (and likely not viable at this stage, given the lack of well-tested alternatives).

So, this specific proposal would concern the "user-facing" randomBytes method only.

@indutny

This comment has been minimized.

Show comment
Hide comment
@indutny

indutny Mar 20, 2016

Member

Ok, considering arguments it probably make more sense now.

Member

indutny commented Mar 20, 2016

Ok, considering arguments it probably make more sense now.

@bnoordhuis

This comment has been minimized.

Show comment
Hide comment
@bnoordhuis

bnoordhuis Mar 20, 2016

Member

Here's a reason not to switch: OpenSSL's PRNG is a known quantity, the strength of platform-specific PRNGs is not. If the next Windows or FreeBSD release has a flawed PRNG, that will compromise node.js.

If (generic) you think moving to platform-specific solutions is the way forward, get OpenSSL to adopt your approach and node.js will automatically go along. I believe @paragonie-scott is volunteering? He sure seems to feel strongly about it.

if fork-safety might start to matter due to future changes, at which point people will likely have forgotten about this specific issue.

@joepie91 The bucket list of fork-safety issues that would have to be addressed is so long that I think it's safe to say that node.js will never be fork-safe. There are many things that keep me awake at night but this is not one of them.

Member

bnoordhuis commented Mar 20, 2016

Here's a reason not to switch: OpenSSL's PRNG is a known quantity, the strength of platform-specific PRNGs is not. If the next Windows or FreeBSD release has a flawed PRNG, that will compromise node.js.

If (generic) you think moving to platform-specific solutions is the way forward, get OpenSSL to adopt your approach and node.js will automatically go along. I believe @paragonie-scott is volunteering? He sure seems to feel strongly about it.

if fork-safety might start to matter due to future changes, at which point people will likely have forgotten about this specific issue.

@joepie91 The bucket list of fork-safety issues that would have to be addressed is so long that I think it's safe to say that node.js will never be fork-safe. There are many things that keep me awake at night but this is not one of them.

@alfiepates

This comment has been minimized.

Show comment
Hide comment
@alfiepates

alfiepates Mar 20, 2016

If the next Windows or FreeBSD release has a flawed PRNG, that will compromise node.js.

I don't believe this argument holds any merit, honestly.

FreeBSD are not just going to push broken code EDIT: FreeBSD are not going to push broken code to the -STABLE kernel branch, especially when they have a perfectly functional CSPRNG already, and especially as they have a security team of their own who would definitely catch any changes to the CSPRNG which would lead to a vulnerability in the OS.

I'm going to be frank, here: Attempting to justify away security issues is downright irresponsible, and possibly dangerous. You need to strive for bulletproof security, or you may as well not implement any security at all (And no, don't twist this to mean "Don't bother with security", because that's just lazy.)

I appreciate it's "extra work" to make a change like this, but considering you're using a PRNG which has actually caused security issues in the past, I'd err on the safe side and move to something more provably secure.

alfiepates commented Mar 20, 2016

If the next Windows or FreeBSD release has a flawed PRNG, that will compromise node.js.

I don't believe this argument holds any merit, honestly.

FreeBSD are not just going to push broken code EDIT: FreeBSD are not going to push broken code to the -STABLE kernel branch, especially when they have a perfectly functional CSPRNG already, and especially as they have a security team of their own who would definitely catch any changes to the CSPRNG which would lead to a vulnerability in the OS.

I'm going to be frank, here: Attempting to justify away security issues is downright irresponsible, and possibly dangerous. You need to strive for bulletproof security, or you may as well not implement any security at all (And no, don't twist this to mean "Don't bother with security", because that's just lazy.)

I appreciate it's "extra work" to make a change like this, but considering you're using a PRNG which has actually caused security issues in the past, I'd err on the safe side and move to something more provably secure.

@bnoordhuis

This comment has been minimized.

Show comment
Hide comment
@bnoordhuis

bnoordhuis Mar 20, 2016

Member

as they have a security team of their own who would definitely catch any changes to the CSPRNG which would lead to a vulnerability in the OS

Besides being an appeal to authority, you're asking (generic) me to trust several teams of implementors (the platforms) instead of just one (OpenSSL) to get their implementation right.

considering you're using a PRNG which has actually caused security issues in the past

Are you saying you feel OpenSSL's PRNG is insecure? If so, why aren't you taking that up with the OpenSSL team? Griping about it here isn't going to do any good.

I'll repeat what I've said above: get the upstream project to move over, and we as downstream consumers will automatically move along with it.

Member

bnoordhuis commented Mar 20, 2016

as they have a security team of their own who would definitely catch any changes to the CSPRNG which would lead to a vulnerability in the OS

Besides being an appeal to authority, you're asking (generic) me to trust several teams of implementors (the platforms) instead of just one (OpenSSL) to get their implementation right.

considering you're using a PRNG which has actually caused security issues in the past

Are you saying you feel OpenSSL's PRNG is insecure? If so, why aren't you taking that up with the OpenSSL team? Griping about it here isn't going to do any good.

I'll repeat what I've said above: get the upstream project to move over, and we as downstream consumers will automatically move along with it.

@joepie91

This comment has been minimized.

Show comment
Hide comment
@joepie91

joepie91 Mar 20, 2016

Contributor

Here's a reason not to switch: OpenSSL's PRNG is a known quantity, the strength of platform-specific PRNGs is not. If the next Windows or FreeBSD release has a flawed PRNG, that will compromise node.js.

Yet OpenSSL's PRNG relies on these platform-specific PRNGs, and mixing in one broken PRNG can weaken the entire (combined) PRNG. How does relying on OpenSSL fix the issue you've described?

The bucket list of fork-safety issues that would have to be addressed is so long that I think it's safe to say that node.js will never be fork-safe. There are many things that keep me awake at night but this is not one of them.

That is a very dangerous assumption to make.

f so, why aren't you taking that up with the OpenSSL team?

I think the existence of this project should give an indication. At this stage, there's a fairly wide consensus around the security community that OpenSSL is awful software, and the only real reason it is still being recommended is because it's what has been tested in the real world for so long. Not because it is of high quality or well-maintained.

Contributor

joepie91 commented Mar 20, 2016

Here's a reason not to switch: OpenSSL's PRNG is a known quantity, the strength of platform-specific PRNGs is not. If the next Windows or FreeBSD release has a flawed PRNG, that will compromise node.js.

Yet OpenSSL's PRNG relies on these platform-specific PRNGs, and mixing in one broken PRNG can weaken the entire (combined) PRNG. How does relying on OpenSSL fix the issue you've described?

The bucket list of fork-safety issues that would have to be addressed is so long that I think it's safe to say that node.js will never be fork-safe. There are many things that keep me awake at night but this is not one of them.

That is a very dangerous assumption to make.

f so, why aren't you taking that up with the OpenSSL team?

I think the existence of this project should give an indication. At this stage, there's a fairly wide consensus around the security community that OpenSSL is awful software, and the only real reason it is still being recommended is because it's what has been tested in the real world for so long. Not because it is of high quality or well-maintained.

@ChALkeR ChALkeR added the discuss label Mar 20, 2016

@paragonie-scott

This comment has been minimized.

Show comment
Hide comment
@paragonie-scott

paragonie-scott Mar 20, 2016

@bnoordhuis:

Here's a reason not to switch: OpenSSL's PRNG is a known quantity, the strength of platform-specific PRNGs is not. If the next Windows or FreeBSD release has a flawed PRNG, that will compromise node.js.

This is a common argument that people make, but it's ultimately invalid.

Even if you avoid depending on the operating system's PRNG, the rest of your system definitely depends on it for security. Node.js will be compromised regardless of what Node.js does.

paragonie-scott commented Mar 20, 2016

@bnoordhuis:

Here's a reason not to switch: OpenSSL's PRNG is a known quantity, the strength of platform-specific PRNGs is not. If the next Windows or FreeBSD release has a flawed PRNG, that will compromise node.js.

This is a common argument that people make, but it's ultimately invalid.

Even if you avoid depending on the operating system's PRNG, the rest of your system definitely depends on it for security. Node.js will be compromised regardless of what Node.js does.

@indutny

This comment has been minimized.

Show comment
Hide comment
@indutny

indutny Mar 20, 2016

Member

Just a bit of FYI for everyone here:

http://lwn.net/Articles/633805/rss

"FreeBSD random number generator broken for last 4 months"

Member

indutny commented Mar 20, 2016

Just a bit of FYI for everyone here:

http://lwn.net/Articles/633805/rss

"FreeBSD random number generator broken for last 4 months"

@ChALkeR

This comment has been minimized.

Show comment
Hide comment
@ChALkeR

ChALkeR Mar 20, 2016

Member

@indutny Note that it also affects keys generated by Node.js on FreeBSD (using crypto.randomBytes()):

This includes, but not limited to, ssh keys and keys generated by openssl.

Member

ChALkeR commented Mar 20, 2016

@indutny Note that it also affects keys generated by Node.js on FreeBSD (using crypto.randomBytes()):

This includes, but not limited to, ssh keys and keys generated by openssl.

@ircmaxell

This comment has been minimized.

Show comment
Hide comment
@ircmaxell

ircmaxell Mar 20, 2016

@bnoordhuis

Here's a reason not to switch: OpenSSL's PRNG is a known quantity, the strength of platform-specific PRNGs is not. If the next Windows or FreeBSD release has a flawed PRNG, that will compromise node.js.

Actually, if Windows's CSPRNG is compromised, then Node.JS will be compromised. This is because OpenSSL relies on the system CSPRNG to seed it. There is no other source of high-quality random data in the system.

This means that the OpenSSL CSPRNG can by definition not be any stronger than the system's CSPRNG. However, it can be weaker (as has been seen several times).

The reason @paragonie-scott and others (including myself) are anti-userspace-csprng is that they provide no possible security gain, but introduce several security risks (by increasing attack surface area, by increasing bug surface area, etc).

There really is no benefit to not switching (other than not making a change at all). However, as has been demonstrated in this thread already, there are several advantages to switching.

My suggestion would be to switch to the kernel-space CSPRNG.

ircmaxell commented Mar 20, 2016

@bnoordhuis

Here's a reason not to switch: OpenSSL's PRNG is a known quantity, the strength of platform-specific PRNGs is not. If the next Windows or FreeBSD release has a flawed PRNG, that will compromise node.js.

Actually, if Windows's CSPRNG is compromised, then Node.JS will be compromised. This is because OpenSSL relies on the system CSPRNG to seed it. There is no other source of high-quality random data in the system.

This means that the OpenSSL CSPRNG can by definition not be any stronger than the system's CSPRNG. However, it can be weaker (as has been seen several times).

The reason @paragonie-scott and others (including myself) are anti-userspace-csprng is that they provide no possible security gain, but introduce several security risks (by increasing attack surface area, by increasing bug surface area, etc).

There really is no benefit to not switching (other than not making a change at all). However, as has been demonstrated in this thread already, there are several advantages to switching.

My suggestion would be to switch to the kernel-space CSPRNG.

@indutny

This comment has been minimized.

Show comment
Hide comment
@indutny

indutny Mar 20, 2016

Member

@ChALkeR this was a reply to:

FreeBSD are not just going to push broken code, especially when they have a perfectly functional CSPRNG already

Member

indutny commented Mar 20, 2016

@ChALkeR this was a reply to:

FreeBSD are not just going to push broken code, especially when they have a perfectly functional CSPRNG already

@ChALkeR

This comment has been minimized.

Show comment
Hide comment
@ChALkeR

ChALkeR Mar 20, 2016

Member

@indutny yes, this assumption by @alfiepates is incorrect:

FreeBSD are not just going to push broken code, especially when they have a perfectly functional CSPRNG already, and especially as they have a security team of their own who would definitely catch any changes to the CSPRNG which would lead to a vulnerability in the OS.

Everyone makes mistakes, you can't say «{*} are not just going to push broken code» or «this lib is magical, shining, and will never be broken».

But what should be actually considered here is the fact that OpenSSL PRNG depends on system PRNG. So, it seems like under no circuimstances you could trust OpenSSL PRNG more than system PRNG, which makes «we can't trust system PRNGs, so let's use OpenSSL» argument invalid.

Member

ChALkeR commented Mar 20, 2016

@indutny yes, this assumption by @alfiepates is incorrect:

FreeBSD are not just going to push broken code, especially when they have a perfectly functional CSPRNG already, and especially as they have a security team of their own who would definitely catch any changes to the CSPRNG which would lead to a vulnerability in the OS.

Everyone makes mistakes, you can't say «{*} are not just going to push broken code» or «this lib is magical, shining, and will never be broken».

But what should be actually considered here is the fact that OpenSSL PRNG depends on system PRNG. So, it seems like under no circuimstances you could trust OpenSSL PRNG more than system PRNG, which makes «we can't trust system PRNGs, so let's use OpenSSL» argument invalid.

@alfiepates

This comment has been minimized.

Show comment
Hide comment
@alfiepates

alfiepates Mar 20, 2016

@indutny

I will retract some of my comment, it was far too absolute, but I don't believe it's wrong.

It's disingenuous to link this article without stating the fact that this occured on the FreeBSD -CURRENT branch, as opposed to the -STABLE branch. The -CURRENT branch is the bleeding-edge branch, and therefore bugs do happen, and in this case the bug was caught before the it made it to -STABLE.

Besides, I feel you're missing the point of this discussion. OpenSSL's CSPRNG is a security risk. EDIT: Need to pay more attention when tired.

alfiepates commented Mar 20, 2016

@indutny

I will retract some of my comment, it was far too absolute, but I don't believe it's wrong.

It's disingenuous to link this article without stating the fact that this occured on the FreeBSD -CURRENT branch, as opposed to the -STABLE branch. The -CURRENT branch is the bleeding-edge branch, and therefore bugs do happen, and in this case the bug was caught before the it made it to -STABLE.

Besides, I feel you're missing the point of this discussion. OpenSSL's CSPRNG is a security risk. EDIT: Need to pay more attention when tired.

@indutny

This comment has been minimized.

Show comment
Hide comment
@indutny

indutny Mar 20, 2016

Member

@ChALkeR of course, I'm not saying that this is a counter-argument. Just wanted to make sure that everyone on the same page and does not trust OS vendors blindly.

Member

indutny commented Mar 20, 2016

@ChALkeR of course, I'm not saying that this is a counter-argument. Just wanted to make sure that everyone on the same page and does not trust OS vendors blindly.

@indutny

This comment has been minimized.

Show comment
Hide comment
@indutny

indutny Mar 20, 2016

Member

@alfiepates hey, I'm not missing the point here! 😉 In fact, I'm almost convinced that this should happen. See #5798 (comment)

Member

indutny commented Mar 20, 2016

@alfiepates hey, I'm not missing the point here! 😉 In fact, I'm almost convinced that this should happen. See #5798 (comment)

@alfiepates

This comment has been minimized.

Show comment
Hide comment
@alfiepates

alfiepates Mar 20, 2016

@indutny Ahh, wonderful. I'll retract that part of my comment too :P (Please forgive me, I'm one cup of coffee behind right now)

alfiepates commented Mar 20, 2016

@indutny Ahh, wonderful. I'll retract that part of my comment too :P (Please forgive me, I'm one cup of coffee behind right now)

@indutny

This comment has been minimized.

Show comment
Hide comment
@indutny

indutny Mar 20, 2016

Member

There is however a risk of incorrect implementation on our side, when we will write that new code to support OS-level PRNG. Just some food for thoughts.

Member

indutny commented Mar 20, 2016

There is however a risk of incorrect implementation on our side, when we will write that new code to support OS-level PRNG. Just some food for thoughts.

@ChALkeR

This comment has been minimized.

Show comment
Hide comment
@ChALkeR

ChALkeR Mar 20, 2016

Member

@indutny True. There is also a blocking-vs-nonblocking argument that would need to be discussed when implementing this (i.e. /dev/random vs /dev/urandom). I don't have an opinion on that yet.

Member

ChALkeR commented Mar 20, 2016

@indutny True. There is also a blocking-vs-nonblocking argument that would need to be discussed when implementing this (i.e. /dev/random vs /dev/urandom). I don't have an opinion on that yet.

@paragonie-scott

This comment has been minimized.

Show comment
Hide comment
@paragonie-scott

paragonie-scott Mar 20, 2016

@indutny Sure. I'm almost certain that the rough draft will be incorrect in some way. That's why peer review matters.

For what it's worth, I did help with PHP's implementation and I work for a company that audits crypto code. There are others in this thread that are often more perceptive than I am.

So as long as we participated it's highly likely that any implementation bugs will be spotted and rectified.

paragonie-scott commented Mar 20, 2016

@indutny Sure. I'm almost certain that the rough draft will be incorrect in some way. That's why peer review matters.

For what it's worth, I did help with PHP's implementation and I work for a company that audits crypto code. There are others in this thread that are often more perceptive than I am.

So as long as we participated it's highly likely that any implementation bugs will be spotted and rectified.

@co60ca

This comment has been minimized.

Show comment
Hide comment
@co60ca

co60ca Sep 17, 2016

To @joepie91 I've seen a implementation of UUID v4 use math.random so yes, a secure default that pulls from system entropy would be fantastic.

co60ca commented Sep 17, 2016

To @joepie91 I've seen a implementation of UUID v4 use math.random so yes, a secure default that pulls from system entropy would be fantastic.

@atoponce

This comment has been minimized.

Show comment
Hide comment
@atoponce

atoponce Sep 17, 2016

As another example of using crypto.randomBytes() in a non-HTTPS setting, I am using it in a password generator: https://github.com/atoponce/nodepassgen.

atoponce commented Sep 17, 2016

As another example of using crypto.randomBytes() in a non-HTTPS setting, I am using it in a password generator: https://github.com/atoponce/nodepassgen.

@jasnell

This comment has been minimized.

Show comment
Hide comment
@jasnell

jasnell May 30, 2017

Member

ping @nodejs/crypto ... should this remain open?

Member

jasnell commented May 30, 2017

ping @nodejs/crypto ... should this remain open?

@bnoordhuis

This comment has been minimized.

Show comment
Hide comment
@bnoordhuis

bnoordhuis May 30, 2017

Member

No, let's close.

Member

bnoordhuis commented May 30, 2017

No, let's close.

@bnoordhuis bnoordhuis closed this May 30, 2017

@azet

This comment has been minimized.

Show comment
Hide comment
@azet

azet May 30, 2017

this issue remains unfixed and there has been valuable discussion on resolving the problem.
similar issues in e.g. ruby proper lead to switch to libsodium-like approaches: https://bugs.ruby-lang.org/issues/9569

OpenSSL's implementation remains, to my knowledge, largely untested and specifically optimized to cater to TLS implementation's needs for fast random numbers. most languages (e.g. python) opt to use the /dev/urandom device on Linux distributions. libsodium is platform aware and spares the overhead of fiddling and maintaining distribution specific code-paths. libsodium has also been reviewed and is used by a lot of people and projects to provide a layer of abstraction for obtaining cryptographically secure pseudo random numbers.

I urge the core team to use libsodium's reviewed, platform-aware way to obtain secure pseudo random numbers: https://github.com/jedisct1/libsodium/blob/master/src/libsodium/randombytes/randombytes.c

please re-open this security relevant issue.

azet commented May 30, 2017

this issue remains unfixed and there has been valuable discussion on resolving the problem.
similar issues in e.g. ruby proper lead to switch to libsodium-like approaches: https://bugs.ruby-lang.org/issues/9569

OpenSSL's implementation remains, to my knowledge, largely untested and specifically optimized to cater to TLS implementation's needs for fast random numbers. most languages (e.g. python) opt to use the /dev/urandom device on Linux distributions. libsodium is platform aware and spares the overhead of fiddling and maintaining distribution specific code-paths. libsodium has also been reviewed and is used by a lot of people and projects to provide a layer of abstraction for obtaining cryptographically secure pseudo random numbers.

I urge the core team to use libsodium's reviewed, platform-aware way to obtain secure pseudo random numbers: https://github.com/jedisct1/libsodium/blob/master/src/libsodium/randombytes/randombytes.c

please re-open this security relevant issue.

@tarcieri

This comment has been minimized.

Show comment
Hide comment
@tarcieri

tarcieri May 31, 2017

What was the rationale for closing this issue?

tarcieri commented May 31, 2017

What was the rationale for closing this issue?

@Trott

This comment has been minimized.

Show comment
Hide comment
@Trott

Trott May 31, 2017

Member

If I understand correctly (which is a big "if" when it comes to cryptography and related issues):

Especially given activity on openssl/openssl#898 fairly recently, and that progress there could mean a suitable fix here that can still use OpenSSL APIs, I'd be for keeping this open.

Member

Trott commented May 31, 2017

If I understand correctly (which is a big "if" when it comes to cryptography and related issues):

Especially given activity on openssl/openssl#898 fairly recently, and that progress there could mean a suitable fix here that can still use OpenSSL APIs, I'd be for keeping this open.

@sam-github

This comment has been minimized.

Show comment
Hide comment
@sam-github

sam-github May 31, 2017

Member

@nodejs/crypto I think we should keep it open until its fixed. Last discussion was that OpenSSL were themselves moving this direction, and we hoped to simply inherit their fix. From openssl/openssl#898, it does indeed look like they are moving along (slowly, but with recent progress). But if OpenSSL 1.1 doesn't change this, we could revisit whether node should use some other way of getting pseudo-random.

Member

sam-github commented May 31, 2017

@nodejs/crypto I think we should keep it open until its fixed. Last discussion was that OpenSSL were themselves moving this direction, and we hoped to simply inherit their fix. From openssl/openssl#898, it does indeed look like they are moving along (slowly, but with recent progress). But if OpenSSL 1.1 doesn't change this, we could revisit whether node should use some other way of getting pseudo-random.

@MylesBorins

This comment has been minimized.

Show comment
Hide comment
@MylesBorins

MylesBorins May 31, 2017

Member

As a handful of people (including collaborators) have chimed in about wanting to continue the discussion. I'm reopening

That being said I think this might be part of a larger conversation about openssl... perhaps we can look into improving their implementation on systems that have support?

afaict libsodium is going to be a nonstarter if it doesn't have fips support

Member

MylesBorins commented May 31, 2017

As a handful of people (including collaborators) have chimed in about wanting to continue the discussion. I'm reopening

That being said I think this might be part of a larger conversation about openssl... perhaps we can look into improving their implementation on systems that have support?

afaict libsodium is going to be a nonstarter if it doesn't have fips support

@MylesBorins MylesBorins reopened this May 31, 2017

@paragonie-scott

This comment has been minimized.

Show comment
Hide comment
@paragonie-scott

paragonie-scott May 31, 2017

afaict libsodium is going to be a nonstarter if it doesn't have fips support

Replacing OpenSSL entirely with Libsodium might be a nonstarter.

Is FIPS-140-2 compliance an absolute mandatory requirement? Because ECB mode is FIPS compliant, and you sure as hell don't want people encrypting that way.

paragonie-scott commented May 31, 2017

afaict libsodium is going to be a nonstarter if it doesn't have fips support

Replacing OpenSSL entirely with Libsodium might be a nonstarter.

Is FIPS-140-2 compliance an absolute mandatory requirement? Because ECB mode is FIPS compliant, and you sure as hell don't want people encrypting that way.

@technion

This comment has been minimized.

Show comment
Hide comment
@technion

technion May 31, 2017

Any changes to OpenSSL, even if they improve in this space, are going to show up on a new major release, which moves much, much slower than Node. If they made a great release tomorrow, it will take years to hit some distributions at all. I don't feel you want to wait on this.

technion commented May 31, 2017

Any changes to OpenSSL, even if they improve in this space, are going to show up on a new major release, which moves much, much slower than Node. If they made a great release tomorrow, it will take years to hit some distributions at all. I don't feel you want to wait on this.

@Trott

This comment has been minimized.

Show comment
Hide comment
@Trott

Trott May 31, 2017

Member

If they made a great release tomorrow, it will take years to hit some distributions at all.

Node.js doesn't use the operating system's OpenSSL. Node.js ships with its own copy of OpenSSL.

Member

Trott commented May 31, 2017

If they made a great release tomorrow, it will take years to hit some distributions at all.

Node.js doesn't use the operating system's OpenSSL. Node.js ships with its own copy of OpenSSL.

@bnoordhuis

This comment has been minimized.

Show comment
Hide comment
@bnoordhuis

bnoordhuis May 31, 2017

Member

I might be open to bundling libsodium in addition to openssl but that should be its own issue because there will be numerous details to hash out.

We sure as heck are not going to ship something homegrown and until openssl grows the requisite APIs there isn't anything actionable. I'm closing this again and I'm locking it to prevent this already humongous thread from growing bigger.

Member

bnoordhuis commented May 31, 2017

I might be open to bundling libsodium in addition to openssl but that should be its own issue because there will be numerous details to hash out.

We sure as heck are not going to ship something homegrown and until openssl grows the requisite APIs there isn't anything actionable. I'm closing this again and I'm locking it to prevent this already humongous thread from growing bigger.

@bnoordhuis bnoordhuis closed this May 31, 2017

@nodejs nodejs locked and limited conversation to collaborators May 31, 2017

@ChALkeR ChALkeR added the ctc-agenda label Jun 1, 2017

@ChALkeR

This comment has been minimized.

Show comment
Hide comment
@ChALkeR

ChALkeR Jun 1, 2017

Member

@MylesBorins Re: FIPS compliance — if libsodium randombytes.c is not compliant and if FIPS compliance is desired, that could be fixed with a runtime flag that switches back the impl to OpenSSL (as we won't stop bundling OpenSSL nevertheless). Also, see this link.

Member

ChALkeR commented Jun 1, 2017

@MylesBorins Re: FIPS compliance — if libsodium randombytes.c is not compliant and if FIPS compliance is desired, that could be fixed with a runtime flag that switches back the impl to OpenSSL (as we won't stop bundling OpenSSL nevertheless). Also, see this link.

@sam-github

This comment has been minimized.

Show comment
Hide comment
@sam-github

sam-github Jun 1, 2017

Member

Note that openssl 1.1 won't be FIPS compliant for quite a while, so FIPS users will need to stick to a node built on 1.0. cf. https://www.openssl.org/blog/blog/2016/07/20/fips/

I'm still hopeful that OpenSSL will deal with this for us, I'm not saying we should be thinking of libsodium for 8.x, but I don't think FIPS would be a blocker if we go looking elsewhere for a PRNG. Also, I'm not sure random seeds are covered by FIPS, anyway, that would take some looking into.

Member

sam-github commented Jun 1, 2017

Note that openssl 1.1 won't be FIPS compliant for quite a while, so FIPS users will need to stick to a node built on 1.0. cf. https://www.openssl.org/blog/blog/2016/07/20/fips/

I'm still hopeful that OpenSSL will deal with this for us, I'm not saying we should be thinking of libsodium for 8.x, but I don't think FIPS would be a blocker if we go looking elsewhere for a PRNG. Also, I'm not sure random seeds are covered by FIPS, anyway, that would take some looking into.

@ChALkeR ChALkeR removed the ctc-agenda label Jun 7, 2017

@mhdawson mhdawson reopened this Jun 8, 2017

@nodejs nodejs unlocked this conversation Jun 8, 2017

@shigeki

This comment has been minimized.

Show comment
Hide comment
@shigeki

shigeki Aug 3, 2017

Contributor

Note that OpenSSL has just landed a commit to use DRGB with AES-CTR of NIST SP 800-90A as openssl/openssl@75e2c87. We can use it with the os-specific seeding source (e.g. /dev/urandom) by a default define flag of OPENSSL_RAND_SEED_OS.
I think it is best for us to wait for the next release of OpenSSL-1.1.1.

Contributor

shigeki commented Aug 3, 2017

Note that OpenSSL has just landed a commit to use DRGB with AES-CTR of NIST SP 800-90A as openssl/openssl@75e2c87. We can use it with the os-specific seeding source (e.g. /dev/urandom) by a default define flag of OPENSSL_RAND_SEED_OS.
I think it is best for us to wait for the next release of OpenSSL-1.1.1.

saghul added a commit to saghul/libuv that referenced this issue Aug 15, 2017

@Trott Trott removed the discuss label Mar 11, 2018

@davisjam

This comment has been minimized.

Show comment
Hide comment
@davisjam

davisjam Mar 13, 2018

Contributor

[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.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 @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.

  1. @azet says that libsodium is a better option for random numbers than OpenSSL is, because libsodium underwent a review.
  2. @FiloSottile here and @ircmaxell here 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:

  • @bnoordhuis here and @sam-github here: if Node's security is broken because of issues in OpenSSL, it seems like the right answer is to pursue enhancements to OpenSSL. @shigeki here 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

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.
Contributor

davisjam commented 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.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 @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.

  1. @azet says that libsodium is a better option for random numbers than OpenSSL is, because libsodium underwent a review.
  2. @FiloSottile here and @ircmaxell here 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:

  • @bnoordhuis here and @sam-github here: if Node's security is broken because of issues in OpenSSL, it seems like the right answer is to pursue enhancements to OpenSSL. @shigeki here 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

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.
@paragonie-scott

This comment has been minimized.

Show comment
Hide comment
@paragonie-scott

paragonie-scott 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.

paragonie-scott commented 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.

@Trott Trott added stalled and removed stalled labels Mar 13, 2018

@bnoordhuis

This comment has been minimized.

Show comment
Hide comment
@bnoordhuis

bnoordhuis Mar 13, 2018

Member

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.

Member

bnoordhuis commented Mar 13, 2018

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.

@bnoordhuis bnoordhuis closed this Mar 13, 2018

@ChALkeR

This comment has been minimized.

Show comment
Hide comment
@ChALkeR

ChALkeR Mar 13, 2018

Member

@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?

Member

ChALkeR commented 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

This comment has been minimized.

Show comment
Hide comment
@bnoordhuis

bnoordhuis Mar 13, 2018

Member

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.

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?

I'm not completely opposed.

Member

bnoordhuis commented 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.

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?

I'm not completely opposed.

@FiloSottile

This comment has been minimized.

Show comment
Hide comment
@FiloSottile

FiloSottile 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.

FiloSottile commented 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

This comment has been minimized.

Show comment
Hide comment
@davisjam

davisjam Mar 14, 2018

Contributor

@FiloSottile Thanks, I've amended my post. Holler if you're still unhappy with my representations.

Contributor

davisjam commented Mar 14, 2018

@FiloSottile Thanks, I've amended my post. Holler if you're still unhappy with my representations.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment