[slightly OT] cryptographically strong random.SystemRandom()
Greetings! A question [1] has arisen about the viability of `random.SystemRandom` in Pythons before and after the secrets module was introduced (3.5 I think) -- specifically does it give independent and uniform discrete distribution for cryptographic purposes across CPython 3.x versions? Any help appreciated! -- ~Ethan~ [1] https://stackoverflow.com/q/68319071/208880
[Ethan Furman]
A question [1] has arisen about the viability of `random.SystemRandom` in Pythons before and after the secrets module was introduced (3.5 I think) -- specifically
does it give independent and uniform discrete distribution for cryptographic purposes across CPython 3.x versions?
`secrets` is just a wrapper around `random.SystemRandom`, so the presence or absence of `secrets` doesn't matter. As to SystemRandom, all answers depend on the quality of the platform os.urandom(), which Python has no control over. See my answer here, and the comments on it: https://stackoverflow.com/questions/20936993/how-can-i-create-a-random-numbe...
On 7/9/21 2:25 PM, Tim Peters wrote:
`secrets` is just a wrapper around `random.SystemRandom`, so the presence or absence of `secrets` doesn't matter.
As to SystemRandom, all answers depend on the quality of the platform os.urandom(), which Python has no control over. See my answer here, and the comments on it:
Good to know, thanks. -- ~Ethan~
FWIW, here is what https://cryptography.io has re: random (/? rng python
cryptography)
```rst
Random number generation
========================
When generating random data for use in cryptographic operations, such as an
initialization vector for encryption in
:class:`~cryptography.hazmat.primitives.ciphers.modes.CBC` mode, you do not
want to use the standard :mod:`random` module APIs. This is because they do
not
provide a cryptographically secure random number generator, which can
result in
major security issues depending on the algorithms in use.
Therefore, it is our recommendation to `always use your operating system's
provided random number generator`_, which is available as
:func:`os.urandom`.
For example, if you need 16 bytes of random data for an initialization
vector,
you can obtain them with:
.. doctest::
>>> import os
>>> iv = os.urandom(16)
This will use ``/dev/urandom`` on UNIX platforms, and ``CryptGenRandom`` on
Windows.
If you need your random number as an integer (for example, for
:meth:`~cryptography.x509.CertificateBuilder.serial_number`), you can use
``int.from_bytes`` to convert the result of ``os.urandom``:
.. code-block:: pycon
>>> serial = int.from_bytes(os.urandom(20), byteorder="big")
Starting with Python 3.6 the `standard library includes`_ the ``secrets``
module, which can be used for generating cryptographically secure random
numbers, with specific helpers for text-based formats.
.. _`always use your operating system's provided random number generator`:
https://sockpuppet.org/blog/2014/02/25/safely-generate-random-numbers/
.. _`standard library includes`:
https://docs.python.org/3/library/secrets.html
```
- https://docs.python.org/3/library/random.html
- https://docs.python.org/3/library/random.html#random.SystemRandom
- https://docs.python.org/3/library/os.html#os.urandom (see below for the
docs)
- https://docs.python.org/3/library/secrets.html
-
https://numpy.org/doc/stable/reference/random/generator.html#simple-random-d...
-
https://docs.scipy.org/doc/scipy/reference/tutorial/stats/discrete.html#disc...
-
https://docs.scipy.org/doc/scipy/reference/tutorial/stats/discrete_randint.h...
- https://docs.python.org/3/library/os.html#os.urandom :
```rst
Random numbers
--------------
.. function:: getrandom(size, flags=0)
Get up to *size* random bytes. The function can return less bytes than
requested.
These bytes can be used to seed user-space random number generators or
for
cryptographic purposes.
``getrandom()`` relies on entropy gathered from device drivers and other
sources of environmental noise. Unnecessarily reading large quantities of
data will have a negative impact on other users of the ``/dev/random``
and
``/dev/urandom`` devices.
The flags argument is a bit mask that can contain zero or more of the
following values ORed together: :py:data:`os.GRND_RANDOM` and
:py:data:`GRND_NONBLOCK`.
See also the `Linux getrandom() manual page
http://man7.org/linux/man-pages/man2/getrandom.2.html`_.
.. availability:: Linux 3.17 and newer.
.. versionadded:: 3.6
.. function:: urandom(size)
Return a string of *size* random bytes suitable for cryptographic use.
This function returns random bytes from an OS-specific randomness
source. The
returned data should be unpredictable enough for cryptographic
applications,
though its exact quality depends on the OS implementation.
On Linux, if the ``getrandom()`` syscall is available, it is used in
blocking mode: block until the system urandom entropy pool is initialized
(128 bits of entropy are collected by the kernel). See the :pep:`524` for
the rationale. On Linux, the :func:`getrandom` function can be used to
get
random bytes in non-blocking mode (using the :data:`GRND_NONBLOCK` flag)
or
to poll until the system urandom entropy pool is initialized.
On a Unix-like system, random bytes are read from the ``/dev/urandom``
device. If the ``/dev/urandom`` device is not available or not readable,
the
:exc:`NotImplementedError` exception is raised.
On Windows, it will use ``CryptGenRandom()``.
.. seealso::
The :mod:`secrets` module provides higher level functions. For an
easy-to-use interface to the random number generator provided by your
platform, please see :class:`random.SystemRandom`.
.. versionchanged:: 3.6.0
On Linux, ``getrandom()`` is now used in blocking mode to increase the
security.
.. versionchanged:: 3.5.2
On Linux, if the ``getrandom()`` syscall blocks (the urandom entropy
pool
is not initialized yet), fall back on reading ``/dev/urandom``.
.. versionchanged:: 3.5
On Linux 3.17 and newer, the ``getrandom()`` syscall is now used
when available. On OpenBSD 5.6 and newer, the C ``getentropy()``
function is now used. These functions avoid the usage of an internal
file
descriptor.
.. data:: GRND_NONBLOCK
By default, when reading from ``/dev/random``, :func:`getrandom` blocks
if
no random bytes are available, and when reading from ``/dev/urandom``,
it blocks
if the entropy pool has not yet been initialized.
If the :py:data:`GRND_NONBLOCK` flag is set, then :func:`getrandom` does
not
block in these cases, but instead immediately raises
:exc:`BlockingIOError`.
.. versionadded:: 3.6
.. data:: GRND_RANDOM
If this bit is set, then random bytes are drawn from the
``/dev/random`` pool instead of the ``/dev/urandom`` pool.
.. versionadded:: 3.6
```
On Fri, Jul 9, 2021 at 6:04 PM Ethan Furman
On 7/9/21 2:25 PM, Tim Peters wrote:
`secrets` is just a wrapper around `random.SystemRandom`, so the presence or absence of `secrets` doesn't matter.
As to SystemRandom, all answers depend on the quality of the platform os.urandom(), which Python has no control over. See my answer here, and the comments on it:
Good to know, thanks.
-- ~Ethan~ _______________________________________________ Python-Dev mailing list -- python-dev@python.org To unsubscribe send an email to python-dev-leave@python.org https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/ZGCYXLN6... Code of Conduct: http://python.org/psf/codeofconduct/
* Citation: https://cryptography.io/en/latest/random-numbers/
On Sat, Jul 10, 2021 at 7:53 PM Wes Turner
FWIW, here is what https://cryptography.io has re: random (/? rng python cryptography)
```rst Random number generation ========================
When generating random data for use in cryptographic operations, such as an initialization vector for encryption in :class:`~cryptography.hazmat.primitives.ciphers.modes.CBC` mode, you do not want to use the standard :mod:`random` module APIs. This is because they do not provide a cryptographically secure random number generator, which can result in major security issues depending on the algorithms in use.
Therefore, it is our recommendation to `always use your operating system's provided random number generator`_, which is available as :func:`os.urandom`. For example, if you need 16 bytes of random data for an initialization vector, you can obtain them with:
.. doctest::
>>> import os >>> iv = os.urandom(16)
This will use ``/dev/urandom`` on UNIX platforms, and ``CryptGenRandom`` on Windows.
If you need your random number as an integer (for example, for :meth:`~cryptography.x509.CertificateBuilder.serial_number`), you can use ``int.from_bytes`` to convert the result of ``os.urandom``:
.. code-block:: pycon
>>> serial = int.from_bytes(os.urandom(20), byteorder="big")
Starting with Python 3.6 the `standard library includes`_ the ``secrets`` module, which can be used for generating cryptographically secure random numbers, with specific helpers for text-based formats.
.. _`always use your operating system's provided random number generator`: https://sockpuppet.org/blog/2014/02/25/safely-generate-random-numbers/ .. _`standard library includes`: https://docs.python.org/3/library/secrets.html ```
- https://docs.python.org/3/library/random.html - https://docs.python.org/3/library/random.html#random.SystemRandom - https://docs.python.org/3/library/os.html#os.urandom (see below for the docs) - https://docs.python.org/3/library/secrets.html - https://numpy.org/doc/stable/reference/random/generator.html#simple-random-d... - https://docs.scipy.org/doc/scipy/reference/tutorial/stats/discrete.html#disc... - https://docs.scipy.org/doc/scipy/reference/tutorial/stats/discrete_randint.h... - https://docs.python.org/3/library/os.html#os.urandom :
```rst Random numbers --------------
.. function:: getrandom(size, flags=0)
Get up to *size* random bytes. The function can return less bytes than requested.
These bytes can be used to seed user-space random number generators or for cryptographic purposes.
``getrandom()`` relies on entropy gathered from device drivers and other sources of environmental noise. Unnecessarily reading large quantities of data will have a negative impact on other users of the ``/dev/random`` and ``/dev/urandom`` devices.
The flags argument is a bit mask that can contain zero or more of the following values ORed together: :py:data:`os.GRND_RANDOM` and :py:data:`GRND_NONBLOCK`.
See also the `Linux getrandom() manual page http://man7.org/linux/man-pages/man2/getrandom.2.html`_.
.. availability:: Linux 3.17 and newer.
.. versionadded:: 3.6
.. function:: urandom(size)
Return a string of *size* random bytes suitable for cryptographic use.
This function returns random bytes from an OS-specific randomness source. The returned data should be unpredictable enough for cryptographic applications, though its exact quality depends on the OS implementation.
On Linux, if the ``getrandom()`` syscall is available, it is used in blocking mode: block until the system urandom entropy pool is initialized (128 bits of entropy are collected by the kernel). See the :pep:`524` for the rationale. On Linux, the :func:`getrandom` function can be used to get random bytes in non-blocking mode (using the :data:`GRND_NONBLOCK` flag) or to poll until the system urandom entropy pool is initialized.
On a Unix-like system, random bytes are read from the ``/dev/urandom`` device. If the ``/dev/urandom`` device is not available or not readable, the :exc:`NotImplementedError` exception is raised.
On Windows, it will use ``CryptGenRandom()``.
.. seealso:: The :mod:`secrets` module provides higher level functions. For an easy-to-use interface to the random number generator provided by your platform, please see :class:`random.SystemRandom`.
.. versionchanged:: 3.6.0 On Linux, ``getrandom()`` is now used in blocking mode to increase the security.
.. versionchanged:: 3.5.2 On Linux, if the ``getrandom()`` syscall blocks (the urandom entropy pool is not initialized yet), fall back on reading ``/dev/urandom``.
.. versionchanged:: 3.5 On Linux 3.17 and newer, the ``getrandom()`` syscall is now used when available. On OpenBSD 5.6 and newer, the C ``getentropy()`` function is now used. These functions avoid the usage of an internal file descriptor.
.. data:: GRND_NONBLOCK
By default, when reading from ``/dev/random``, :func:`getrandom` blocks if no random bytes are available, and when reading from ``/dev/urandom``, it blocks if the entropy pool has not yet been initialized.
If the :py:data:`GRND_NONBLOCK` flag is set, then :func:`getrandom` does not block in these cases, but instead immediately raises :exc:`BlockingIOError`.
.. versionadded:: 3.6
.. data:: GRND_RANDOM
If this bit is set, then random bytes are drawn from the ``/dev/random`` pool instead of the ``/dev/urandom`` pool.
.. versionadded:: 3.6 ```
On Fri, Jul 9, 2021 at 6:04 PM Ethan Furman
wrote: On 7/9/21 2:25 PM, Tim Peters wrote:
`secrets` is just a wrapper around `random.SystemRandom`, so the presence or absence of `secrets` doesn't matter.
As to SystemRandom, all answers depend on the quality of the platform os.urandom(), which Python has no control over. See my answer here, and the comments on it:
Good to know, thanks.
-- ~Ethan~ _______________________________________________ Python-Dev mailing list -- python-dev@python.org To unsubscribe send an email to python-dev-leave@python.org https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/ZGCYXLN6... Code of Conduct: http://python.org/psf/codeofconduct/
On Fri, Jul 9, 2021 at 2:26 PM Tim Peters
[Ethan Furman]
A question [1] has arisen about the viability of `random.SystemRandom` in Pythons before and after the secrets module was introduced (3.5 I think) -- specifically
does it give independent and uniform discrete distribution for cryptographic purposes across CPython 3.x versions?
`secrets` is just a wrapper around `random.SystemRandom`, so the presence or absence of `secrets` doesn't matter.
As to SystemRandom, all answers depend on the quality of the platform os.urandom(), which Python has no control over. See my answer here, and the comments on it:
https://stackoverflow.com/questions/20936993/how-can-i-create-a-random-numbe...
It looks like CPython could do better on Windows: SystemRandom (because of os.urandom()) is good on Linux and mac, but on Windows they use the CryptGenRandom deprecated API.... Supporting detail: https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryp... Should I open an issue?
On 7/12/2021 4:11 PM, Dan Stromberg wrote:
It looks like CPython could do better on Windows: SystemRandom (because of os.urandom()) is good on Linux and mac, but on Windows they use the CryptGenRandom deprecated API....
Supporting detail: https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryp... https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryp...
Should I open an issue?
Please do, but note that the API is only deprecated because it was not very extensible and the new API is much more comple... er... extensible. There's nothing wrong with the randomness from the function. It'll be using the new API under the covers. So this is an enhancement, not a security issue, and should only target 3.11. Cheers, Steve
"PEP 543 -- A Unified TLS API for Python" could specify a [CS][P][RNG]
interface that could be used instead of os.urandom, which is probably also
wrong.
PEP 543 compares OpenSSL, SecureTransport, SChannel, and NSS; which
presumably all have some sort of a CSPRNG function that may or may not need
to be initialized with state and paramaetrs.
https://wiki.openssl.org/index.php/Random_Numbers#Generation
Hopefully, hardware support for RNGs that OpenSSL already has is already
functionally extant in the various OSes as well:
https://wiki.openssl.org/index.php/Random_Numbers#Hardware
https://en.wikipedia.org/wiki//dev/random
On Sat, Jul 10, 2021 at 7:54 PM Wes Turner
* Citation: https://cryptography.io/en/latest/random-numbers/
On Sat, Jul 10, 2021 at 7:53 PM Wes Turner
wrote: FWIW, here is what https://cryptography.io has re: random (/? rng python cryptography)
```rst Random number generation ========================
When generating random data for use in cryptographic operations, such as an initialization vector for encryption in :class:`~cryptography.hazmat.primitives.ciphers.modes.CBC` mode, you do not want to use the standard :mod:`random` module APIs. This is because they do not provide a cryptographically secure random number generator, which can result in major security issues depending on the algorithms in use.
Therefore, it is our recommendation to `always use your operating system's provided random number generator`_, which is available as :func:`os.urandom`. For example, if you need 16 bytes of random data for an initialization vector, you can obtain them with:
.. doctest::
>>> import os >>> iv = os.urandom(16)
This will use ``/dev/urandom`` on UNIX platforms, and ``CryptGenRandom`` on Windows.
If you need your random number as an integer (for example, for :meth:`~cryptography.x509.CertificateBuilder.serial_number`), you can use ``int.from_bytes`` to convert the result of ``os.urandom``:
.. code-block:: pycon
>>> serial = int.from_bytes(os.urandom(20), byteorder="big")
Starting with Python 3.6 the `standard library includes`_ the ``secrets`` module, which can be used for generating cryptographically secure random numbers, with specific helpers for text-based formats.
.. _`always use your operating system's provided random number generator`: https://sockpuppet.org/blog/2014/02/25/safely-generate-random-numbers/ .. _`standard library includes`: https://docs.python.org/3/library/secrets.html ```
- https://docs.python.org/3/library/random.html - https://docs.python.org/3/library/random.html#random.SystemRandom - https://docs.python.org/3/library/os.html#os.urandom (see below for the docs) - https://docs.python.org/3/library/secrets.html - https://numpy.org/doc/stable/reference/random/generator.html#simple-random-d... - https://docs.scipy.org/doc/scipy/reference/tutorial/stats/discrete.html#disc... - https://docs.scipy.org/doc/scipy/reference/tutorial/stats/discrete_randint.h... - https://docs.python.org/3/library/os.html#os.urandom :
```rst Random numbers --------------
.. function:: getrandom(size, flags=0)
Get up to *size* random bytes. The function can return less bytes than requested.
These bytes can be used to seed user-space random number generators or for cryptographic purposes.
``getrandom()`` relies on entropy gathered from device drivers and other sources of environmental noise. Unnecessarily reading large quantities of data will have a negative impact on other users of the ``/dev/random`` and ``/dev/urandom`` devices.
The flags argument is a bit mask that can contain zero or more of the following values ORed together: :py:data:`os.GRND_RANDOM` and :py:data:`GRND_NONBLOCK`.
See also the `Linux getrandom() manual page http://man7.org/linux/man-pages/man2/getrandom.2.html`_.
.. availability:: Linux 3.17 and newer.
.. versionadded:: 3.6
.. function:: urandom(size)
Return a string of *size* random bytes suitable for cryptographic use.
This function returns random bytes from an OS-specific randomness source. The returned data should be unpredictable enough for cryptographic applications, though its exact quality depends on the OS implementation.
On Linux, if the ``getrandom()`` syscall is available, it is used in blocking mode: block until the system urandom entropy pool is initialized (128 bits of entropy are collected by the kernel). See the :pep:`524` for the rationale. On Linux, the :func:`getrandom` function can be used to get random bytes in non-blocking mode (using the :data:`GRND_NONBLOCK` flag) or to poll until the system urandom entropy pool is initialized.
On a Unix-like system, random bytes are read from the ``/dev/urandom`` device. If the ``/dev/urandom`` device is not available or not readable, the :exc:`NotImplementedError` exception is raised.
On Windows, it will use ``CryptGenRandom()``.
.. seealso:: The :mod:`secrets` module provides higher level functions. For an easy-to-use interface to the random number generator provided by your platform, please see :class:`random.SystemRandom`.
.. versionchanged:: 3.6.0 On Linux, ``getrandom()`` is now used in blocking mode to increase the security.
.. versionchanged:: 3.5.2 On Linux, if the ``getrandom()`` syscall blocks (the urandom entropy pool is not initialized yet), fall back on reading ``/dev/urandom``.
.. versionchanged:: 3.5 On Linux 3.17 and newer, the ``getrandom()`` syscall is now used when available. On OpenBSD 5.6 and newer, the C ``getentropy()`` function is now used. These functions avoid the usage of an internal file descriptor.
.. data:: GRND_NONBLOCK
By default, when reading from ``/dev/random``, :func:`getrandom` blocks if no random bytes are available, and when reading from ``/dev/urandom``, it blocks if the entropy pool has not yet been initialized.
If the :py:data:`GRND_NONBLOCK` flag is set, then :func:`getrandom` does not block in these cases, but instead immediately raises :exc:`BlockingIOError`.
.. versionadded:: 3.6
.. data:: GRND_RANDOM
If this bit is set, then random bytes are drawn from the ``/dev/random`` pool instead of the ``/dev/urandom`` pool.
.. versionadded:: 3.6 ```
On Fri, Jul 9, 2021 at 6:04 PM Ethan Furman
wrote: On 7/9/21 2:25 PM, Tim Peters wrote:
`secrets` is just a wrapper around `random.SystemRandom`, so the presence or absence of `secrets` doesn't matter.
As to SystemRandom, all answers depend on the quality of the platform os.urandom(), which Python has no control over. See my answer here, and the comments on it:
Good to know, thanks.
-- ~Ethan~ _______________________________________________ Python-Dev mailing list -- python-dev@python.org To unsubscribe send an email to python-dev-leave@python.org https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/ZGCYXLN6... Code of Conduct: http://python.org/psf/codeofconduct/
On Mon, Jul 12, 2021 at 8:37 AM Steve Dower
On 7/12/2021 4:11 PM, Dan Stromberg wrote:
It looks like CPython could do better on Windows: SystemRandom (because of os.urandom()) is good on Linux and mac, but on Windows they use the CryptGenRandom deprecated API....
Supporting detail:
https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryp...
< https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryp...
Should I open an issue?
Please do, but note that the API is only deprecated because it was not very extensible and the new API is much more comple... er... extensible.
There's nothing wrong with the randomness from the function. It'll be using the new API under the covers. So this is an enhancement, not a security issue, and should only target 3.11.
I created https://bugs.python.org/issue44611 for this.
https://docs.microsoft.com/en-us/windows/win32/seccng/cng-portal ?
On Mon, 12 Jul 2021, 23:18 Dan Stromberg,
On Mon, Jul 12, 2021 at 8:37 AM Steve Dower
wrote: On 7/12/2021 4:11 PM, Dan Stromberg wrote:
It looks like CPython could do better on Windows: SystemRandom (because of os.urandom()) is good on Linux and mac, but on Windows they use the CryptGenRandom deprecated API....
Supporting detail:
https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryp...
< https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryp...
Should I open an issue?
Please do, but note that the API is only deprecated because it was not very extensible and the new API is much more comple... er... extensible.
There's nothing wrong with the randomness from the function. It'll be using the new API under the covers. So this is an enhancement, not a security issue, and should only target 3.11.
I created https://bugs.python.org/issue44611 for this.
_______________________________________________ Python-Dev mailing list -- python-dev@python.org To unsubscribe send an email to python-dev-leave@python.org https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/C3QBAG3Y... Code of Conduct: http://python.org/psf/codeofconduct/
participants (6)
-
Dan Stromberg
-
Ethan Furman
-
Steve Dower
-
Thomas Grainger
-
Tim Peters
-
Wes Turner