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``.
In wheel, scripts are packaged in
``{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
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
'''''''''''''
#. Wheel files contain a folder {distribution}-{version}.dist-info/
with the PEP 426 metadata (Metadata version 1.3 or greater) and an
additional file WHEEL with metadata about the archive itself.
#. The root of a .whl is installed into one of purelib or platlib.
#. Wheel files contain metadata about the wheel format itself in
``{distribution}-{version}.dist-info/WHEEL``::
The conents of a wheel file, where {distribution} is replaced with the
name of the package, e.g. ``beaglevote`` and {version} is replaced with
its version, e.g. ``1.0.0``, consist of:
#. ``/``, the root of the archive, contains all files to be installed in
``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
Generator: bdist_wheel 0.7
@ -163,16 +177,17 @@ File contents
directory of the archive should be installed into purelib;
otherwise the root should be installed into platlib.
#. 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 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.
version it supports, and must fail if Wheel-Version has a greater
major version than the version it supports.
#. Wheel, being an installation format that is intended to work across
multiple versions of Python, does not generally include .pyc files.
#. 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
^^^^^^^^^^^^^^^^^^^^^^^^
@ -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
fail.
The signature is one or more JSON Web Signature JSON Serialization
(JWS-JS) signatures stored in a file RECORD.jws adjacent to RECORD.
The signature format is derived from the JSON Web Signatures (JWS)
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.::
# 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:
package[extra, ed25519=ouBJlTJJ4SJXoy8Bi1KRlewWLU6JW7HUXTgvU1YRuiA]
An application could distribute a requires.txt file with many such
lines for all its dependencies and their public keys. By installing
from this file an application's users would know whether the
application's dependencies came from the correct publishers.
An application could distribute a requires.txt file with many such lines
for all its dependencies and their public keys. By installing from this
file an application's users can know they are getting packages from the
same publishers.
Applications that wish to "fail open" for backwards compatibility with
non-signature-aware installers should specify that their package
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
''''''''''''''''''''''''''''''
The Ed25519 algorithm is used as an extension to the JSON Web
Signatures specification. Wheel uses ``alg="Ed25519"`` in the header.
The key attribute holds the signature's public JSON Web Key. For JSON
Web Key / JSON Private Key the verifying (public) key is called vk and
The Ed25519 algorithm is used as an extension to the JSON Web Signatures
specification. Wheel uses ``alg="Ed25519"`` in the header. The key
attribute holds the signature's public JSON Web Key. In JSON Web Key
/ JSON Private Key the Ed25519 verifying (public) key is called vk and
the signing (private) key is called sk.
Example header::
{
"alg": "Ed25519",
"typ": "JWT",
"key": {
"alg": "Ed25519",
"vk": "tmAYCrSfj8gtJ10v3VkvW7jOndKmQIYE12hgnFu3cvk"
}
"alg": "Ed25519",
"jwk": {
"alg": "Ed25519",
"vk": "tmAYCrSfj8gtJ10v3VkvW7jOndKmQIYE12hgnFu3cvk"
}
}
A future version of wheel may omit ``typ``.
Example payload::
Example payload, always the SHA-256 hash of RECORD::
{ "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-ietf-jose-json-web-key.html
- http://self-issued.info/docs/draft-jones-jose-json-private-key.html
- http://ed25519.cr.yp.to/
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
your code. The .data directory is just a place for any files that are
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?
Wheel's signing scheme is designed to protect against cryptography
that is not used. Wheel tries to encourage signing by making it very
fast and easy. Signature verification is encouraged by including
the signature in the archive itself rather than making it a separate
download, and by including a Python implementation of the entire
signing system in the reference implementation.
that is not used. The system yields a tiny, performant pure-Python
implementation that can just be included with the reference installer.
The 32-byte public keys are convienent to share directly in the
same way you would share a SHA-256 digest. Since the signatures
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
is fast enough that public-key cryptography can be considered for
applications where it was traditionally too slow to be used, so
wheels can be signed without worrying about performance. In Ed25519,
unlike ECDSA, only key generation, but not signing, depends on
a continuing high-quality source of entropy. The combination of
increased performance, convenience, and availability compared to
using a separate program means digital signatures can always be
enabled in wheel.
Wheel's signing system is designed to be used more like an md5 sum
or a secure hash used to verify the integrity of an archive than
something like PGP or X.509 signatures. A secure hash can verify
the integrity of a single archive, but a wheel signing key verifies
the signer of all packages signed with that key. Once you know to
expect a particular signing key, a signature-verifying installer
protects you from installing anything but intact packages from the
expected signers. It makes no difference whether the wrong packages
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
=========