buildSupport: add helpers for verifying code signatures#43233
buildSupport: add helpers for verifying code signatures#43233xeji wants to merge 5 commits intoNixOS:masterfrom
Conversation
|
Success on x86_64-linux (full log) Attempted: samba4 Partial log (click to expand)
|
|
Success on x86_64-darwin (full log) Attempted: samba4 Partial log (click to expand)
|
|
Success on aarch64-linux (full log) Attempted: samba4 Partial log (click to expand)
|
| fingerprint = "52FBC0B86D954B0843324CDC6F33915B6568B7EA"; | ||
| }; | ||
|
|
||
| nativeBuildInputs = [ verifySignatureHook ]; |
There was a problem hiding this comment.
Does this work? We aren't downloading binaries here so I have no idea where the signature would be coming from. This should be not needed at all for source based builds.
There was a problem hiding this comment.
It works by convention: The hook assumes that srcSignature contains the signature file, and signaturePublicKey the corresponding key. If they're present, srcSignature is checked against src. Of course you have to fetchurl the signature file and fetchpgpkey the key for the hook to work.
There was a problem hiding this comment.
And yes, it can be used for source base builds if upstream provides a signature for the source tarball. It obviously doesn't work with fetchFromGitHub, but that would be a case for verifying signed git commits.
There was a problem hiding this comment.
Ok did not realize that on tarball signatures! I wonder if we could put the source-based part of the hook in fetchurl then? Just have an optional attribute that is verified for us. This would also make it possible to support multiple-src derivations.
There was a problem hiding this comment.
Sure we can do that. I only decided against modifying fetchurl for now to avoid a rebuild-everything change. It would take several extra attributes: URL and hash of the signature file, and the public key which I would still download separately with fetchpgpgkey as it may be re-used for multiple projects or sources.
There was a problem hiding this comment.
Actually it shouldn't though! fetchurl is fixed output so you can make any changes you want to it.
|
It should be worth taking a look at how Triton did it: see https://github.com/triton/triton/commits/master?before=6a1de201948b7755177562105e49181baca2bc2e+35&path[]=pkgs&path[]=build-support&path[]=fetchurl&path[]=builder.sh starting from Mar 30, 2016. (/cc @wkennington in case you are interested or would like to help.) |
|
Okay a few thoughts on this.
|
@matthewbauer fully agree. I just randomly selected these examples to test and show different use cases of the setup hook. |
|
Marked WIP while I have a look at how Triton does it and try to put part of the features into |
|
Would it be hard to support this common use case? Here's are the instructions for verifying bitcoin signatures:
|
|
Ooooh I would really like to see this happen. I'm discovering this PR just now and it seems the proposed implementation is easily extensible. TL;DR; I'll now read other posts |
gpg supports ed25519 sigs |
| # if UNCOMPRESS is set, uncompress DATAFILE before verification | ||
| verifySignature() { | ||
| if [ -z "$3" ]; then | ||
| gpgv --keyring pubring.kbx "$1" "$2" || exit 1 |
There was a problem hiding this comment.
Can you make gpg ignoring expire dates? Otherwise it will become a problem when somebody tries to build an old nixpkgs revision. We could print a warning if a gpg key is expired.
There was a problem hiding this comment.
The warning should be good enough for the TOFU case.
| nativeBuildInputs = [ verifySignatureHook ]; | ||
|
|
||
| signaturePublicKey = fetchpgpkey { | ||
| url = https://keybase.io/1password/pgp_keys.asc; |
There was a problem hiding this comment.
Can we fetch their key from a key-server using the current keyid instead?
There was a problem hiding this comment.
Keyservers are just one of many ways of fetching OpenPGP keys, I don't think it would make sense to force downloads through them (also, we'd want to fetch using the fingerprint, not the keyid).
Having a fetchFromSks wrapper of fetchpgpkey that fetches from the sks-keyservers network might be a meaningful addition, but I don't think it's required for the first iteration
|
|
||
| name = "pubkey-${fingerprint}"; | ||
|
|
||
| postFetch = |
There was a problem hiding this comment.
I think we could reduce issues when a key gets an additional signature (eg. for when fetching from sks-keyservers) by stripping it of all UIDs, signatures, etc. before the sha256 check.
|
Please do not make this part of Now I do respect that if the attacker has access to the victim's As to motivation of why we want this: We'd like to use automatic updates by bots such as |
|
Hello, I'm a bot and I thank you in the name of the community for your contributions. Nixpkgs is a busy repository, and unfortunately sometimes PRs get left behind for too long. Nevertheless, we'd like to help committers reach the PRs that are still important. This PR has had no activity for 180 days, and so I marked it as stale, but you can rest assured it will never be closed by a non-human. If this is still important to you and you'd like to remove the stale label, we ask that you leave a comment. Your comment can be as simple as "still important to me". But there's a bit more you can do: If you received an approval by an unprivileged maintainer and you are just waiting for a merge, you can @ mention someone with merge permissions and ask them to help. You might be able to find someone relevant by using Git blame on the relevant files, or via GitHub's web interface. You can see if someone's a member of the nixpkgs-committers team, by hovering with the mouse over their username on the web interface, or by searching them directly on the list. If your PR wasn't reviewed at all, it might help to find someone who's perhaps a user of the package or module you are changing, or alternatively, ask once more for a review by the maintainer of the package/module this is about. If you don't know any, you can use Git blame on the relevant files, or GitHub's web interface to find someone who touched the relevant files in the past. If your PR has had reviews and nevertheless got stale, make sure you've responded to all of the reviewer's requests / questions. Usually when PR authors show responsibility and dedication, reviewers (privileged or not) show dedication as well. If you've pushed a change, it's possible the reviewer wasn't notified about your push via email, so you can always officially request them for a review, or just @ mention them and say you've addressed their comments. Lastly, you can always ask for help at our Discourse Forum, or more specifically, at this thread or at #nixos' IRC channel. |
|
I agree with @roconnor-blockstream we should make this part of our tooling rather than the build process. Once we have our own checksum we no longer need to rely on public key cryptography. |
|
This pull request has been mentioned on NixOS Discourse. There might be relevant details there: https://discourse.nixos.org/t/any-interest-in-checkings-signatures-while-building-packages/8918/7 |
|
@Mic92 Correct me if otherwise, but I don't think @roconnor-blockstream was saying that it shouldn't be verified via Nix in a derivation, only that the verification shouldn't be behind a fixed output derivation like There is also another alternative I haven't seen mentioned: Have another derivation that takes the source and signature as input, and outputs a symlink to the original source if and only if it passes a signature check. The output of that verification derivation could then be passed as the |
Motivation for this change
Many projects provide signed source tarballs or signed binaries, which are currently not checked in nixpkgs. While it's not perfect, I believe that checking signatures provides some security advantage our typical "TOFU" workflow of implicitly trusting changed sha256 hashes.
The main reason is that, as opposed to sha256 hashes, public keys are usually long term, so we can invest more time to verify them initially, and after doing this once, malicious changes are more likely to be spotted.
This PR proposes some simple helpers for checking code signatures. It also provides some examples on how to use them.
Things done
fetchpgpkeyis an extension offetchurlthat fetches a PGP public key to the nix store and verifies its fingerprint withgpg. It still needs a sha256 because it is based onfetchurl. (I have experimented with an alternative implementation usingbuiltins.fetchurland just a fingerprint, no sha256, but that is not strictly a fixed-output derivation).verifySignatureHooksets up signature verification and adds apreUnpackHookto automatically verify the signaturesrcSignatureofsrcwithsignaturePublicKeywhen present. Verification can also be triggered manually using the shell functions defined in the hook.Implemented 3 different examples for various use cases of the hook. These examples are for demonstartion and may or may not be merged with this PR.
samba4: the tarball is signed, but the signature is for the uncompressed tar archive. The hook has an option for this.tor-browser-bundle-bin: provides signed tarballs but there's not standard unpack phase, so the verification must be triggered manually inbuildCommand1password: the tarball contains a signed binary and the signature file, so verification is done incheckPhasehere.Possible future work
Enhance
fetchgitto verify signed revisions usinggit verify-commit.cc @matthewbauer @jb55 @garbas