pcb-rnd knowledge pool
sign by Tibor 'Igor2' Palinkas on 2020-04-21
Tags: howto, signature, rsa, key, cert, ca
Abstract: If pcb-rnd or any related material is coming with a digital signature, it was signed by the procedure described in this article. The method and/or script provided here can be used to verify the signature of any download.
If you are not interested in the theory, click here to jump to the signature verification part
When you download a tarball from the official pcb-rnd web page, and you don't end up having malware injected in your download you relied on various factors:
- 1. an attacker did not crack repo.hu and did not replace the content of the file you download
- 2. an attacker did not stand between your computer and repo.hu during the download to replace the data stream on the network with a malware-injected version
- 3. an attacker did not already have access to your computer to replace or manipulate the file after the download
From repo.hu side we obviously can't do much about 3., but can provide an effective protection against 1 and 2.
An obvious protection would be to generate a checksum of the file -- e.g. md5 or rather, something stronger -- called the digest. Then, send that digest to the user. Then, after the download the user could check the digest to see if the file was changed (1 or 2). However, uploading this digest next to the file on the same webserver doesn't make much sense: in case of both 1 and 2 the attacker could simply manipulate the digest too.
Uploading the digest to an external server would work better for 1, because the attacker would need to crack at least two independent servers, one for replacing the file and another for replacing the digest. However, for 2, if the attacker is close to the client computer, the attacker can manipulate both the download stream of original file and the digest.
A possible solution to 2, is using encrypted communication on the web. To make it real secure, it take much more effort than it first seems (a plain https won't solve everything!). And then, even if proper encryption is solved, it won't protect against attack 1.
Another possible solution is to use asymmetric cryptography. Assume there is a public-private key pair with the usual properties (something encoded with the private key can be decoded only with the public key). Assume I store this private key on an off-line computer. Instead of the digest, I can use the private key to encrypt the file - or rather just the digest generated from the file and upload the encrypted digest next to the file. When you download the file, you can also download the encrypted digest and the public key 1 , then use the public key to decrypt the digest and verify if the file really has that digest.
An attacker to perfom either 1 or 2, would need to be able to do one of these:
- manipulate the content of the file without changing the resulting digest - this is very hard if the digest algorithm is strong enough
- access my private key to sign the manipulated file - which is hard, because it's on an offline computer
- use another private key, replace the file with the manipulated one and replace the signature with the one generated with the attacker's private key, then make the user believe it should be checked against the attacker's public key instead of mine
Thus the realistic attack is the third one, which depends on the user accepting the right public key only. This normally requires us to have a secure channel between you and me, at least initially, where I can give you the right public key that you can then use for validating downloads. But there's no such channel.
However, there's an imperfect, but good-enough solution to that (see below ).
Finally, the last major problem is automation. The above method assumes I build all tarballs and binaries and basically everything that I want to publish manually, on an off-line computer where I have the private key. While it would be possible, it would be utterly impractical: we have automated processes for releasing and building our software. This is required for reproducability and low overhead. Fortunately, the below "imperfect, but good-enough solution" solves that too.
Good-enough solution: architecture
Let's say you want to download and verify a release tarball I want to auto-build.
The basic idea is that I have a master key pair, the CA, on the offline computer. I guarantee that the private part of the CA never leaves that computer. The public part of the CA is published on multiple independent servers.
Then, I generate key pairs, for example a dedicated key pair for the server that builds the source tarball you are going to download. Let's call this dedicated key pair the build key pair. I sign the public build key with the private key of the CA. I make the public build key accessible next to the file you download. Then, I also upload the private build key to the build server, unaccessible to the world, so the build server can use it to sign tarballs it builds.
An attacker could replace the tarball at the download area, but without the private build key, the file would fail the verification against the public key. The attacker could replace the public key too, but that public key would fail the verification against the CA public.
Of course the attacker could perhaps crack my build server and start distributing malware injected tarball encrypted by the private key present on the build server. But we would detect that soon and I would send out prompt notifiactions about this and would revoke the build key pair. Revoking a key means I add it to the list of revoked keys; this list is called CRL. Then, I could reinstall the build server, generate a new build key pair, again signed with the CA and manually sign all relevant files with the new build key (after verification of those files, of course).
So, at the end, when you get the tarball for best security you need to do the following checks:
- 1. download the tarball, the signature and the build public key
- 2. download the public key of the CA from elsewhere and verify it (see below )
- 3. download the latest version of the CRL
- 4. verify the build public key against the CA and the CRL - so it is signed by the CA and is not revoked by the CRL
- 5. generate the digest of the file and verify it against the build public key
If any of the above steps fails, stop immediately and do not use the tarball.
Download and signature verification
Step 1: download the files from repo.hu
You may use http, at the end the security of your download will be guaranteed by the signature, not by transport encryption.
File names used in this document:
|foo.tar.gz||the tarball to check|
|foo.tar.gz.sig||signature file downloaded from next to the tarball|
|foo.tar.gz.crt||build server's cert ("build public key") at the time of the tarball build, downloaded from next to the tarball|
|rootca_repo.hu_2020.crt||the CA (downloaded only once, in step 2)|
|crl_repo.hu.pem||the CRL, Certificate Revocation List (downloaded from time to time, in step 3)|
Step 2: verify and save the CA
The weak spot of this method is distributing the public key of the CA. In theory we'd again need an initial secure channel between you and me where I could give you the public key 1 of the CA. But we don't have that.
The second best thing I can do is uploading the public key of the CA to multiple independent hosting services. Instead of downloading it from one place, you should download it from multiple places and compare the downloads. As long as they all match, the verification succeeded. Even better, if you use channels outside of web: ask me for the CA fingerprint on IRC, over email, ask other pcb-rnd users you trust for the CA fingerprint (only if they did accurately do this verification before!).
This step has to be done only once, before the first use of the CA. Once you did this, you can save the verified public key of the CA on a secure place and use that any time without having to repeat CA verification. The rest of the document assumes you have saved the file as rootca_repo.hu_2020.crt
Step 3: download CRL
The CRL is uploaded to the same sites as the CA. Please download it from at least 2 places and compare. Please repeat this step when you are about to verify a file and your CRL file was last manually checked more than 2 weeks ago. The file name shall be crl_repo.hu.pem .
At this moment you can choose to go step by step manually executing openssl commands, or you can skip that and run the script.
Step 4: "build public key" 1 vs. CA+CRL verification
cat rootca_repo.hu_2020.crt crl_repo.hu.pem > ca_crl.pem openssl verify -crl_check -CAfile ca_crl.pem foo.tar.gz.crt
This should print:
Step 5: digest generation and tarball verification
openssl x509 -pubkey -noout -in foo.tar.gz.crt > foo.tar.gz.pem openssl dgst -verify foo.tar.gz.pem -signature foo.tar.gz.sig foo.tar.gz
This should print:
Automated verification: script
From version 2.2.1 the script lives in pcb-rnd's util/sign/ directory and is called verify.sh . Please remember: for maximum security you do need to do step 1, 2 and 3 manually then run the script which automates step 4 and 5.
- 1. you actually get a certificate, not a public key; the certificate does contain the public key tho