Re: [Python-Dev] [Python-checkins] cpython: Issue #12049: Add RAND_bytes() and RAND_pseudo_bytes() functions to the ssl

Le mardi 24 mai 2011 à 11:27 -0400, Terry Reedy a écrit :
An important feature of a CPRNG (cryptographic pseudo-random number generator) is that even if you know all of its output, you cannot rebuild its internal state to guess next (or maybe previous number). The CPRNG can for example hash its output using SHA-1: you will have to "break" the SHA-1 hash (maybe using "salt"). Another important feature is that even if you know the internal state, you will not be able to guess all previous and next numbers, because the internal state is regulary updated using an external source of entropy. Use RAND_add() to do that explicitly. We may add a link to Wikipedia: http://en.wikipedia.org/wiki/CPRNG Read the "Requirements" section, it's maybe more correct than my explanation: http://en.wikipedia.org/wiki/CPRNG#Requirements About the random module, it must not be used to generate passwords or certificates, because it is easy to rebuild the internal state of a Mersenne Twister generator if you know the previous 624 numbers. Since you know the state, it's also easy to generate all next numbers. Seed a Mersenne Twister PRNG doesn't help. See my Hasard project if you would like to learn more about PRNG ;-) We may also add a link from random to SSL.RAND_bytes() and SSL.RAND_pseudo_bytes(). https://bitbucket.org/haypo/hasard/ Victor

On 5/24/2011 12:06 PM, Victor Stinner wrote:
So it is presumably slower. I still do not get RAND_pseudo_bytes, which somehow decides internally what to do.
That would be helpful
-- Terry Jan Reedy

On Wed, May 25, 2011 at 3:52 AM, Terry Reedy <tjreedy@udel.edu> wrote:
The more important feature here is that it is exposing *OpenSSL's* random number generation, rather than our own. A CPRNG isn't *necessarily* slower than a non-crypto one (particularly on systems with dedicated crypto hardware), but they can definitely fail to return data if there isn't enough entropy available in the pool (and the system has to have a usable entropy source in the first place). The RAND_bytes() documentation should probably make it clearer that unlike the random module and RAND_pseudo_bytes(), RAND_bytes() can *fail* (by raising SSLError) if it isn't in a position to provide the requested random data. The pseudo_bytes version just encapsulates a fallback technique that may be suitable in some circumstances: if crypto quality random data is not available, fall back on PRNG data instead of failing. It is most suitable for tasks like prototyping an algorithm in Python for later conversion to C, or similar tasks where it is desirable to use the OpenSSL PRNG over the one in the random module. Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia

Le mercredi 25 mai 2011 à 15:09 +1000, Nick Coghlan a écrit :
According to the doc, both functions can fail, but it is more likely than RAND_bytes() fail. I disabled temporary Linux random devices to test RAND_bytes() error code: mv /dev/random /dev/random.xxx mv /dev/urandom /dev/urandom.xxx In this case, RAND_pseudo_bytes() generates non-cryptographic random numbers: it returns (random_bytes, False). I don't know how to test RAND_pseudo_bytes() error code. -- I patched test_ssl to test that RAND_bytes() raises an SSLError if there is not enough entropy, and I also improved the documentation to detail the error cases. Victor

On 5/25/2011 1:09 AM, Nick Coghlan wrote:
The more important feature here is that it is exposing *OpenSSL's* random number generation, rather than our own.
I agree, thought from a different stance, I think. The issue is whether we should 'automatically' expose everything is a wrapped library, even if it duplicates existing functions. I think not. But in this case, at least one of the two functions is sufficiently different, and the newest doc patches clarify the situation. -- Terry Jan Reedy

Terry Reedy wrote:
According to the RAND_bytes manual page from OpenSSL: RAND_bytes() puts num cryptographically strong pseudo-random bytes into buf. An error occurs if the PRNG has not been seeded with enough randomness to ensure an unpredictable byte sequence. RAND_pseudo_bytes() puts num pseudo-random bytes into buf. Pseudo-random byte sequences generated by RAND_pseudo_bytes() will be unique if they are of sufficient length, but are not necessarily unpredictable. They can be used for non-cryptographic purposes and for certain purposes in cryptographic protocols, but usually not for key generation etc. And: RAND_bytes() returns 1 on success, 0 otherwise. The error code can be obtained by ERR_get_error(3). RAND_pseudo_bytes() returns 1 if the bytes generated are cryptographically strong, 0 otherwise. Both functions return -1 if they are not supported by the current RAND method. So it seems to me that RAND_bytes() either returns cryptographically strong data or fails (is it possible to detect the failure with the Python function? Should this be documented?). RAND_pseudo_bytes() always succeeds but does not necessarily generate cryptographically strong data.
Obviously, the user needs to be familiar with the concept of "cryptographically strong randomness" to use these functions. Petri Lehtinen

Le mercredi 25 mai 2011 à 08:59 +0300, Petri Lehtinen a écrit :
RAND_bytes() raises an SSLError on error. You can check if there is enough entropy before calling RAND_bytes() using RAND_status(). I documented this two infos.
RAND_pseudo_bytes() always succeeds...
No, it can fail if the RAND method was changed and the current RAND method doesn't support this operation. Example: ----
Cool, ssl.RAND_pseudo_bytes() raises also an error, as expected :-)
... but does not necessarily generate cryptographically strong data.
Yes, if the PRNG was not seed with enough data, the RAND_pseudo_bytes() Python function returns (random_bytes, False).
I already patched the doc of the random module to add a security warning. Well, you don't really need to know how a CSPRNG is implemented, just that random cannot be used for security and that ssl.RAND_bytes() raises an error if was seeded with enough data. Tell me if my warning is not clear: .. warning:: The generators of the :mod:`random` module should not be used for security purposes, they are not cryptographic. Use ssl.RAND_bytes() if you require a cryptographically secure pseudorandom number generator. Victor

On 5/24/2011 12:06 PM, Victor Stinner wrote:
So it is presumably slower. I still do not get RAND_pseudo_bytes, which somehow decides internally what to do.
That would be helpful
-- Terry Jan Reedy

On Wed, May 25, 2011 at 3:52 AM, Terry Reedy <tjreedy@udel.edu> wrote:
The more important feature here is that it is exposing *OpenSSL's* random number generation, rather than our own. A CPRNG isn't *necessarily* slower than a non-crypto one (particularly on systems with dedicated crypto hardware), but they can definitely fail to return data if there isn't enough entropy available in the pool (and the system has to have a usable entropy source in the first place). The RAND_bytes() documentation should probably make it clearer that unlike the random module and RAND_pseudo_bytes(), RAND_bytes() can *fail* (by raising SSLError) if it isn't in a position to provide the requested random data. The pseudo_bytes version just encapsulates a fallback technique that may be suitable in some circumstances: if crypto quality random data is not available, fall back on PRNG data instead of failing. It is most suitable for tasks like prototyping an algorithm in Python for later conversion to C, or similar tasks where it is desirable to use the OpenSSL PRNG over the one in the random module. Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia

Le mercredi 25 mai 2011 à 15:09 +1000, Nick Coghlan a écrit :
According to the doc, both functions can fail, but it is more likely than RAND_bytes() fail. I disabled temporary Linux random devices to test RAND_bytes() error code: mv /dev/random /dev/random.xxx mv /dev/urandom /dev/urandom.xxx In this case, RAND_pseudo_bytes() generates non-cryptographic random numbers: it returns (random_bytes, False). I don't know how to test RAND_pseudo_bytes() error code. -- I patched test_ssl to test that RAND_bytes() raises an SSLError if there is not enough entropy, and I also improved the documentation to detail the error cases. Victor

On 5/25/2011 1:09 AM, Nick Coghlan wrote:
The more important feature here is that it is exposing *OpenSSL's* random number generation, rather than our own.
I agree, thought from a different stance, I think. The issue is whether we should 'automatically' expose everything is a wrapped library, even if it duplicates existing functions. I think not. But in this case, at least one of the two functions is sufficiently different, and the newest doc patches clarify the situation. -- Terry Jan Reedy

Terry Reedy wrote:
According to the RAND_bytes manual page from OpenSSL: RAND_bytes() puts num cryptographically strong pseudo-random bytes into buf. An error occurs if the PRNG has not been seeded with enough randomness to ensure an unpredictable byte sequence. RAND_pseudo_bytes() puts num pseudo-random bytes into buf. Pseudo-random byte sequences generated by RAND_pseudo_bytes() will be unique if they are of sufficient length, but are not necessarily unpredictable. They can be used for non-cryptographic purposes and for certain purposes in cryptographic protocols, but usually not for key generation etc. And: RAND_bytes() returns 1 on success, 0 otherwise. The error code can be obtained by ERR_get_error(3). RAND_pseudo_bytes() returns 1 if the bytes generated are cryptographically strong, 0 otherwise. Both functions return -1 if they are not supported by the current RAND method. So it seems to me that RAND_bytes() either returns cryptographically strong data or fails (is it possible to detect the failure with the Python function? Should this be documented?). RAND_pseudo_bytes() always succeeds but does not necessarily generate cryptographically strong data.
Obviously, the user needs to be familiar with the concept of "cryptographically strong randomness" to use these functions. Petri Lehtinen

Le mercredi 25 mai 2011 à 08:59 +0300, Petri Lehtinen a écrit :
RAND_bytes() raises an SSLError on error. You can check if there is enough entropy before calling RAND_bytes() using RAND_status(). I documented this two infos.
RAND_pseudo_bytes() always succeeds...
No, it can fail if the RAND method was changed and the current RAND method doesn't support this operation. Example: ----
Cool, ssl.RAND_pseudo_bytes() raises also an error, as expected :-)
... but does not necessarily generate cryptographically strong data.
Yes, if the PRNG was not seed with enough data, the RAND_pseudo_bytes() Python function returns (random_bytes, False).
I already patched the doc of the random module to add a security warning. Well, you don't really need to know how a CSPRNG is implemented, just that random cannot be used for security and that ssl.RAND_bytes() raises an error if was seeded with enough data. Tell me if my warning is not clear: .. warning:: The generators of the :mod:`random` module should not be used for security purposes, they are not cryptographic. Use ssl.RAND_bytes() if you require a cryptographically secure pseudorandom number generator. Victor
participants (5)
-
Eric Smith
-
Nick Coghlan
-
Petri Lehtinen
-
Terry Reedy
-
Victor Stinner