Convert to Unix newlines.

This commit is contained in:
Serhiy Storchaka 2016-05-03 13:27:59 +03:00
parent 3dad438872
commit e54e86b163
2 changed files with 701 additions and 701 deletions

View File

@ -1,449 +1,449 @@
PEP: 506 PEP: 506
Title: Adding A Secrets Module To The Standard Library Title: Adding A Secrets Module To The Standard Library
Version: $Revision$ Version: $Revision$
Last-Modified: $Date$ Last-Modified: $Date$
Author: Steven D'Aprano <steve@pearwood.info> Author: Steven D'Aprano <steve@pearwood.info>
Status: Accepted Status: Accepted
Type: Standards Track Type: Standards Track
Content-Type: text/x-rst Content-Type: text/x-rst
Created: 19-Sep-2015 Created: 19-Sep-2015
Python-Version: 3.6 Python-Version: 3.6
Post-History: Post-History:
Abstract Abstract
======== ========
This PEP proposes the addition of a module for common security-related This PEP proposes the addition of a module for common security-related
functions such as generating tokens to the Python standard library. functions such as generating tokens to the Python standard library.
Definitions Definitions
=========== ===========
Some common abbreviations used in this proposal: Some common abbreviations used in this proposal:
* PRNG: * PRNG:
Pseudo Random Number Generator. A deterministic algorithm used Pseudo Random Number Generator. A deterministic algorithm used
to produce random-looking numbers with certain desirable to produce random-looking numbers with certain desirable
statistical properties. statistical properties.
* CSPRNG: * CSPRNG:
Cryptographically Strong Pseudo Random Number Generator. An Cryptographically Strong Pseudo Random Number Generator. An
algorithm used to produce random-looking numbers which are algorithm used to produce random-looking numbers which are
resistant to prediction. resistant to prediction.
* MT: * MT:
Mersenne Twister. An extensively studied PRNG which is currently Mersenne Twister. An extensively studied PRNG which is currently
used by the ``random`` module as the default. used by the ``random`` module as the default.
Rationale Rationale
========= =========
This proposal is motivated by concerns that Python's standard library This proposal is motivated by concerns that Python's standard library
makes it too easy for developers to inadvertently make serious security makes it too easy for developers to inadvertently make serious security
errors. Theo de Raadt, the founder of OpenBSD, contacted Guido van Rossum errors. Theo de Raadt, the founder of OpenBSD, contacted Guido van Rossum
and expressed some concern [#]_ about the use of MT for generating sensitive and expressed some concern [#]_ about the use of MT for generating sensitive
information such as passwords, secure tokens, session keys and similar. information such as passwords, secure tokens, session keys and similar.
Although the documentation for the ``random`` module explicitly states that Although the documentation for the ``random`` module explicitly states that
the default is not suitable for security purposes [#]_, it is strongly the default is not suitable for security purposes [#]_, it is strongly
believed that this warning may be missed, ignored or misunderstood by believed that this warning may be missed, ignored or misunderstood by
many Python developers. In particular: many Python developers. In particular:
* developers may not have read the documentation and consequently * developers may not have read the documentation and consequently
not seen the warning; not seen the warning;
* they may not realise that their specific use of the module has security * they may not realise that their specific use of the module has security
implications; or implications; or
* not realising that there could be a problem, they have copied code * not realising that there could be a problem, they have copied code
(or learned techniques) from websites which don't offer best (or learned techniques) from websites which don't offer best
practises. practises.
The first [#]_ hit when searching for "python how to generate passwords" on The first [#]_ hit when searching for "python how to generate passwords" on
Google is a tutorial that uses the default functions from the ``random`` Google is a tutorial that uses the default functions from the ``random``
module [#]_. Although it is not intended for use in web applications, it is module [#]_. Although it is not intended for use in web applications, it is
likely that similar techniques find themselves used in that situation. likely that similar techniques find themselves used in that situation.
The second hit is to a StackOverflow question about generating The second hit is to a StackOverflow question about generating
passwords [#]_. Most of the answers given, including the accepted one, use passwords [#]_. Most of the answers given, including the accepted one, use
the default functions. When one user warned that the default could be the default functions. When one user warned that the default could be
easily compromised, they were told "I think you worry too much." [#]_ easily compromised, they were told "I think you worry too much." [#]_
This strongly suggests that the existing ``random`` module is an attractive This strongly suggests that the existing ``random`` module is an attractive
nuisance when it comes to generating (for example) passwords or secure nuisance when it comes to generating (for example) passwords or secure
tokens. tokens.
Additional motivation (of a more philosophical bent) can be found in the Additional motivation (of a more philosophical bent) can be found in the
post which first proposed this idea [#]_. post which first proposed this idea [#]_.
Proposal Proposal
======== ========
Alternative proposals have focused on the default PRNG in the ``random`` Alternative proposals have focused on the default PRNG in the ``random``
module, with the aim of providing "secure by default" cryptographically module, with the aim of providing "secure by default" cryptographically
strong primitives that developers can build upon without thinking about strong primitives that developers can build upon without thinking about
security. (See Alternatives below.) This proposes a different approach: security. (See Alternatives below.) This proposes a different approach:
* The standard library already provides cryptographically strong * The standard library already provides cryptographically strong
primitives, but many users don't know they exist or when to use them. primitives, but many users don't know they exist or when to use them.
* Instead of requiring crypto-naive users to write secure code, the * Instead of requiring crypto-naive users to write secure code, the
standard library should include a set of ready-to-use "batteries" for standard library should include a set of ready-to-use "batteries" for
the most common needs, such as generating secure tokens. This code the most common needs, such as generating secure tokens. This code
will both directly satisfy a need ("How do I generate a password reset will both directly satisfy a need ("How do I generate a password reset
token?"), and act as an example of acceptable practises which token?"), and act as an example of acceptable practises which
developers can learn from [#]_. developers can learn from [#]_.
To do this, this PEP proposes that we add a new module to the standard To do this, this PEP proposes that we add a new module to the standard
library, with the suggested name ``secrets``. This module will contain a library, with the suggested name ``secrets``. This module will contain a
set of ready-to-use functions for common activities with security set of ready-to-use functions for common activities with security
implications, together with some lower-level primitives. implications, together with some lower-level primitives.
The suggestion is that ``secrets`` becomes the go-to module for dealing The suggestion is that ``secrets`` becomes the go-to module for dealing
with anything which should remain secret (passwords, tokens, etc.) with anything which should remain secret (passwords, tokens, etc.)
while the ``random`` module remains backward-compatible. while the ``random`` module remains backward-compatible.
API and Implementation API and Implementation
====================== ======================
This PEP proposes the following functions for the ``secrets`` module: This PEP proposes the following functions for the ``secrets`` module:
* Functions for generating tokens suitable for use in (e.g.) password * Functions for generating tokens suitable for use in (e.g.) password
recovery, as session keys, etc., in the following formats: recovery, as session keys, etc., in the following formats:
- as bytes, ``secrets.token_bytes``; - as bytes, ``secrets.token_bytes``;
- as text, using hexadecimal digits, ``secrets.token_hex``; - as text, using hexadecimal digits, ``secrets.token_hex``;
- as text, using URL-safe base-64 encoding, ``secrets.token_urlsafe``. - as text, using URL-safe base-64 encoding, ``secrets.token_urlsafe``.
* A limited interface to the system CSPRNG, using either ``os.urandom`` * A limited interface to the system CSPRNG, using either ``os.urandom``
directly or ``random.SystemRandom``. Unlike the ``random`` module, this directly or ``random.SystemRandom``. Unlike the ``random`` module, this
does not need to provide methods for seeding, getting or setting the does not need to provide methods for seeding, getting or setting the
state, or any non-uniform distributions. It should provide the state, or any non-uniform distributions. It should provide the
following: following:
- A function for choosing items from a sequence, ``secrets.choice``. - A function for choosing items from a sequence, ``secrets.choice``.
- A function for generating a given number of random bits and/or bytes - A function for generating a given number of random bits and/or bytes
as an integer, ``secrets.randbits``. as an integer, ``secrets.randbits``.
- A function for returning a random integer in the half-open range - A function for returning a random integer in the half-open range
0 to the given upper limit, ``secrets.randbelow`` [#]_. 0 to the given upper limit, ``secrets.randbelow`` [#]_.
* A function for comparing text or bytes digests for equality while being * A function for comparing text or bytes digests for equality while being
resistent to timing attacks, ``secrets.compare_digest``. resistent to timing attacks, ``secrets.compare_digest``.
The consensus appears to be that there is no need to add a new CSPRNG to The consensus appears to be that there is no need to add a new CSPRNG to
the ``random`` module to support these uses, ``SystemRandom`` will be the ``random`` module to support these uses, ``SystemRandom`` will be
sufficient. sufficient.
Some illustrative implementations have been given by Nick Coghlan [#]_ Some illustrative implementations have been given by Nick Coghlan [#]_
and a minimalist API by Tim Peters [#]_. This idea has also been discussed and a minimalist API by Tim Peters [#]_. This idea has also been discussed
on the issue tracker for the "cryptography" module [#]_. The following on the issue tracker for the "cryptography" module [#]_. The following
pseudo-code should be taken as the starting point for the real pseudo-code should be taken as the starting point for the real
implementation:: implementation::
from random import SystemRandom from random import SystemRandom
from hmac import compare_digest from hmac import compare_digest
_sysrand = SystemRandom() _sysrand = SystemRandom()
randbits = _sysrand.getrandbits randbits = _sysrand.getrandbits
choice = _sysrand.choice choice = _sysrand.choice
def randbelow(exclusive_upper_bound): def randbelow(exclusive_upper_bound):
return _sysrand._randbelow(exclusive_upper_bound) return _sysrand._randbelow(exclusive_upper_bound)
DEFAULT_ENTROPY = 32 # bytes DEFAULT_ENTROPY = 32 # bytes
def token_bytes(nbytes=None): def token_bytes(nbytes=None):
if nbytes is None: if nbytes is None:
nbytes = DEFAULT_ENTROPY nbytes = DEFAULT_ENTROPY
return os.urandom(nbytes) return os.urandom(nbytes)
def token_hex(nbytes=None): def token_hex(nbytes=None):
return binascii.hexlify(token_bytes(nbytes)).decode('ascii') return binascii.hexlify(token_bytes(nbytes)).decode('ascii')
def token_urlsafe(nbytes=None): def token_urlsafe(nbytes=None):
tok = token_bytes(nbytes) tok = token_bytes(nbytes)
return base64.urlsafe_b64encode(tok).rstrip(b'=').decode('ascii') return base64.urlsafe_b64encode(tok).rstrip(b'=').decode('ascii')
The ``secrets`` module itself will be pure Python, and other Python The ``secrets`` module itself will be pure Python, and other Python
implementations can easily make use of it unchanged, or adapt it as implementations can easily make use of it unchanged, or adapt it as
necessary. An implementation can be found on BitBucket [#]_. necessary. An implementation can be found on BitBucket [#]_.
Default arguments Default arguments
~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~
One difficult question is "How many bytes should my token be?". We can One difficult question is "How many bytes should my token be?". We can
help with this question by providing a default amount of entropy for the help with this question by providing a default amount of entropy for the
"token_*" functions. If the ``nbytes`` argument is None or not given, the "token_*" functions. If the ``nbytes`` argument is None or not given, the
default entropy will be used. This default value should be large enough default entropy will be used. This default value should be large enough
to be expected to be secure for medium-security uses, but is expected to to be expected to be secure for medium-security uses, but is expected to
change in the future, possibly even in a maintenance release [#]_. change in the future, possibly even in a maintenance release [#]_.
Naming conventions Naming conventions
~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~
One question is the naming conventions used in the module [#]_, whether to One question is the naming conventions used in the module [#]_, whether to
use C-like naming conventions such as "randrange" or more Pythonic names use C-like naming conventions such as "randrange" or more Pythonic names
such as "random_range". such as "random_range".
Functions which are simply bound methods of the private ``SystemRandom`` Functions which are simply bound methods of the private ``SystemRandom``
instance (e.g. ``randrange``), or a thin wrapper around such, should keep instance (e.g. ``randrange``), or a thin wrapper around such, should keep
the familiar names. Those which are something new (such as the various the familiar names. Those which are something new (such as the various
``token_*`` functions) will use more Pythonic names. ``token_*`` functions) will use more Pythonic names.
Alternatives Alternatives
============ ============
One alternative is to change the default PRNG provided by the ``random`` One alternative is to change the default PRNG provided by the ``random``
module [#]_. This received considerable scepticism and outright opposition: module [#]_. This received considerable scepticism and outright opposition:
* There is fear that a CSPRNG may be slower than the current PRNG (which * There is fear that a CSPRNG may be slower than the current PRNG (which
in the case of MT is already quite slow). in the case of MT is already quite slow).
* Some applications (such as scientific simulations, and replaying * Some applications (such as scientific simulations, and replaying
gameplay) require the ability to seed the PRNG into a known state, gameplay) require the ability to seed the PRNG into a known state,
which a CSPRNG lacks by design. which a CSPRNG lacks by design.
* Another major use of the ``random`` module is for simple "guess a number" * Another major use of the ``random`` module is for simple "guess a number"
games written by beginners, and many people are loath to make any games written by beginners, and many people are loath to make any
change to the ``random`` module which may make that harder. change to the ``random`` module which may make that harder.
* Although there is no proposal to remove MT from the ``random`` module, * Although there is no proposal to remove MT from the ``random`` module,
there was considerable hostility to the idea of having to opt-in to there was considerable hostility to the idea of having to opt-in to
a non-CSPRNG or any backwards-incompatible changes. a non-CSPRNG or any backwards-incompatible changes.
* Demonstrated attacks against MT are typically against PHP applications. * Demonstrated attacks against MT are typically against PHP applications.
It is believed that PHP's version of MT is a significantly softer target It is believed that PHP's version of MT is a significantly softer target
than Python's version, due to a poor seeding technique [#]_. Consequently, than Python's version, due to a poor seeding technique [#]_. Consequently,
without a proven attack against Python applications, many people object without a proven attack against Python applications, many people object
to a backwards-incompatible change. to a backwards-incompatible change.
Nick Coghlan made an earlier suggestion for a globally configurable PRNG Nick Coghlan made an earlier suggestion for a globally configurable PRNG
which uses the system CSPRNG by default [#]_, but has since withdrawn it which uses the system CSPRNG by default [#]_, but has since withdrawn it
in favour of this proposal. in favour of this proposal.
Comparison To Other Languages Comparison To Other Languages
============================= =============================
* PHP * PHP
PHP includes a function ``uniqid`` [#]_ which by default returns a PHP includes a function ``uniqid`` [#]_ which by default returns a
thirteen character string based on the current time in microseconds. thirteen character string based on the current time in microseconds.
Translated into Python syntax, it has the following signature:: Translated into Python syntax, it has the following signature::
def uniqid(prefix='', more_entropy=False)->str def uniqid(prefix='', more_entropy=False)->str
The PHP documentation warns that this function is not suitable for The PHP documentation warns that this function is not suitable for
security purposes. Nevertheless, various mature, well-known PHP security purposes. Nevertheless, various mature, well-known PHP
applications use it for that purpose (citation needed). applications use it for that purpose (citation needed).
PHP 5.3 and better also includes a function ``openssl_random_pseudo_bytes`` PHP 5.3 and better also includes a function ``openssl_random_pseudo_bytes``
[#]_. Translated into Python syntax, it has roughly the following [#]_. Translated into Python syntax, it has roughly the following
signature:: signature::
def openssl_random_pseudo_bytes(length:int)->Tuple[str, bool] def openssl_random_pseudo_bytes(length:int)->Tuple[str, bool]
This function returns a pseudo-random string of bytes of the given This function returns a pseudo-random string of bytes of the given
length, and an boolean flag giving whether the string is considered length, and an boolean flag giving whether the string is considered
cryptographically strong. The PHP manual suggests that returning cryptographically strong. The PHP manual suggests that returning
anything but True should be rare except for old or broken platforms. anything but True should be rare except for old or broken platforms.
* JavaScript * JavaScript
Based on a rather cursory search [#]_, there do not appear to be any Based on a rather cursory search [#]_, there do not appear to be any
well-known standard functions for producing strong random values in well-known standard functions for producing strong random values in
JavaScript. ``Math.random`` is often used, despite serious weaknesses JavaScript. ``Math.random`` is often used, despite serious weaknesses
making it unsuitable for cryptographic purposes [#]_. In recent years making it unsuitable for cryptographic purposes [#]_. In recent years
the majority of browsers have gained support for ``window.crypto.getRandomValues`` [#]_. the majority of browsers have gained support for ``window.crypto.getRandomValues`` [#]_.
Node.js offers a rich cryptographic module, ``crypto`` [#]_, most of Node.js offers a rich cryptographic module, ``crypto`` [#]_, most of
which is beyond the scope of this PEP. It does include a single function which is beyond the scope of this PEP. It does include a single function
for generating random bytes, ``crypto.randomBytes``. for generating random bytes, ``crypto.randomBytes``.
* Ruby * Ruby
The Ruby standard library includes a module ``SecureRandom`` [#]_ The Ruby standard library includes a module ``SecureRandom`` [#]_
which includes the following methods: which includes the following methods:
* base64 - returns a Base64 encoded random string. * base64 - returns a Base64 encoded random string.
* hex - returns a random hexadecimal string. * hex - returns a random hexadecimal string.
* random_bytes - returns a random byte string. * random_bytes - returns a random byte string.
* random_number - depending on the argument, returns either a random * random_number - depending on the argument, returns either a random
integer in the range(0, n), or a random float between 0.0 and 1.0. integer in the range(0, n), or a random float between 0.0 and 1.0.
* urlsafe_base64 - returns a random URL-safe Base64 encoded string. * urlsafe_base64 - returns a random URL-safe Base64 encoded string.
* uuid - return a version 4 random Universally Unique IDentifier. * uuid - return a version 4 random Universally Unique IDentifier.
What Should Be The Name Of The Module? What Should Be The Name Of The Module?
====================================== ======================================
There was a proposal to add a "random.safe" submodule, quoting the Zen There was a proposal to add a "random.safe" submodule, quoting the Zen
of Python "Namespaces are one honking great idea" koan. However, the of Python "Namespaces are one honking great idea" koan. However, the
author of the Zen, Tim Peters, has come out against this idea [#]_, and author of the Zen, Tim Peters, has come out against this idea [#]_, and
recommends a top-level module. recommends a top-level module.
In discussion on the python-ideas mailing list so far, the name "secrets" In discussion on the python-ideas mailing list so far, the name "secrets"
has received some approval, and no strong opposition. has received some approval, and no strong opposition.
There is already an existing third-party module with the same name [#]_, There is already an existing third-party module with the same name [#]_,
but it appears to be unused and abandoned. but it appears to be unused and abandoned.
Frequently Asked Questions Frequently Asked Questions
========================== ==========================
* Q: Is this a real problem? Surely MT is random enough that nobody can * Q: Is this a real problem? Surely MT is random enough that nobody can
predict its output. predict its output.
A: The consensus among security professionals is that MT is not safe A: The consensus among security professionals is that MT is not safe
in security contexts. It is not difficult to reconstruct the internal in security contexts. It is not difficult to reconstruct the internal
state of MT [#]_ [#]_ and so predict all past and future values. There state of MT [#]_ [#]_ and so predict all past and future values. There
are a number of known, practical attacks on systems using MT for are a number of known, practical attacks on systems using MT for
randomness [#]_. randomness [#]_.
While there are currently no known direct attacks on applications While there are currently no known direct attacks on applications
written in Python due to the use of MT, there is widespread agreement written in Python due to the use of MT, there is widespread agreement
that such usage is unsafe. that such usage is unsafe.
* Q: Is this an alternative to specialise cryptographic software such as SSL? * Q: Is this an alternative to specialise cryptographic software such as SSL?
A: No. This is a "batteries included" solution, not a full-featured A: No. This is a "batteries included" solution, not a full-featured
"nuclear reactor". It is intended to mitigate against some basic "nuclear reactor". It is intended to mitigate against some basic
security errors, not be a solution to all security-related issues. To security errors, not be a solution to all security-related issues. To
quote Nick Coghlan referring to his earlier proposal [#]_:: quote Nick Coghlan referring to his earlier proposal [#]_::
"...folks really are better off learning to use things like "...folks really are better off learning to use things like
cryptography.io for security sensitive software, so this change cryptography.io for security sensitive software, so this change
is just about harm mitigation given that it's inevitable that a is just about harm mitigation given that it's inevitable that a
non-trivial proportion of the millions of current and future non-trivial proportion of the millions of current and future
Python developers won't do that." Python developers won't do that."
* Q: What about a password generator? * Q: What about a password generator?
A: The consensus is that the requirements for password generators are too A: The consensus is that the requirements for password generators are too
variable for it to be a good match for the standard library [#]_. No variable for it to be a good match for the standard library [#]_. No
password generator will be included in the initial release of the password generator will be included in the initial release of the
module, instead it will be given in the documentation as a recipe (à la module, instead it will be given in the documentation as a recipe (à la
the recipes in the ``itertools`` module) [#]_. the recipes in the ``itertools`` module) [#]_.
* Q: Will ``secrets`` use /dev/random (which blocks) or /dev/urandom (which * Q: Will ``secrets`` use /dev/random (which blocks) or /dev/urandom (which
doesn't block) on Linux? What about other platforms? doesn't block) on Linux? What about other platforms?
A: ``secrets`` will be based on ``os.urandom`` and ``random.SystemRandom``, A: ``secrets`` will be based on ``os.urandom`` and ``random.SystemRandom``,
which are interfaces to your operating system's best source of which are interfaces to your operating system's best source of
cryptographic randomness. On Linux, that may be ``/dev/urandom`` [#]_, cryptographic randomness. On Linux, that may be ``/dev/urandom`` [#]_,
on Windows it may be ``CryptGenRandom()``, but see the documentation on Windows it may be ``CryptGenRandom()``, but see the documentation
and/or source code for the detailed implementation details. and/or source code for the detailed implementation details.
References References
========== ==========
.. [#] https://mail.python.org/pipermail/python-ideas/2015-September/035820.html .. [#] https://mail.python.org/pipermail/python-ideas/2015-September/035820.html
.. [#] https://docs.python.org/3/library/random.html .. [#] https://docs.python.org/3/library/random.html
.. [#] As of the date of writing. Also, as Google search terms may be .. [#] As of the date of writing. Also, as Google search terms may be
automatically customised for the user without their knowledge, some automatically customised for the user without their knowledge, some
readers may see different results. readers may see different results.
.. [#] http://interactivepython.org/runestone/static/everyday/2013/01/3_password.html .. [#] http://interactivepython.org/runestone/static/everyday/2013/01/3_password.html
.. [#] http://stackoverflow.com/questions/3854692/generate-password-in-python .. [#] http://stackoverflow.com/questions/3854692/generate-password-in-python
.. [#] http://stackoverflow.com/questions/3854692/generate-password-in-python/3854766#3854766 .. [#] http://stackoverflow.com/questions/3854692/generate-password-in-python/3854766#3854766
.. [#] https://mail.python.org/pipermail/python-ideas/2015-September/036238.html .. [#] https://mail.python.org/pipermail/python-ideas/2015-September/036238.html
.. [#] At least those who are motivated to read the source code and documentation. .. [#] At least those who are motivated to read the source code and documentation.
.. [#] After considerable discussion, Guido ruled that the module need only .. [#] After considerable discussion, Guido ruled that the module need only
provide ``randbelow``, and not similar functions ``randrange`` or provide ``randbelow``, and not similar functions ``randrange`` or
``randint``. http://code.activestate.com/lists/python-dev/138375/ ``randint``. http://code.activestate.com/lists/python-dev/138375/
.. [#] https://mail.python.org/pipermail/python-ideas/2015-September/036271.html .. [#] https://mail.python.org/pipermail/python-ideas/2015-September/036271.html
.. [#] https://mail.python.org/pipermail/python-ideas/2015-September/036350.html .. [#] https://mail.python.org/pipermail/python-ideas/2015-September/036350.html
.. [#] https://github.com/pyca/cryptography/issues/2347 .. [#] https://github.com/pyca/cryptography/issues/2347
.. [#] https://bitbucket.org/sdaprano/secrets .. [#] https://bitbucket.org/sdaprano/secrets
.. [#] https://mail.python.org/pipermail/python-ideas/2015-September/036517.html .. [#] https://mail.python.org/pipermail/python-ideas/2015-September/036517.html
https://mail.python.org/pipermail/python-ideas/2015-September/036515.html https://mail.python.org/pipermail/python-ideas/2015-September/036515.html
.. [#] https://mail.python.org/pipermail/python-ideas/2015-September/036474.html .. [#] https://mail.python.org/pipermail/python-ideas/2015-September/036474.html
.. [#] Link needed. .. [#] Link needed.
.. [#] By default PHP seeds the MT PRNG with the time (citation needed), .. [#] By default PHP seeds the MT PRNG with the time (citation needed),
which is exploitable by attackers, while Python seeds the PRNG with which is exploitable by attackers, while Python seeds the PRNG with
output from the system CSPRNG, which is believed to be much harder to output from the system CSPRNG, which is believed to be much harder to
exploit. exploit.
.. [#] http://legacy.python.org/dev/peps/pep-0504/ .. [#] http://legacy.python.org/dev/peps/pep-0504/
.. [#] http://php.net/manual/en/function.uniqid.php .. [#] http://php.net/manual/en/function.uniqid.php
.. [#] http://php.net/manual/en/function.openssl-random-pseudo-bytes.php .. [#] http://php.net/manual/en/function.openssl-random-pseudo-bytes.php
.. [#] Volunteers and patches are welcome. .. [#] Volunteers and patches are welcome.
.. [#] http://ifsec.blogspot.fr/2012/05/cross-domain-mathrandom-prediction.html .. [#] http://ifsec.blogspot.fr/2012/05/cross-domain-mathrandom-prediction.html
.. [#] https://developer.mozilla.org/en-US/docs/Web/API/RandomSource/getRandomValues .. [#] https://developer.mozilla.org/en-US/docs/Web/API/RandomSource/getRandomValues
.. [#] https://nodejs.org/api/crypto.html .. [#] https://nodejs.org/api/crypto.html
.. [#] http://ruby-doc.org/stdlib-2.1.2/libdoc/securerandom/rdoc/SecureRandom.html .. [#] http://ruby-doc.org/stdlib-2.1.2/libdoc/securerandom/rdoc/SecureRandom.html
.. [#] https://mail.python.org/pipermail/python-ideas/2015-September/036254.html .. [#] https://mail.python.org/pipermail/python-ideas/2015-September/036254.html
.. [#] https://pypi.python.org/pypi/secrets .. [#] https://pypi.python.org/pypi/secrets
.. [#] https://jazzy.id.au/2010/09/22/cracking_random_number_generators_part_3.html .. [#] https://jazzy.id.au/2010/09/22/cracking_random_number_generators_part_3.html
.. [#] https://mail.python.org/pipermail/python-ideas/2015-September/036077.html .. [#] https://mail.python.org/pipermail/python-ideas/2015-September/036077.html
.. [#] https://media.blackhat.com/bh-us-12/Briefings/Argyros/BH_US_12_Argyros_PRNG_WP.pdf .. [#] https://media.blackhat.com/bh-us-12/Briefings/Argyros/BH_US_12_Argyros_PRNG_WP.pdf
.. [#] https://mail.python.org/pipermail/python-ideas/2015-September/036157.html .. [#] https://mail.python.org/pipermail/python-ideas/2015-September/036157.html
.. [#] https://mail.python.org/pipermail/python-ideas/2015-September/036476.html .. [#] https://mail.python.org/pipermail/python-ideas/2015-September/036476.html
https://mail.python.org/pipermail/python-ideas/2015-September/036478.html https://mail.python.org/pipermail/python-ideas/2015-September/036478.html
.. [#] https://mail.python.org/pipermail/python-ideas/2015-September/036488.html .. [#] https://mail.python.org/pipermail/python-ideas/2015-September/036488.html
.. [#] http://sockpuppet.org/blog/2014/02/25/safely-generate-random-numbers/ .. [#] http://sockpuppet.org/blog/2014/02/25/safely-generate-random-numbers/
http://www.2uo.de/myths-about-urandom/ http://www.2uo.de/myths-about-urandom/
Copyright Copyright
========= =========
This document has been placed in the public domain. This document has been placed in the public domain.
.. ..
Local Variables: Local Variables:
mode: indented-text mode: indented-text
indent-tabs-mode: nil indent-tabs-mode: nil
sentence-end-double-space: t sentence-end-double-space: t
fill-column: 70 fill-column: 70
coding: utf-8 coding: utf-8
End: End:

View File

@ -1,253 +1,253 @@
PEP: 514 PEP: 514
Title: Python registration in the Windows registry Title: Python registration in the Windows registry
Version: $Revision$ Version: $Revision$
Last-Modified: $Date$ Last-Modified: $Date$
Author: Steve Dower <steve.dower@python.org> Author: Steve Dower <steve.dower@python.org>
Status: Draft Status: Draft
Type: Informational Type: Informational
Content-Type: text/x-rst Content-Type: text/x-rst
Created: 02-Feb-2016 Created: 02-Feb-2016
Post-History: 02-Feb-2016, 01-Mar-2016 Post-History: 02-Feb-2016, 01-Mar-2016
Abstract Abstract
======== ========
This PEP defines a schema for the Python registry key to allow third-party This PEP defines a schema for the Python registry key to allow third-party
installers to register their installation, and to allow applications to detect installers to register their installation, and to allow applications to detect
and correctly display all Python environments on a user's machine. No and correctly display all Python environments on a user's machine. No
implementation changes to Python are proposed with this PEP. implementation changes to Python are proposed with this PEP.
Python environments are not required to be registered unless they want to be Python environments are not required to be registered unless they want to be
automatically discoverable by external tools. automatically discoverable by external tools.
The schema matches the registry values that have been used by the official The schema matches the registry values that have been used by the official
installer since at least Python 2.5, and the resolution behaviour matches the installer since at least Python 2.5, and the resolution behaviour matches the
behaviour of the official Python releases. behaviour of the official Python releases.
Motivation Motivation
========== ==========
When installed on Windows, the official Python installer creates a registry key When installed on Windows, the official Python installer creates a registry key
for discovery and detection by other applications. This allows tools such as for discovery and detection by other applications. This allows tools such as
installers or IDEs to automatically detect and display a user's Python installers or IDEs to automatically detect and display a user's Python
installations. installations.
Third-party installers, such as those used by distributions, typically create Third-party installers, such as those used by distributions, typically create
identical keys for the same purpose. Most tools that use the registry to detect identical keys for the same purpose. Most tools that use the registry to detect
Python installations only inspect the keys used by the official installer. As a Python installations only inspect the keys used by the official installer. As a
result, third-party installations that wish to be discoverable will overwrite result, third-party installations that wish to be discoverable will overwrite
these values, resulting in users "losing" their Python installation. these values, resulting in users "losing" their Python installation.
By describing a layout for registry keys that allows third-party installations By describing a layout for registry keys that allows third-party installations
to register themselves uniquely, as well as providing tool developers guidance to register themselves uniquely, as well as providing tool developers guidance
for discovering all available Python installations, these collisions should be for discovering all available Python installations, these collisions should be
prevented. prevented.
Definitions Definitions
=========== ===========
A "registry key" is the equivalent of a file-system path into the registry. Each A "registry key" is the equivalent of a file-system path into the registry. Each
key may contain "subkeys" (keys nested within keys) and "values" (named and key may contain "subkeys" (keys nested within keys) and "values" (named and
typed attributes attached to a key). typed attributes attached to a key).
``HKEY_CURRENT_USER`` is the root of settings for the currently logged-in user, ``HKEY_CURRENT_USER`` is the root of settings for the currently logged-in user,
and this user can generally read and write all settings under this root. and this user can generally read and write all settings under this root.
``HKEY_LOCAL_MACHINE`` is the root of settings for all users. Generally, any ``HKEY_LOCAL_MACHINE`` is the root of settings for all users. Generally, any
user can read these settings but only administrators can modify them. It is user can read these settings but only administrators can modify them. It is
typical for values under ``HKEY_CURRENT_USER`` to take precedence over those in typical for values under ``HKEY_CURRENT_USER`` to take precedence over those in
``HKEY_LOCAL_MACHINE``. ``HKEY_LOCAL_MACHINE``.
On 64-bit Windows, ``HKEY_LOCAL_MACHINE\Software\Wow6432Node`` is a special key On 64-bit Windows, ``HKEY_LOCAL_MACHINE\Software\Wow6432Node`` is a special key
that 32-bit processes transparently read and write to rather than accessing the that 32-bit processes transparently read and write to rather than accessing the
``Software`` key directly. ``Software`` key directly.
Structure Structure
========= =========
We consider there to be a single collection of Python environments on a machine, We consider there to be a single collection of Python environments on a machine,
where the collection may be different for each user of the machine. There are where the collection may be different for each user of the machine. There are
three potential registry locations where the collection may be stored based on three potential registry locations where the collection may be stored based on
the installation options of each environment:: the installation options of each environment::
HKEY_CURRENT_USER\Software\Python\<Company>\<Tag> HKEY_CURRENT_USER\Software\Python\<Company>\<Tag>
HKEY_LOCAL_MACHINE\Software\Python\<Company>\<Tag> HKEY_LOCAL_MACHINE\Software\Python\<Company>\<Tag>
HKEY_LOCAL_MACHINE\Software\Wow6432Node\Python\<Company>\<Tag> HKEY_LOCAL_MACHINE\Software\Wow6432Node\Python\<Company>\<Tag>
Environments are uniquely identified by their Company-Tag pair, with two options Environments are uniquely identified by their Company-Tag pair, with two options
for conflict resolution: include everything, or give priority to user for conflict resolution: include everything, or give priority to user
preferences. preferences.
Tools that include every installed environment, even where the Company-Tag pairs Tools that include every installed environment, even where the Company-Tag pairs
match, should ensure users can easily identify whether the registration was match, should ensure users can easily identify whether the registration was
per-user or per-machine. per-user or per-machine.
When tools are selecting a single installed environment from all registered When tools are selecting a single installed environment from all registered
environments, the intent is that user preferences from ``HKEY_CURRENT_USER`` environments, the intent is that user preferences from ``HKEY_CURRENT_USER``
will override matching Company-Tag pairs in ``HKEY_LOCAL_MACHINE``. will override matching Company-Tag pairs in ``HKEY_LOCAL_MACHINE``.
Official Python releases use ``PythonCore`` for Company, and the value of Official Python releases use ``PythonCore`` for Company, and the value of
``sys.winver`` for Tag. Other registered environments may use any values for ``sys.winver`` for Tag. Other registered environments may use any values for
Company and Tag. Recommendations are made in the following sections. Company and Tag. Recommendations are made in the following sections.
Python environments are not required to register themselves unless they want to Python environments are not required to register themselves unless they want to
be automatically discoverable by external tools. be automatically discoverable by external tools.
Backwards Compatibility Backwards Compatibility
----------------------- -----------------------
Python 3.4 and earlier did not distinguish between 32-bit and 64-bit builds in Python 3.4 and earlier did not distinguish between 32-bit and 64-bit builds in
``sys.winver``. As a result, it is possible to have valid side-by-side ``sys.winver``. As a result, it is possible to have valid side-by-side
installations of both 32-bit and 64-bit interpreters. installations of both 32-bit and 64-bit interpreters.
To ensure backwards compatibility, applications should treat environments listed To ensure backwards compatibility, applications should treat environments listed
under the following two registry keys as distinct, even when the Tag matches:: under the following two registry keys as distinct, even when the Tag matches::
HKEY_LOCAL_MACHINE\Software\Python\PythonCore\<Tag> HKEY_LOCAL_MACHINE\Software\Python\PythonCore\<Tag>
HKEY_LOCAL_MACHINE\Software\Wow6432Node\Python\PythonCore\<Tag> HKEY_LOCAL_MACHINE\Software\Wow6432Node\Python\PythonCore\<Tag>
Environments listed under ``HKEY_CURRENT_USER`` may be treated as distinct from Environments listed under ``HKEY_CURRENT_USER`` may be treated as distinct from
both of the above keys, potentially resulting in three environments discovered both of the above keys, potentially resulting in three environments discovered
using the same Tag. Alternatively, a tool may determine whether the per-user using the same Tag. Alternatively, a tool may determine whether the per-user
environment is 64-bit or 32-bit and give it priority over the per-machine environment is 64-bit or 32-bit and give it priority over the per-machine
environment, resulting in a maximum of two discovered environments. environment, resulting in a maximum of two discovered environments.
It is not possible to detect side-by-side installations of both 64-bit and It is not possible to detect side-by-side installations of both 64-bit and
32-bit versions of Python prior to 3.5 when they have been installed for the 32-bit versions of Python prior to 3.5 when they have been installed for the
current user. Python 3.5 and later always uses different Tags for 64-bit and current user. Python 3.5 and later always uses different Tags for 64-bit and
32-bit versions. 32-bit versions.
Environments registered under other Company names must use distinct Tags to Environments registered under other Company names must use distinct Tags to
support side-by-side installations. Tools consuming these registrations are support side-by-side installations. Tools consuming these registrations are
not required to disambiguate tags other than by preferring the user's setting. not required to disambiguate tags other than by preferring the user's setting.
Company Company
------- -------
The Company part of the key is intended to group related environments and to The Company part of the key is intended to group related environments and to
ensure that Tags are namespaced appropriately. The key name should be ensure that Tags are namespaced appropriately. The key name should be
alphanumeric without spaces and likely to be unique. For example, a trademarked alphanumeric without spaces and likely to be unique. For example, a trademarked
name, a UUID, or a hostname would be appropriate:: name, a UUID, or a hostname would be appropriate::
HKEY_CURRENT_USER\Software\Python\ExampleCorp HKEY_CURRENT_USER\Software\Python\ExampleCorp
HKEY_CURRENT_USER\Software\Python\6C465E66-5A8C-4942-9E6A-D29159480C60 HKEY_CURRENT_USER\Software\Python\6C465E66-5A8C-4942-9E6A-D29159480C60
HKEY_CURRENT_USER\Software\Python\www.example.com HKEY_CURRENT_USER\Software\Python\www.example.com
The company name ``PyLauncher`` is reserved for the PEP 397 launcher The company name ``PyLauncher`` is reserved for the PEP 397 launcher
(``py.exe``). It does not follow this convention and should be ignored by tools. (``py.exe``). It does not follow this convention and should be ignored by tools.
If a string value named ``DisplayName`` exists, it should be used to identify If a string value named ``DisplayName`` exists, it should be used to identify
the environment category to users. Otherwise, the name of the key should be the environment category to users. Otherwise, the name of the key should be
used. used.
If a string value named ``SupportUrl`` exists, it may be displayed or otherwise If a string value named ``SupportUrl`` exists, it may be displayed or otherwise
used to direct users to a web site related to the environment. used to direct users to a web site related to the environment.
A complete example may look like:: A complete example may look like::
HKEY_CURRENT_USER\Software\Python\ExampleCorp HKEY_CURRENT_USER\Software\Python\ExampleCorp
(Default) = (value not set) (Default) = (value not set)
DisplayName = "Example Corp" DisplayName = "Example Corp"
SupportUrl = "http://www.example.com" SupportUrl = "http://www.example.com"
Tag Tag
--- ---
The Tag part of the key is intended to uniquely identify an environment within The Tag part of the key is intended to uniquely identify an environment within
those provided by a single company. The key name should be alphanumeric without those provided by a single company. The key name should be alphanumeric without
spaces and stable across installations. For example, the Python language spaces and stable across installations. For example, the Python language
version, a UUID or a partial/complete hash would be appropriate; an integer version, a UUID or a partial/complete hash would be appropriate; an integer
counter that increases for each new environment may not:: counter that increases for each new environment may not::
HKEY_CURRENT_USER\Software\Python\ExampleCorp\3.6 HKEY_CURRENT_USER\Software\Python\ExampleCorp\3.6
HKEY_CURRENT_USER\Software\Python\ExampleCorp\6C465E66 HKEY_CURRENT_USER\Software\Python\ExampleCorp\6C465E66
If a string value named ``DisplayName`` exists, it should be used to identify If a string value named ``DisplayName`` exists, it should be used to identify
the environment to users. Otherwise, the name of the key should be used. the environment to users. Otherwise, the name of the key should be used.
If a string value named ``SupportUrl`` exists, it may be displayed or otherwise If a string value named ``SupportUrl`` exists, it may be displayed or otherwise
used to direct users to a web site related to the environment. used to direct users to a web site related to the environment.
If a string value named ``Version`` exists, it should be used to identify the If a string value named ``Version`` exists, it should be used to identify the
version of the environment. This is independent from the version of Python version of the environment. This is independent from the version of Python
implemented by the environment. implemented by the environment.
If a string value named ``SysVersion`` exists, it must be in ``x.y`` or If a string value named ``SysVersion`` exists, it must be in ``x.y`` or
``x.y.z`` format matching the version returned by ``sys.version_info`` in the ``x.y.z`` format matching the version returned by ``sys.version_info`` in the
interpreter. Otherwise, if the Tag matches this format it is used. If not, the interpreter. Otherwise, if the Tag matches this format it is used. If not, the
Python version is unknown. Python version is unknown.
Note that each of these values is recommended, but optional. A complete example Note that each of these values is recommended, but optional. A complete example
may look like this:: may look like this::
HKEY_CURRENT_USER\Software\Python\ExampleCorp\6C465E66 HKEY_CURRENT_USER\Software\Python\ExampleCorp\6C465E66
(Default) = (value not set) (Default) = (value not set)
DisplayName = "Distro 3" DisplayName = "Distro 3"
SupportUrl = "http://www.example.com/distro-3" SupportUrl = "http://www.example.com/distro-3"
Version = "3.0.12345.0" Version = "3.0.12345.0"
SysVersion = "3.6.0" SysVersion = "3.6.0"
InstallPath InstallPath
----------- -----------
Beneath the environment key, an ``InstallPath`` key must be created. This key is Beneath the environment key, an ``InstallPath`` key must be created. This key is
always named ``InstallPath``, and the default value must match ``sys.prefix``:: always named ``InstallPath``, and the default value must match ``sys.prefix``::
HKEY_CURRENT_USER\Software\Python\ExampleCorp\3.6\InstallPath HKEY_CURRENT_USER\Software\Python\ExampleCorp\3.6\InstallPath
(Default) = "C:\ExampleCorpPy36" (Default) = "C:\ExampleCorpPy36"
If a string value named ``ExecutablePath`` exists, it must be a path to the If a string value named ``ExecutablePath`` exists, it must be a path to the
``python.exe`` (or equivalent) executable. Otherwise, the interpreter executable ``python.exe`` (or equivalent) executable. Otherwise, the interpreter executable
is assumed to be called ``python.exe`` and exist in the directory referenced by is assumed to be called ``python.exe`` and exist in the directory referenced by
the default value. the default value.
If a string value named ``WindowedExecutablePath`` exists, it must be a path to If a string value named ``WindowedExecutablePath`` exists, it must be a path to
the ``pythonw.exe`` (or equivalent) executable. Otherwise, the windowed the ``pythonw.exe`` (or equivalent) executable. Otherwise, the windowed
interpreter executable is assumed to be called ``pythonw.exe`` and exist in the interpreter executable is assumed to be called ``pythonw.exe`` and exist in the
directory referenced by the default value. directory referenced by the default value.
A complete example may look like:: A complete example may look like::
HKEY_CURRENT_USER\Software\Python\ExampleCorp\6C465E66\InstallPath HKEY_CURRENT_USER\Software\Python\ExampleCorp\6C465E66\InstallPath
(Default) = "C:\ExampleDistro30" (Default) = "C:\ExampleDistro30"
ExecutablePath = "C:\ExampleDistro30\ex_python.exe" ExecutablePath = "C:\ExampleDistro30\ex_python.exe"
WindowedExecutablePath = "C:\ExampleDistro30\ex_pythonw.exe" WindowedExecutablePath = "C:\ExampleDistro30\ex_pythonw.exe"
Help Help
---- ----
Beneath the environment key, a ``Help`` key may be created. This key is always Beneath the environment key, a ``Help`` key may be created. This key is always
named ``Help`` if present and has no default value. named ``Help`` if present and has no default value.
Each subkey of ``Help`` specifies a documentation file, tool, or URL associated Each subkey of ``Help`` specifies a documentation file, tool, or URL associated
with the environment. The subkey may have any name, and the default value is a with the environment. The subkey may have any name, and the default value is a
string appropriate for passing to ``os.startfile`` or equivalent. string appropriate for passing to ``os.startfile`` or equivalent.
If a string value named ``DisplayName`` exists, it should be used to identify If a string value named ``DisplayName`` exists, it should be used to identify
the help file to users. Otherwise, the key name should be used. the help file to users. Otherwise, the key name should be used.
A complete example may look like:: A complete example may look like::
HKEY_CURRENT_USER\Software\Python\ExampleCorp\6C465E66\Help HKEY_CURRENT_USER\Software\Python\ExampleCorp\6C465E66\Help
Python\ Python\
(Default) = "C:\ExampleDistro30\python36.chm" (Default) = "C:\ExampleDistro30\python36.chm"
DisplayName = "Python Documentation" DisplayName = "Python Documentation"
Extras\ Extras\
(Default) = "http://www.example.com/tutorial" (Default) = "http://www.example.com/tutorial"
DisplayName = "Example Distro Online Tutorial" DisplayName = "Example Distro Online Tutorial"
Other Keys Other Keys
---------- ----------
Some other registry keys are used for defining or inferring search paths under Some other registry keys are used for defining or inferring search paths under
certain conditions. A third-party installation is permitted to define these keys certain conditions. A third-party installation is permitted to define these keys
under their Company-Tag key, however, the interpreter must be modified and under their Company-Tag key, however, the interpreter must be modified and
rebuilt in order to read these values. Alternatively, the interpreter may be rebuilt in order to read these values. Alternatively, the interpreter may be
modified to not use any registry keys for determining search paths. Making such modified to not use any registry keys for determining search paths. Making such
changes is a decision for the third party; this PEP makes no recommendation changes is a decision for the third party; this PEP makes no recommendation
either way. either way.
Copyright Copyright
========= =========
This document has been placed in the public domain. This document has been placed in the public domain.