Funtoo Linux Optimization Proposal: Release Signing
The goal of release signing is to ensure a user that what they downloaded is the same thing that Funtoo generated and has not been replaced by some sort of malware or some mirror operator. It assumes that the downloading is being done on a system the user trusts and that installation will be done from a system the user trusts.
Based on my research into PGP release signing, the key should be larger than or equal to 4096 bits and should not be a DSA key. GnuPG should be configured not to use the weaker hashing algorithms as well such as MD5 or SHA1. That’s the guidance that Apache’s release management gives. The trickier part will be to get the public key into the PGP Web of Trust. From what I understand about PGP’s trust model, a key will be trusted if you trust someone that fully trusts the key or if you trust three people that partially trust the key. That seems like a big order so its unlikely that most people will have a chain of trust to the public key. That’s where publishing the key fingerprint over HTTPS or some other similarly secured channel can bootstrap that process by augmenting PGP’s Web of Trust with the certificate authority model used by SSL.
The signings will likely be automated, so I’d suggest running a GPG key agent process of some sort so that the private key can still be protected but still be able to be used in an automated manner without having to enter the passphrase with each build. The person that generates the key should fully trust the “Funtoo Release Key” by signing it with their personal key. At that point, it’s just a matter of getting that person to be trusted by others and signed by their keys over time. Ultimately, release signing provides users with two benefits: They can verify the integrity of what they download. They can also verify the authenticity and ensure that none of the mirrors have tampered with the file. The other issue would be key expiration. I’d suggest the first one be a short expiration to ensure the process is working. If the process seems to be working, a later key can be generated with a longer expiration and cross signed with the original to maintain the trust path. A revocation key also needs to be generated and not stored on the system doing the signing so the key can be revoked if it is ever compromised.
Why not do md5 or sha1 hashes as well?
Our files are already compressed in the xz format, and that format already takes care of integrity checks which is what an md5 or sha1 provides. If the file is corrupt, xz will say so. I just tested this with xz on a tar.xz that I corrupted and got this:
brantgurga@gurganbldesktop ~ $ xz -d portage-current.tar.xz xz: portage-current.tar.xz: Compressed data is corrupt
Even if unpacked indirectly through tar, you'll see this message:
brantgurga@gurganbldesktop ~ $ tar -xJf portage-current.tar.xz xz: (stdin): Compressed data is corrupt tar: Unexpected EOF in archive tar: Unexpected EOF in archive tar: Error is not recoverable: exiting now
What does someone without gpg get?
Without gpg or some other PGP signature verification system, they don't get any extra benefit. It's just an extra file. They still get the integrity checks of the xz compression, but that doesn't mean that someone on a mirror didn't replace the file with another archive of something else.
What about someone with gpg but no key?
gpg will indicate that it is unable to verify anything because it doesn't have the public key.
brantgurga@gurganbldesktop ~ $ gpg --verify signedfile gpg: Signature made Tue 13 May 2008 04:17:42 AM EDT using DSA key ID 7E7B8AC9 gpg: Can't check signature: No public key
And with the key but no trust path?
gpg can verify that the file is the same as the file when the person verified it, but it can't say anything about whether that person is who the public key claims that person to be. In effect, you're no better off than having a hash.
brantgurga@gurganbldesktop ~ $ gpg --verify signedfile gpg: Signature made Tue 13 May 2008 04:17:42 AM EDT using DSA key ID 7E7B8AC9 gpg: Good signature from "Joerg Jaspert <email@example.com>" gpg: aka "Joerg Jaspert <firstname.lastname@example.org>" gpg: aka "Joerg Jaspert <email@example.com>" gpg: aka "Joerg Jaspert <firstname.lastname@example.org>" gpg: aka "Joerg Jaspert <email@example.com>" gpg: aka "Joerg Jaspert <firstname.lastname@example.org>" gpg: WARNING: This key is not certified with a trusted signature! gpg: There is no indication that the signature belongs to the owner. Primary key fingerprint: DF7D EB2F DB28 FD2B A9FB FA6D 715E D6A0 7E7B 8AC9
Notice that it prints out the key fingerprint encouraging that the fingerprint be verified through some means.
And with a trust path?
gpg can verify that it's the same file that "Funtoo Release Engineering" released.
brantgurga@gurganbldesktop ~ $ gpg --verify signedfile gpg: Signature made Tue 13 May 2008 04:17:42 AM EDT using DSA key ID 7E7B8AC9 gpg: Good signature from "Joerg Jaspert <email@example.com>" gpg: aka "Joerg Jaspert <firstname.lastname@example.org>" gpg: aka "Joerg Jaspert <email@example.com>" gpg: aka "Joerg Jaspert <firstname.lastname@example.org>" gpg: aka "Joerg Jaspert <email@example.com>" gpg: aka "Joerg Jaspert <firstname.lastname@example.org>"
Because of the way git works with cryptographic hashes linking the revisions together, as long as the original portage tree came from a snapshot that is signed, every sync is effectively signed because you have a cryptographic hierarchy to that original signed revision.
Because the tree has hashes of the distfiles used by packages, you effectively get a transitive signing of all of those as well.
If the portage tree is retrieved by cloning the original over http, you don't have any guarantees because you don't know what server that is. It could be a man in the middle with a replaced git repository containing something else. If it is cloned over the git protocol, the same issue is there. You don't have a way to know what the legitimate root of the repository is for the future revisions to build upon.