Commits

Daniel Holth committed d27bd31

pep-0427 edits

Comments (0)

Files changed (1)

 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.
 
 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
    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
 ^^^^^^^^^^^^^^^^^^^^^^^^
 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
     # 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" }
 
 - 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
     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.
 
-    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.
+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)
+
 
 Copyright
 =========