This is a proposal that describes the hypothetical policy and structure of Quicklisp's implementation of public key cryptography used for signing Quicklisp releases and software.
- A single private key becomes the root of trust. This key has an expiration date of five years and is used to sign release
subkeys.
- Alternative: we might want to go for a shorter expiration time, e.g. one year. In such a situation, each root should be signed by all of the previous roots to make migration easier for people who have gone a whole year+ without updating the root.
- Release subkeys are keys that are used to sign individual dist releases. These keys are generated during a dist release
and have an expiration date set at a week.
- For often-releasing dists such as Ultralisp, it might be equivalent to say that a release key is generated at the beginning of every month, it has an expiration date until the end of the month, and is used throughout the month.
- Key and signatures are distributed via HTTP.
- Public keys for the root of trust are available at
http://beta.quicklisp.org/keys/root.zip
.- The public key of the root of trust can be distributed within the Quicklisp installer for bootstrapping purposes.
- The Quicklisp installer itself can be signed with the root of trust.
- Public keys for every release are available at
http://beta.quicklisp.org/keys/version.zip
whereversion
is the version of the dist.- Because the keys are small, we can consider avoiding distributed them in a ZIP file and send them over plaintext instead, which will also avoid the issue of sending maliciously crafted ZIP files meant to attack the inflating function.
- Dist signatures are available at
http://beta.quicklisp.org/signature/.../foo.sig
where...
in the URL depends on the URL of the signed file.http://beta.quicklisp.org/signature/dist/quicklisp/2020-12-20/distinfo.txt.sig
forhttp://beta.quicklisp.org/dist/quicklisp/2020-12-20/distinfo.txt
- The signed dist file contains SHA256 sums for all tarballs and other files that are a part of the dist.
- Revocation certificates are available at
http://beta.quicklisp.org/keys/revocations.zip
.- If a release key is revoked, a new one is generated for that release and everything is resigned with it.
- When the Quicklisp client notices that its root of trust expired, it downloads a new archive containing the root of trust public key and checks if it is signed by one of the old ones. If so, it adds it to the internal keyring to replace the old one.
- When the Quicklisp client notices that it does not have a key for a given release, it downloads it and checks if it is signed by the root of trust. If so, it adds it to the internal keyring.
- If a release is signed by a key that had expired by the time the release was created (e.g. a May 2021 release signed with a Apr 2021 key), the client must signal an error.
Root Key
Honestly, one year seems like a short amount of time for a key that should be kept offline.
Should the root key be rotated or just have its expiry date extended? Should this be mandated or should we leave it up to the dist maintainers to best fit their security models?
What if someone goes over a year without updating the root? Should the new roots be signed by every previous root key?
Signing Files
It seems like overkill to sign every single tarball. What about signing only the Quicklisp metadata? If the hash contained in the metadata is switched from MD5 to something cryptographically secure it should give the same integrity guarantees. This would also loosen the requirement of keeping old keys around.
Revoking
Do we want to handle revoking keys? If so, need to specify where revocation certificates can be found.
Presumably if a release key is revoked, a new one would be generated for that release and everything resigned. This is another case where signing only the metadata would be a boon (fewer things to resign/redownload).