pep-0427 edits

This commit is contained in:
Daniel Holth 2012-10-27 15:57:47 -04:00
parent c42dc66be1
commit f1535d9c8c
1 changed files with 83 additions and 55 deletions

View File

@ -93,7 +93,7 @@ Recommended installer features
Rewrite ``#!python``. Rewrite ``#!python``.
In wheel, scripts are packaged in In wheel, scripts are packaged in
``{distribution}-{version}.data/scripts/``. If the first line of ``{distribution}-{version}.data/scripts/``. If the first line of
a file in ``scripts/`` starts with exactly b'#!python', rewrite to a file in ``scripts/`` starts with exactly ``b'#!python'``, rewrite to
point to the correct interpreter. Unix installers may need to add point to the correct interpreter. Unix installers may need to add
the +x bit to these files if the archive was created on Windows. the +x bit to these files if the archive was created on Windows.
@ -146,12 +146,26 @@ package's basic interpreter requirements and are detailed in PEP 425.
File contents File contents
''''''''''''' '''''''''''''
#. Wheel files contain a folder {distribution}-{version}.dist-info/ The conents of a wheel file, where {distribution} is replaced with the
with the PEP 426 metadata (Metadata version 1.3 or greater) and an name of the package, e.g. ``beaglevote`` and {version} is replaced with
additional file WHEEL with metadata about the archive itself. its version, e.g. ``1.0.0``, consist of:
#. The root of a .whl is installed into one of purelib or platlib.
#. Wheel files contain metadata about the wheel format itself in #. ``/``, the root of the archive, contains all files to be installed in
``{distribution}-{version}.dist-info/WHEEL``:: ``purelib`` or ``platlib`` as specified in ``WHEEL``. ``purelib`` and
``platlib`` are usually both ``site-packages``.
#. ``{distribution}-{version}.dist-info/`` contains metadata.
#. ``{distribution}-{version}.data/`` contains one subdirectory
for each non-empty install scheme key not already covered, where
the subdirectory name is an index into a dictionary of install paths
(e.g. ``data``, ``scripts``, ``include``, ``purelib`, ``platlib``).
#. Python scripts must appear in ``scripts`` and begin with exactly
``b'#!python'`` in order to enjoy script wrapper generation and
``#!python`` rewriting at install time. They may have any or no
extension.
#. ``{distribution}-{version}.dist-info/METADATA`` is Metadata version 1.3
(PEP 426) or greater format metadata.
#. ``{distribution}-{version}.dist-info/WHEEL`` is metadata about the archive
itself::
Wheel-Version: 0.1 Wheel-Version: 0.1
Generator: bdist_wheel 0.7 Generator: bdist_wheel 0.7
@ -163,16 +177,17 @@ File contents
directory of the archive should be installed into purelib; directory of the archive should be installed into purelib;
otherwise the root should be installed into platlib. otherwise the root should be installed into platlib.
#. A wheel installer should warn if Wheel-Version is greater than the #. A wheel installer should warn if Wheel-Version is greater than the
version it supports, and fail if Wheel-Version has a greater major version it supports, and must fail if Wheel-Version has a greater
version than the version it supports. major version than the version it supports.
#. If a .whl contains scripts, both purelib and platlib, or any other
files that are not installed on ``sys.path``, they are found in
``{distribution}-{version}.data/{key}``, where ``{key}`` is an
index into a dictionary of install paths.
#. Wheel, being an installation format that is intended to work across #. Wheel, being an installation format that is intended to work across
multiple versions of Python, does not generally include .pyc files. multiple versions of Python, does not generally include .pyc files.
#. Wheel does not contain setup.py or setup.cfg. #. Wheel does not contain setup.py or setup.cfg.
This version of the wheel specification is based on the distutils install
schemes and does not define how to install files to other locations.
The layout offers a superset of the functionality provided by the existing
wininst and egg binary formats.
The .dist-info directory The .dist-info directory
^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^
@ -232,10 +247,11 @@ RECORD.jws is not mentioned in RECORD at all. Every other file in the
archive must have a correct hash in RECORD, or the installation will archive must have a correct hash in RECORD, or the installation will
fail. fail.
The signature is one or more JSON Web Signature JSON Serialization The signature format is derived from the JSON Web Signatures (JWS)
(JWS-JS) signatures stored in a file RECORD.jws adjacent to RECORD. specification. One or more JSON Web Signature JSON Serialization (JWS-JS)
signatures may be stored in a file RECORD.jws adjacent to RECORD.
A signature-aware installer can be instructed to check for a A signature-aware installer could be instructed to check for a
particular Ed25519 public key by using an extended "extras" syntax.:: particular Ed25519 public key by using an extended "extras" syntax.::
# request a normal optional feature "extra", and indicate # request a normal optional feature "extra", and indicate
@ -243,43 +259,36 @@ particular Ed25519 public key by using an extended "extras" syntax.::
# urlsafe-b64encode-nopad encoded ed25519 public key: # urlsafe-b64encode-nopad encoded ed25519 public key:
package[extra, ed25519=ouBJlTJJ4SJXoy8Bi1KRlewWLU6JW7HUXTgvU1YRuiA] package[extra, ed25519=ouBJlTJJ4SJXoy8Bi1KRlewWLU6JW7HUXTgvU1YRuiA]
An application could distribute a requires.txt file with many such An application could distribute a requires.txt file with many such lines
lines for all its dependencies and their public keys. By installing for all its dependencies and their public keys. By installing from this
from this file an application's users would know whether the file an application's users can know they are getting packages from the
application's dependencies came from the correct publishers. same publishers.
Applications that wish to "fail open" for backwards compatibility with Applications that wish to "fail open" for backwards compatibility with
non-signature-aware installers should specify that their package non-signature-aware installers should specify that their package
provides the extra ``ed25519=(key)`` with no associated dependencies. provides the extra ``ed25519=(key)`` with no associated dependencies.
Key distribution is outside the scope of this spec. Public wheel
signing keys could be signed with the packager's GPG key or stored at
an ``https://`` protected URL.
JSON Web Signatures Extensions JSON Web Signatures Extensions
'''''''''''''''''''''''''''''' ''''''''''''''''''''''''''''''
The Ed25519 algorithm is used as an extension to the JSON Web The Ed25519 algorithm is used as an extension to the JSON Web Signatures
Signatures specification. Wheel uses ``alg="Ed25519"`` in the header. specification. Wheel uses ``alg="Ed25519"`` in the header. The key
The key attribute holds the signature's public JSON Web Key. For JSON attribute holds the signature's public JSON Web Key. In JSON Web Key
Web Key / JSON Private Key the verifying (public) key is called vk and / JSON Private Key the Ed25519 verifying (public) key is called vk and
the signing (private) key is called sk. the signing (private) key is called sk.
Example header:: Example header::
{ {
"alg": "Ed25519", "alg": "Ed25519",
"typ": "JWT", "jwk": {
"key": { "alg": "Ed25519",
"alg": "Ed25519", "vk": "tmAYCrSfj8gtJ10v3VkvW7jOndKmQIYE12hgnFu3cvk"
"vk": "tmAYCrSfj8gtJ10v3VkvW7jOndKmQIYE12hgnFu3cvk" }
}
} }
A future version of wheel may omit ``typ``. Example payload, always the SHA-256 hash of RECORD::
Example payload::
{ "hash": "sha256=ADD-r2urObZHcxBW3Cr-vDCu5RJwT4CaRTHiFmbcIYY" } { "hash": "sha256=ADD-r2urObZHcxBW3Cr-vDCu5RJwT4CaRTHiFmbcIYY" }
@ -292,6 +301,7 @@ See
- http://self-issued.info/docs/draft-jones-jose-jws-json-serialization.html - http://self-issued.info/docs/draft-jones-jose-jws-json-serialization.html
- http://self-issued.info/docs/draft-ietf-jose-json-web-key.html - http://self-issued.info/docs/draft-ietf-jose-json-web-key.html
- http://self-issued.info/docs/draft-jones-jose-json-private-key.html - http://self-issued.info/docs/draft-jones-jose-json-private-key.html
- http://ed25519.cr.yp.to/
Comparison to .egg Comparison to .egg
@ -328,29 +338,47 @@ Wheel defines a .data directory. Should I put all my data there?
This specification does not have an opinion on how you should organize This specification does not have an opinion on how you should organize
your code. The .data directory is just a place for any files that are your code. The .data directory is just a place for any files that are
not normally installed inside ``site-packages`` or on the PYTHONPATH. not normally installed inside ``site-packages`` or on the PYTHONPATH.
In other words, you may continue to use ``pkgutil.get_data(package,
resource)`` even though *those* files will usually not be distributed
in *wheel's* ``.data`` directory.
Why are you using Ed25519 and JWS instead of PGP, S/MIME, or ECDSA? Why are you using Ed25519 and JWS instead of PGP, S/MIME, or ECDSA?
Wheel's signing scheme is designed to protect against cryptography Wheel's signing scheme is designed to protect against cryptography
that is not used. Wheel tries to encourage signing by making it very that is not used. The system yields a tiny, performant pure-Python
fast and easy. Signature verification is encouraged by including implementation that can just be included with the reference installer.
the signature in the archive itself rather than making it a separate The 32-byte public keys are convienent to share directly in the
download, and by including a Python implementation of the entire same way you would share a SHA-256 digest. Since the signatures
signing system in the reference implementation. are inside the archive itself, they are more likely to be present
at install time compared to detached signatures.
JWS and Ed25519 yield small, pure-Python implementations. Ed25519 Wheel's signing system is designed to be used more like an md5 sum
is fast enough that public-key cryptography can be considered for or a secure hash used to verify the integrity of an archive than
applications where it was traditionally too slow to be used, so something like PGP or X.509 signatures. A secure hash can verify
wheels can be signed without worrying about performance. In Ed25519, the integrity of a single archive, but a wheel signing key verifies
unlike ECDSA, only key generation, but not signing, depends on the signer of all packages signed with that key. Once you know to
a continuing high-quality source of entropy. The combination of expect a particular signing key, a signature-verifying installer
increased performance, convenience, and availability compared to protects you from installing anything but intact packages from the
using a separate program means digital signatures can always be expected signers. It makes no difference whether the wrong packages
enabled in wheel. come from choosing the wrong package index, disk corruption, or an
actual attack; if a package is not signed with the expected key,
with its file contents matching their hashes in RECORD, then it will
not be installed.
Appendix
========
Example urlsafe-base64-nopad implementation::
# urlsafe-base64-nopad for Python 3
import base64
def urlsafe_b64encode_nopad(data):
return base64.urlsafe_b64encode(data).rstrip(b'=')
def urlsafe_b64decode_nopad(data):
pad = b'=' * (4 - (len(data) & 3))
return base64.urlsafe_b64decode(data + pad)
Wheel uses simplified keys and a signature system where key generation
is about as fast as signing, making it possible to consider signing
keys an abundant resource. Keys could represent a build server or
a package rather than the publisher's entire digital identity.
Copyright Copyright
========= =========