<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Tue, Feb 5, 2013 at 2:21 PM, Christian Heimes <span dir="ltr"><<a href="mailto:christian@python.org" target="_blank">christian@python.org</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Hello,<br>
<br>
I like to discuss my proposal for a package signing and verification<br>
process. It's just a brief draft and not a final document. (Credits to<br>
my friend Marcus Brinkmann for additional insights).<br>
<br>
<br>
Package maintainer registers PGP key<br>
------------------------------------<br>
<br>
Package owners and maintainer that like to sign their packages must<br>
register their PGP/GPG key in front. The key must be registered with a<br>
public key server (e.g. launchpad) and must contain an identity that<br>
corresponds with her email address. Also the key must follow certain<br>
standards (no insecure algorithms / key length) and be valid (not<br>
expired or revoked). A user can register multiple GPG keys.<br>
<br>
process:<br>
 - User must provide the full fingerprint (not the short key id).<br>
 - PyPI retrieves the key from a key server.<br>
 - PyPI verifies the key's properties.<br>
 - PyPI sends an encrypted mail to the user which contains an<br>
   activation link for the key.<br>
 - User decrypts the mails with her private key and actives<br>
   the key with the link.<br>
<br>
result:<br>
  PyPI has a verified GPG key of the package maintainer.<br>
<br>
<br>
Package maintainer signs and uploads a package<br>
-----------------------------------------------<br>
<br>
The procedure doesn't change excepet that PyPI may revoke a signature<br>
(more on that later). The upload process must use HTTPS and the SSL<br>
server cert is validating against a CA cert bundle.<br>
<br>
result:<br>
  uploader has uploaded her content and signature through a<br>
  safe channel that protects against password sniffing<br>
  and reply attacks<br>
<br>
<br>
PyPI accepts and validates upload<br>
---------------------------------<br>
<br>
As first step PyPI validates the signature and the user's key:<br>
<br>
 - Is the signature valid and matches the uploaded content?<br>
 - Does the signing key match a registered GPG key of the user?<br>
 - Is the user's key still valid (expiration, revocation)<br>
 - Is the timestamp of the signature within a sensible range<br>
   (plus minus a couple of hours?)<br>
<br>
result:<br>
  PyPI has a validated signature that matches the user's<br>
  settings. The time check adds an additional countermeasure<br>
  against replay attacks,<br>
<br>
<br>
PyPI signs the signature<br>
------------------------<br>
<br>
Here comes the tricky part of the process. Bare with me!<br>
<br>
PyPI generates a metadata file that contains:<br>
<br>
  - timestamp of the upload<br>
  - metadata of the user (id, name, email ...)<br>
  - metadata of the package (excerpt of PKG-INFO)<br>
  - the user's signature of the uploaded content as ASCII armor<br>
<br>
Then PyPI signs the metadata files with its OWN key. It's crucial to<br>
acknowledge that PyPI does NOT sign the uploaded content! It just signs<br>
the user's signature and the package + user metadata. PyPI's signature<br>
does NOT state anything about the file's content or the correctness of<br>
the containing code.<br>
<br>
Why does PyPI sign the package then? PyPI is the only instance that can<br>
verify the relationship between an uploader and a package's content.<br>
PyPI's signature promises that PyPI trusts the user to upload and sign<br>
the package *at this very moment*. With this signature a downloader can<br>
verify that the uploader was a registered maintainer of the package at<br>
this very moment. Without the PyPI signature a downloader would have to<br>
trust a key for all available packages.<br>
<br>
result:<br>
  The combined file (inner layer: metadata, user's signature,<br>
  outer layer: PyPI signature) certifies that the uploader<br>
  has a relationship to the project on PyPI.<br>
<br>
<br>
User installs package<br>
---------------------<br>
<br>
process:<br>
 - <tool> retrieves the package and the combined signature file (PyPI's<br>
signature, metadata file and embedded signature of the uploader)<br>
 - <tool> optionally downloads missing GPG keys from PyPI<br>
 - <tool> verifies PyPIs signature of the metadata file and then the<br>
   uploader's signature of the content<br>
 - on success <tool> install the package<br>
<br>
The verification process needs some interaction with the downloader. She<br>
must accept and establish a trust level with each key. This needs to be<br>
discussed in detail.<br>
<br>
<br>
Open points<br>
-----------<br>
<br>
- Should we allow multiple users for a single GPG key (e.g .team keys)?<br>
<br>
- Should the tool chains use its own key rings for verification instead<br>
  of the user's default keyring? A tool like<br>
<a href="http://man.he.net/man8/apt-key" target="_blank">http://man.he.net/man8/apt-key</a> might be useful.<br>
<br>
- An uploader must be able to revoke her keys from PyPI without<br>
  access to her private key.<br>
<br>
- When a package owner removes a user from the maintainer list<br>
  of a package she must be able to remove all signatures of a<br>
  user, too.<br>
<br>
- PyPI should have a hidden and well protected private key that is used<br>
  to sign a transitional signing key. The signing key is used for a<br>
  couple of months and then replaced by a new signing key<br>
  (with grace periode).<br>
<br>
<br>
Questions?<br>
<br>
Christian<br>
_______________________________________________<br>
Catalog-SIG mailing list<br>
<a href="mailto:Catalog-SIG@python.org">Catalog-SIG@python.org</a><br>
<a href="http://mail.python.org/mailman/listinfo/catalog-sig" target="_blank">http://mail.python.org/mailman/listinfo/catalog-sig</a><br></blockquote><div><br></div><div>There is a well-engineered framework out there already: <a href="https://www.updateframework.com/wiki/SecuringPythonPackageManagement">https://www.updateframework.com/wiki/SecuringPythonPackageManagement</a><br>
</div></div><br></div></div>