From d491405c498fb9d728536657b800f86d16614cea Mon Sep 17 00:00:00 2001 From: Las Safin Date: Fri, 6 Aug 2021 11:30:09 +0000 Subject: [PATCH 01/11] [RFC 0100] Sign commits Add mechanisms by which Nixpkgs can be trusted. Specifically: - Require that authorized committers (people who commit directly to Nixpkgs) sign their commits eventually - Add a mechanism by which flake Git inputs can be verified for trust and signatures - Speed up fetching Git repositories with Nix (since non-Git inputs can't be checked) --- rfcs/0100-sign-commits.md | 317 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 317 insertions(+) create mode 100644 rfcs/0100-sign-commits.md diff --git a/rfcs/0100-sign-commits.md b/rfcs/0100-sign-commits.md new file mode 100644 index 000000000..8d3725804 --- /dev/null +++ b/rfcs/0100-sign-commits.md @@ -0,0 +1,317 @@ +--- +feature: sign-commits +start-date: 2021-08-14 +author: Las Safin +co-authors: +shepherd-team: +shepherd-leader: +related-issues: https://github.com/NixOS/rfcs/pull/34 +--- + +# Summary +[summary]: #summary + +Recommend and eventually require that people who commit directly to +https://github.com/NixOS/nixpkgs and https://github.com/NixOS/nix, +so called authorized committers, sign their commits. + +Commits inside merges do not have to be signed as long as the merge commit itself is signed, +such that only Committers have to sign their commits. + +# Motivation +[motivation]: #motivation + +Signing commits would allow cryptographically verifying that the source code +hasn't been tampered by an untrusted party. + +This would ensure that when pulling from GitHub, or some other source, +you can check if the source code has been signed by a trusted person. + +This is already done by Guix: +- https://guix.gnu.org/en/blog/2020/securing-updates/ +- https://github.com/guix-mirror/guix/commits/master +- https://guix.gnu.org/manual/en/html_node/Commit-Access.html +- https://guix.gnu.org/manual/en/html_node/Channel-Authentication.html + +It is also done by most conventional distros, however, they sign +the output from the compilation rather than the source code, since +they distribute the output from the compilation. + +This change would also allow using 3rd-party mirrors of Nixpkgs, +since we can verify the source code independent of where it came from. + +This RFC was motivated by work during Summer of Nix, specifically, +the Libre SoC maintainer requested that source integrity be +maintained. + +# Detailed design +[design]: #detailed-design + +## Signing the commits +[signing]: #signing-the-commits + +The following will be required from 2022-03-01T00:00Z on, +but is strongly recommended from now on. + +Currently merging is done through GitHub, which would not work in this case. +Merging would have to happen outside of GitHub, so that you can sign the commits, +since currently the API doesn't support signing commits with your own GPG +key: https://github.com/cli/cli/issues/1318. + +The exact workflow for merging a PR with ID 123 would be something like this: +```bash +git switch master +git pull +gh pr checkout 123 +git switch master +git merge -m "Merged #123" --no-ff --gpg-sign - +git push origin master +gh pr close 123 +``` +A merge commit must always be made so that there is something to sign. + +A git hook like the one presented here is also recommended, +so that unsigned commits aren't pushed by accident. +This would be put in `/.git/hooks/pre-push` of the repository to +be committed to. +```bash +#!/bin/sh + +# Inspiration taken from https://github.com/guix-mirror/guix/blob/master/etc/git/pre-push. +# Put this in .git/hooks/pre-push. +set -xe + +# This is the "empty hash" used by Git when pushing a branch deletion. +z40=0000000000000000000000000000000000000000 + +while read local_ref local_hash remote_ref remote_hash +do + # Branch deletion; no signature to verify. + if [ "$local_hash" != $z40 ] + then + # Check repositories under github.com/NixOS. + case "$2" in + *github.com*NixOS/*) + # TODO: More thorough check. + git verify-commit HEAD + ;; + esac + fi +done +``` + +The digest algorithm for GPG must be set to something that isn't SHA-1, +as [it isn't secure anymore](https://eprint.iacr.org/2020/014.pdf), for example by putting the following in +`$HOME/.gnupg/gpg.conf`: +``` +digest-algo sha512 +``` + +Committers will need to put their PGP keys in +https://github.com/NixOS/nixpkgs/blob/master/maintainers/maintainer-list.nix, +and add their keys to public key servers. + +The following might not be implemented before 2022-03-01T00:00Z, +but the above will still regardless be required at that point in time. + +## Verifying flake Git inputs + +### Updating flake Git inputs +[updating]: #updating-flake-git-inputs + +The design is inspired by what is described here: https://guix.gnu.org/en/blog/2020/securing-updates/. + +When updating any existing flake input of type `git` from an old commit, Nix must verify that +the new commit is trusted. + +The old commit is always trusted. + +In the context of Git, a parent is a direct parent in the DAG of commits. + +If a commit has a trusted parent, then the commit is trusted if +it doesn't have a trusted parent with `/.authorized-committers.nix`, + +If a commit has a trusted parent, +and is signed by a committer listed in each of the trusted +parents' `/.authorized-committers.nix`, then the commit is trusted. + +#### The format of `/.authorized-committers.nix` + +An example: `/.authorized-committers.nix`: +```nix +{ + committers = { + jacob = "XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX"; + jonathan = "YYYY YYYY YYYY YYYY YYYY YYYY YYYY YYYY YYYY YYYY"; + }; +} +``` + +Specifically, it will contain a Nix expression, that evaluates +to a set with a single attribute `committers`, which contains +another set where names are mapped to PGP fingerprints. This is a set +instead of a list to make it easy to get the fingerprint for a specific +person. + +### New flake Git inputs + +When a flake input is initialized, there is no good way to check who to trust +automatically, i.e. it is [Trust on First Use](https://en.wikipedia.org/wiki/Trust_on_first_use). + +To secure initializations, new attributes are added to the `git` input type: +- `startsAt` (optional): This is the first commit to use, therefore verification + starts from this commit on. +- `startsAtKey` (optional): This is the PGP fingerprint for the `startsAt` commit. + This should not be required, but is necessary since SHA-1 is insecure. + +The standard registry entries will have `startsAt` and `startsAtKey` attributes +added, to ensure that NixOS users fetch trusted source code. + +### Other new input attributes + +- `insecureUpdate` (optional): If set to true, then the flake will update without errors + to untrusted commits, however it will still emit a warning. +- `alwaysTrust` (optional): Commits signed by these PGP fingerprints will always be trusted. + +## Speeding up fetching Git + +Cryptographically verifying Git commits is easy, but +Git is currently often not suitable for using as a flake input. +Nixpkgs is growing at an extreme rate, and with each +revision cloning it becomes slower. +For the author, a full clone from scratch takes over 4 minutes. + +To avoid this problem with the Git protocol, Nix currently +supports the `github` type, which fetches archives from GitHub, +and updates the flake input using proprietary GitHub APIs. +This is GitHub specific, isn't usable on other platforms, and can +not take advantage of the above method for verifying source code +integrity. + +We can however speed up fetching Git repositories heavily +by passing filters (see man page for `git-clone(1)` and `git-rev-list(1)`). +A small benchmark from the author of this RFC: +- `git clone git://github.com/NixOS/nixpkgs` 4:24 +- `git clone git://github.com/NixOS/nixpkgs --filter=blob:null` 1:06 +- `git clone git://github.com/NixOS/nixpkgs --filter=tree:0` 0:22 +- `git clone git://github.com/NixOS/nixpkgs --depth 1` 0:10 + (Almost supported already, see https://github.com/NixOS/nix/issues/5119) +- `curl https://github.com/NixOS/nixpkgs/archive/master.tar.gz -LO | tar -xf -` + 0:05 (roughly equivalent to `github:NixOS/nixpkgs`) + +This is with an 850 EVO SSD, the max download speed from GitHub was 24 MiB/s. +Relevant documentation is: +- https://github.blog/2020-12-21-get-up-to-speed-with-partial-clone-and-shallow-clone/ +- https://git-scm.com/docs/partial-clone +- https://git-scm.com/docs/shallow + +We likely want to make Nix use `--filter=tree:0` by default when fetching repositories. +`--depth 1` is faster, but it doesn't preserve the commit history, +and it's not clear how it it interacts with GPG signing. + +# Examples and Interactions +[examples-and-interactions]: #examples-and-interactions + +Committers will need to adapt to the new workflow before March of 2022. +The command they will run is explained in [signing], but further +information about how to sign commits is out of scope for this RFC. + +Relevant documentation for setting up GPG: +- https://guix.gnu.org/manual/en/html_node/Commit-Access.html +- https://www.kernel.org/doc/html/latest/process/maintainer-pgp-guide.html + +Flake users will need to become aware of the basics of this system +when using forks of Nixpkgs, as updating such flake inputs +will be different from before. +In addition, flake users should also begin taking use of the features +introduced in this RFC, as they are usable and useful for all flakes. + +## Example flake + +```nix +# flake.nix +{ + inputs.someflake = { + url = "https://github.com/some/flake.git"; + startsAt = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + startsAtKey = "XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX"; + type = "git"; + }; + + outputs = { someflake }: {}; +} +``` + +```nix +# some/flake/authorized-committers.nix +{ + committers.some = "XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX"; +} +``` + +Now if `https://github.com/some/flake.git` receives a new commit that can +*not* be trusted according to the algorithm specified in [updating], +we'd get an error like the following if we run `nix flake update`: +``` +* **Failed trust verification!** 'someflake': 'git+https://github.com/some/flake.git?ref=master&rev=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' -!> 'git+https://github.com/some/flake.git?ref=master&rev=bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' (Not signed by a trusted party!) +``` + +Notably, there is nothing that tells the user how to bypass the check +using the `insecureUpdate` attribute, +since if there were, users might very often ignore the error even if valid. + +# Drawbacks +[drawbacks]: #drawbacks + +- Merging PRs can not be done through GitHub. +- Setting up GPG signatures will be a bit extra work for the committers. +- Committers will need to maintain the list of authorized committers. +- Fetching Nixpkgs with Nix will take around [4 times](#speeding-up-fetching-git) the time, depending on your hardware. +- Currently building a fork of Nixpkgs (for e.g. a PR) will still work fine, since + the latest commit will be trusted when adding a new flake input, or referring + to one from the commandline, but updating the flake input will fail + since the commits are likely not signed by authorized committers. + +# Alternatives +[alternatives]: #alternatives + +- Mandating signing only tags is an alternative, though not very useful for most users. + +# Unresolved questions +[unresolved]: #unresolved-questions + +- Should `/.authorized-committers.nix` perhaps not support computation like `flake.nix`? + If it supports computation, in Nixpkgs it can be derived from the maintainer list partially. +- Should we require that repositories that use this mechanism contain + the public keys corresponding to the fingerprints to remove the need for key servers? + +# Future work +[future]: #future-work + +- Currently, Git still uses SHA-1, which means that verifying a commit's signature + doesn't mean that the hash of that commit is trusted, since there could be + multiple commits with the same hash. See [SHA-1 is a Shambles](https://eprint.iacr.org/2020/014.pdf). + To avoid this, all Git repositories must eventually be transitioned to + SHA-256 when Git support for SHA-256 is stabilized. +- The `github` flake input type could potentially be removed since it doesn't seem to be necessary anymore. +- Instead of an ad-hoc workflow for signing merges, functionality + could be added to https://github.com/desktop/desktop and https://github.com/cli/cli + to support signing merge commits. See https://github.com/cli/cli/issues/1318. +- To reduce the amount of time fetching Nixpkgs takes, redirection flakes could be introduced. + A redirection flake must have no inputs and no outputs. + It would have a single `redirection` attribute, with the same format as an input. + For example: + ```nix + { + redirection.url = "https://github.com/NixOS/nixpkgs/archive/e51edc1e641e4a9532566961c7336f4cdd4602a1.tar.gz"; + } + ``` + Flakes that depend on this flake will instead depend on the target of the redirection. + Redirection flakes would have lock files, `/.authorized-committers` as usual. + This would be used to make a "lightweight" Nixpkgs repository that tracks + the main repository, redirecting using the `tarball` input type. + This repository would also be verified using the method described in [Updating flake Git inputs][updating]. + CI would be put in place to check that the tarballs' contents are the same + as the corresponding commits. +- Verify the sources used in Nixpkgs to the extent possible. This would be done on a + per-package basis since it depends on how upstream signs their source code (if at all). From 1bacb5bc18a7ae6b5fc0f4f0ea7bc934d963fca9 Mon Sep 17 00:00:00 2001 From: Las Safin Date: Sat, 14 Aug 2021 12:34:06 +0000 Subject: [PATCH 02/11] [RFC 0100 work] Add more benchmark results --- rfcs/0100-sign-commits.md | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/rfcs/0100-sign-commits.md b/rfcs/0100-sign-commits.md index 8d3725804..4a8198c8f 100644 --- a/rfcs/0100-sign-commits.md +++ b/rfcs/0100-sign-commits.md @@ -189,17 +189,25 @@ not take advantage of the above method for verifying source code integrity. We can however speed up fetching Git repositories heavily -by passing filters (see man page for `git-clone(1)` and `git-rev-list(1)`). -A small benchmark from the author of this RFC: -- `git clone git://github.com/NixOS/nixpkgs` 4:24 -- `git clone git://github.com/NixOS/nixpkgs --filter=blob:null` 1:06 -- `git clone git://github.com/NixOS/nixpkgs --filter=tree:0` 0:22 -- `git clone git://github.com/NixOS/nixpkgs --depth 1` 0:10 +by passing filters (see man page for `git-clone(1)` and `git-rev-list(1)`): +- `git clone git://github.com/NixOS/nixpkgs --single-branch --branch=21.05-beta` 4:17 +- `git clone git://github.com/NixOS/nixpkgs --single-branch --branch=21.05-beta --filter=blob:none` 1:05 +- `git clone git://github.com/NixOS/nixpkgs --single-branch --branch=21.05-beta --filter=tree:0` 0:22 +- `git clone git://github.com/NixOS/nixpkgs --single-branch --branch=21.05-beta --depth 1` 0:08 (Almost supported already, see https://github.com/NixOS/nix/issues/5119) -- `curl https://github.com/NixOS/nixpkgs/archive/master.tar.gz -LO | tar -xf -` - 0:05 (roughly equivalent to `github:NixOS/nixpkgs`) +- `curl https://github.com/NixOS/nixpkgs/archive/21.05-beta.tar.gz -LO | tar -xf -` + 0:04 (roughly equivalent to `github:NixOS/nixpkgs?ref=21.05-beta`) +Then after doing `cd nixpkgs`, we try fetching `21.05-beta`, which is 659 commits more to +pull: +- `git pull --ff-only origin 21.05` 0:08 +- `git pull --ff-only origin 21.05` 0:08 (after having fetched with `--filter=blob:none`) +- `git pull --ff-only origin 21.05` 0:07 (after having fetched with `--filter=tree:0`) +- `git clone git://github.com/NixOS/nixpkgs --single-branch --branch=21.05 --depth 1` 0:08 (pulling doesn't make sense) + (Almost supported already, see https://github.com/NixOS/nix/issues/5119) +- `curl https://github.com/NixOS/nixpkgs/archive/21.05.tar.gz -LO | tar -xf -` + 0:04 (roughly equivalent to `github:NixOS/nixpkgs?ref=21.05`) -This is with an 850 EVO SSD, the max download speed from GitHub was 24 MiB/s. +This is with an 850 EVO SSD, the average download speed from GitHub was around 11 MiB/s according to `git`. Relevant documentation is: - https://github.blog/2020-12-21-get-up-to-speed-with-partial-clone-and-shallow-clone/ - https://git-scm.com/docs/partial-clone From 2ed58e5bade88374e4a803e38cdda4fee6259fbf Mon Sep 17 00:00:00 2001 From: Las Safin Date: Sat, 14 Aug 2021 12:38:34 +0000 Subject: [PATCH 03/11] [RFC 0100 work] Fix formatting --- rfcs/0100-sign-commits.md | 1 + 1 file changed, 1 insertion(+) diff --git a/rfcs/0100-sign-commits.md b/rfcs/0100-sign-commits.md index 4a8198c8f..d09400e57 100644 --- a/rfcs/0100-sign-commits.md +++ b/rfcs/0100-sign-commits.md @@ -197,6 +197,7 @@ by passing filters (see man page for `git-clone(1)` and `git-rev-list(1)`): (Almost supported already, see https://github.com/NixOS/nix/issues/5119) - `curl https://github.com/NixOS/nixpkgs/archive/21.05-beta.tar.gz -LO | tar -xf -` 0:04 (roughly equivalent to `github:NixOS/nixpkgs?ref=21.05-beta`) + Then after doing `cd nixpkgs`, we try fetching `21.05-beta`, which is 659 commits more to pull: - `git pull --ff-only origin 21.05` 0:08 From 8647e1cef5bcf01c1f2abeaa6afd8e398a7b590e Mon Sep 17 00:00:00 2001 From: Las Safin Date: Sat, 14 Aug 2021 15:48:57 +0000 Subject: [PATCH 04/11] [RFC 0100 work] Tiny changes --- rfcs/0100-sign-commits.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/rfcs/0100-sign-commits.md b/rfcs/0100-sign-commits.md index d09400e57..aaa286bfb 100644 --- a/rfcs/0100-sign-commits.md +++ b/rfcs/0100-sign-commits.md @@ -203,8 +203,7 @@ pull: - `git pull --ff-only origin 21.05` 0:08 - `git pull --ff-only origin 21.05` 0:08 (after having fetched with `--filter=blob:none`) - `git pull --ff-only origin 21.05` 0:07 (after having fetched with `--filter=tree:0`) -- `git clone git://github.com/NixOS/nixpkgs --single-branch --branch=21.05 --depth 1` 0:08 (pulling doesn't make sense) - (Almost supported already, see https://github.com/NixOS/nix/issues/5119) +- `git clone git://github.com/NixOS/nixpkgs --single-branch --branch=21.05 --depth 1` 0:08 (pulling doesn't work) - `curl https://github.com/NixOS/nixpkgs/archive/21.05.tar.gz -LO | tar -xf -` 0:04 (roughly equivalent to `github:NixOS/nixpkgs?ref=21.05`) @@ -275,7 +274,7 @@ since if there were, users might very often ignore the error even if valid. - Merging PRs can not be done through GitHub. - Setting up GPG signatures will be a bit extra work for the committers. - Committers will need to maintain the list of authorized committers. -- Fetching Nixpkgs with Nix will take around [4 times](#speeding-up-fetching-git) the time, depending on your hardware. +- Fetching Nixpkgs with Nix will take around [5 times](#speeding-up-fetching-git) the time, depending on your hardware. - Currently building a fork of Nixpkgs (for e.g. a PR) will still work fine, since the latest commit will be trusted when adding a new flake input, or referring to one from the commandline, but updating the flake input will fail From b86b32b3ff50d4a2c1a51c27a775190baeb030b9 Mon Sep 17 00:00:00 2001 From: Las Safin Date: Sat, 14 Aug 2021 19:19:40 +0000 Subject: [PATCH 05/11] [RFC 0100 work] GPG -> PGP, in some places --- rfcs/0100-sign-commits.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/rfcs/0100-sign-commits.md b/rfcs/0100-sign-commits.md index aaa286bfb..5d280a029 100644 --- a/rfcs/0100-sign-commits.md +++ b/rfcs/0100-sign-commits.md @@ -55,7 +55,7 @@ but is strongly recommended from now on. Currently merging is done through GitHub, which would not work in this case. Merging would have to happen outside of GitHub, so that you can sign the commits, -since currently the API doesn't support signing commits with your own GPG +since currently the API doesn't support signing commits with your own PGP key: https://github.com/cli/cli/issues/1318. The exact workflow for merging a PR with ID 123 would be something like this: @@ -100,7 +100,7 @@ do done ``` -The digest algorithm for GPG must be set to something that isn't SHA-1, +The digest algorithm for GPG (if you're using GPG) must be set to something that isn't SHA-1, as [it isn't secure anymore](https://eprint.iacr.org/2020/014.pdf), for example by putting the following in `$HOME/.gnupg/gpg.conf`: ``` @@ -215,7 +215,7 @@ Relevant documentation is: We likely want to make Nix use `--filter=tree:0` by default when fetching repositories. `--depth 1` is faster, but it doesn't preserve the commit history, -and it's not clear how it it interacts with GPG signing. +and it's not clear how it it interacts with PGP signing. # Examples and Interactions [examples-and-interactions]: #examples-and-interactions @@ -272,7 +272,7 @@ since if there were, users might very often ignore the error even if valid. [drawbacks]: #drawbacks - Merging PRs can not be done through GitHub. -- Setting up GPG signatures will be a bit extra work for the committers. +- Setting up PGP signatures will be a bit extra work for the committers. - Committers will need to maintain the list of authorized committers. - Fetching Nixpkgs with Nix will take around [5 times](#speeding-up-fetching-git) the time, depending on your hardware. - Currently building a fork of Nixpkgs (for e.g. a PR) will still work fine, since From 63cf9b76bd156981d83b04171a23f5b2b80842e2 Mon Sep 17 00:00:00 2001 From: Las Safin Date: Sun, 15 Aug 2021 07:21:06 +0000 Subject: [PATCH 06/11] [RFC 0100 work] Experimental Git SHA-256 support and other small changes --- rfcs/0100-sign-commits.md | 58 ++++++++++++++++++++++++++------------- 1 file changed, 39 insertions(+), 19 deletions(-) diff --git a/rfcs/0100-sign-commits.md b/rfcs/0100-sign-commits.md index 5d280a029..9c4c73530 100644 --- a/rfcs/0100-sign-commits.md +++ b/rfcs/0100-sign-commits.md @@ -11,12 +11,13 @@ related-issues: https://github.com/NixOS/rfcs/pull/34 # Summary [summary]: #summary -Recommend and eventually require that people who commit directly to -https://github.com/NixOS/nixpkgs and https://github.com/NixOS/nix, -so called authorized committers, sign their commits. - -Commits inside merges do not have to be signed as long as the merge commit itself is signed, -such that only Committers have to sign their commits. +- Add a way for flake inputs that point to Git repositories to be verified for trust. +- Speed up fetching Git repositories with Nix. +- Recommend and eventually require that people who commit directly to + https://github.com/NixOS/nixpkgs and https://github.com/NixOS/nix, + so called authorized committers, sign their commits. + - Commits inside merges do not have to be signed as long as the merge commit itself is signed, + such that only Committers have to sign their commits. # Motivation [motivation]: #motivation @@ -58,16 +59,27 @@ Merging would have to happen outside of GitHub, so that you can sign the commits since currently the API doesn't support signing commits with your own PGP key: https://github.com/cli/cli/issues/1318. -The exact workflow for merging a PR with ID 123 would be something like this: +We would make a script for merging pull requests instead, something like: ```bash +#!/bin/sh +# nixpkgsmerge + git switch master git pull -gh pr checkout 123 +gh pr checkout $1 git switch master -git merge -m "Merged #123" --no-ff --gpg-sign - +git merge -m "Merged #$1" --no-ff --gpg-sign - git push origin master -gh pr close 123 +gh pr close $1 ``` +Then +```bash +nixpkgsmerge 123 +``` + +For mobile platforms, you would use [nix-on-droid](https://github.com/t184256/nix-on-droid) +to run the script instead. + A merge commit must always be made so that there is something to sign. A git hook like the one presented here is also recommended, @@ -161,10 +173,8 @@ automatically, i.e. it is [Trust on First Use](https://en.wikipedia.org/wiki/Tru To secure initializations, new attributes are added to the `git` input type: - `startsAt` (optional): This is the first commit to use, therefore verification starts from this commit on. -- `startsAtKey` (optional): This is the PGP fingerprint for the `startsAt` commit. - This should not be required, but is necessary since SHA-1 is insecure. -The standard registry entries will have `startsAt` and `startsAtKey` attributes +The standard registry entries will have the `startsAt` attribute added, to ensure that NixOS users fetch trusted source code. ### Other new input attributes @@ -283,24 +293,34 @@ since if there were, users might very often ignore the error even if valid. # Alternatives [alternatives]: #alternatives -- Mandating signing only tags is an alternative, though not very useful for most users. +- Mandating signing only tags is an alternative, though not very useful for most users, since: + 1) Users of Nixpkgs rarely fix their used revision to a tag. + 2) Not signing every commit prevents you from using the algorithm described in [updating]. + Somewhat the same thing can be achieved by the "redirection flake" design described + in [future], however. # Unresolved questions [unresolved]: #unresolved-questions - Should `/.authorized-committers.nix` perhaps not support computation like `flake.nix`? - If it supports computation, in Nixpkgs it can be derived from the maintainer list partially. + If it supports computation, in Nixpkgs it could be derived from the maintainer list partially. - Should we require that repositories that use this mechanism contain the public keys corresponding to the fingerprints to remove the need for key servers? # Future work [future]: #future-work -- Currently, Git still uses SHA-1, which means that verifying a commit's signature - doesn't mean that the hash of that commit is trusted, since there could be - multiple commits with the same hash. See [SHA-1 is a Shambles](https://eprint.iacr.org/2020/014.pdf). +- Currently, Git still uses SHA-1, which means that you can't + completely trust signatures on SHA-1 repositories, since it is a combination + of the commit message, parent hashes, and tree hashes, that are seemingly signed. To avoid this, all Git repositories must eventually be transitioned to - SHA-256 when Git support for SHA-256 is stabilized. + SHA-256 when Git support for SHA-256 is stabilized. Users can already + try SHA-256 if they want extra security for their own repositories. + See: + - https://git-scm.com/docs/hash-function-transition/ + - [Git 2.29.0 release notes](https://github.com/git/git/blob/master/Documentation/RelNotes/2.29.0.txt) + - [SHA-1 is a Shambles](https://eprint.iacr.org/2020/014.pdf) + - https://sha-mbles.github.io/ for a more readable version. - The `github` flake input type could potentially be removed since it doesn't seem to be necessary anymore. - Instead of an ad-hoc workflow for signing merges, functionality could be added to https://github.com/desktop/desktop and https://github.com/cli/cli From cf51b1f0b0a87dd07efad67f4bb57b6a26775343 Mon Sep 17 00:00:00 2001 From: Las Safin Date: Sun, 15 Aug 2021 10:31:07 +0000 Subject: [PATCH 07/11] [RFC 0100 work] Add note about alternatively trusting GitHub --- rfcs/0100-sign-commits.md | 1 + 1 file changed, 1 insertion(+) diff --git a/rfcs/0100-sign-commits.md b/rfcs/0100-sign-commits.md index 9c4c73530..be54f9e54 100644 --- a/rfcs/0100-sign-commits.md +++ b/rfcs/0100-sign-commits.md @@ -298,6 +298,7 @@ since if there were, users might very often ignore the error even if valid. 2) Not signing every commit prevents you from using the algorithm described in [updating]. Somewhat the same thing can be achieved by the "redirection flake" design described in [future], however. +- We could trust GitHub's PGP key, so that merging can still be done through GitHub. # Unresolved questions [unresolved]: #unresolved-questions From 20609d3a29939b8e87089d9e659fa10ee46d1fed Mon Sep 17 00:00:00 2001 From: Las Safin Date: Sun, 15 Aug 2021 16:34:00 +0000 Subject: [PATCH 08/11] [RFC 0100 work] Take into account @andir's suggestions (Thanks!) --- rfcs/0100-sign-commits.md | 464 ++++++++++++++++++++------------------ 1 file changed, 247 insertions(+), 217 deletions(-) diff --git a/rfcs/0100-sign-commits.md b/rfcs/0100-sign-commits.md index be54f9e54..941edf677 100644 --- a/rfcs/0100-sign-commits.md +++ b/rfcs/0100-sign-commits.md @@ -11,35 +11,40 @@ related-issues: https://github.com/NixOS/rfcs/pull/34 # Summary [summary]: #summary -- Add a way for flake inputs that point to Git repositories to be verified for trust. -- Speed up fetching Git repositories with Nix. -- Recommend and eventually require that people who commit directly to - https://github.com/NixOS/nixpkgs and https://github.com/NixOS/nix, - so called authorized committers, sign their commits. - - Commits inside merges do not have to be signed as long as the merge commit itself is signed, - such that only Committers have to sign their commits. +This RFC consists of several somewhat interdependent parts: +- [Add support in Nix for verifying trust when fetching Git repositories.](#verifying-trust) +- Speed up fetching Git repositories with Nix so that we don't have to + rely on unverifiable tarballs as much. +- Make use of the above functionality in Nixpkgs, allowing users to + make sure the version of Nixpkgs they are using is trusted. # Motivation [motivation]: #motivation -Signing commits would allow cryptographically verifying that the source code -hasn't been tampered by an untrusted party. - -This would ensure that when pulling from GitHub, or some other source, -you can check if the source code has been signed by a trusted person. - -This is already done by Guix: -- https://guix.gnu.org/en/blog/2020/securing-updates/ +There is already much literature on why you should +sign your commits, but to quickly reiterate, +it provides assurance that you can trust a commit, +and thus makes it harder to inject malicious code +during an update, i.e. moving from an old commit +to a new commit. + +However, even if you sign your commits, Nix currently +provides no way of automatically verifying said +commits for trust. + +[Guix](https://guix.gnu.org/), a competitor to Nix, already +support verifying commits through their own system, described +in the following links: +- **https://guix.gnu.org/en/blog/2020/securing-updates/** - https://github.com/guix-mirror/guix/commits/master - https://guix.gnu.org/manual/en/html_node/Commit-Access.html - https://guix.gnu.org/manual/en/html_node/Channel-Authentication.html -It is also done by most conventional distros, however, they sign -the output from the compilation rather than the source code, since -they distribute the output from the compilation. - -This change would also allow using 3rd-party mirrors of Nixpkgs, -since we can verify the source code independent of where it came from. +In addition, most conventional Linux distributions already sign their +binary packages. By adding this functionality to Nix, end-users of Nixpkgs +and other Nix repositories can be sure that they're getting the correct +source code, **regardless** of the channel through they received +it. This RFC was motivated by work during Summer of Nix, specifically, the Libre SoC maintainer requested that source integrity be @@ -48,108 +53,40 @@ maintained. # Detailed design [design]: #detailed-design -## Signing the commits -[signing]: #signing-the-commits - -The following will be required from 2022-03-01T00:00Z on, -but is strongly recommended from now on. - -Currently merging is done through GitHub, which would not work in this case. -Merging would have to happen outside of GitHub, so that you can sign the commits, -since currently the API doesn't support signing commits with your own PGP -key: https://github.com/cli/cli/issues/1318. - -We would make a script for merging pull requests instead, something like: -```bash -#!/bin/sh -# nixpkgsmerge - -git switch master -git pull -gh pr checkout $1 -git switch master -git merge -m "Merged #$1" --no-ff --gpg-sign - -git push origin master -gh pr close $1 -``` -Then -```bash -nixpkgsmerge 123 -``` - -For mobile platforms, you would use [nix-on-droid](https://github.com/t184256/nix-on-droid) -to run the script instead. - -A merge commit must always be made so that there is something to sign. - -A git hook like the one presented here is also recommended, -so that unsigned commits aren't pushed by accident. -This would be put in `/.git/hooks/pre-push` of the repository to -be committed to. -```bash -#!/bin/sh - -# Inspiration taken from https://github.com/guix-mirror/guix/blob/master/etc/git/pre-push. -# Put this in .git/hooks/pre-push. -set -xe - -# This is the "empty hash" used by Git when pushing a branch deletion. -z40=0000000000000000000000000000000000000000 - -while read local_ref local_hash remote_ref remote_hash -do - # Branch deletion; no signature to verify. - if [ "$local_hash" != $z40 ] - then - # Check repositories under github.com/NixOS. - case "$2" in - *github.com*NixOS/*) - # TODO: More thorough check. - git verify-commit HEAD - ;; - esac - fi -done -``` - -The digest algorithm for GPG (if you're using GPG) must be set to something that isn't SHA-1, -as [it isn't secure anymore](https://eprint.iacr.org/2020/014.pdf), for example by putting the following in -`$HOME/.gnupg/gpg.conf`: -``` -digest-algo sha512 -``` +## Verifying trust +[verifying trust]: #verifying-trust -Committers will need to put their PGP keys in -https://github.com/NixOS/nixpkgs/blob/master/maintainers/maintainer-list.nix, -and add their keys to public key servers. - -The following might not be implemented before 2022-03-01T00:00Z, -but the above will still regardless be required at that point in time. - -## Verifying flake Git inputs - -### Updating flake Git inputs -[updating]: #updating-flake-git-inputs +### The algorithm The design is inspired by what is described here: https://guix.gnu.org/en/blog/2020/securing-updates/. -When updating any existing flake input of type `git` from an old commit, Nix must verify that -the new commit is trusted. - -The old commit is always trusted. +We have two inputs to consider, an old trusted commit, +and a new potentially untrusted commit. In the context of Git, a parent is a direct parent in the DAG of commits. +The old commit is always trusted. + If a commit has a trusted parent, then the commit is trusted if -it doesn't have a trusted parent with `/.authorized-committers.nix`, +it doesn't have a trusted parent with `/.well-known/authorized-committers.nix`, If a commit has a trusted parent, -and is signed by a committer listed in each of the trusted -parents' `/.authorized-committers.nix`, then the commit is trusted. +and is signed by a key listed in each of the trusted +parents' `/.well-known/authorized-committers.nix`, +and the key hasn't expired or been revoked, regardless +of when the commit has made, then the commit is trusted. -#### The format of `/.authorized-committers.nix` +The reason the timestamp of the commit doesn't matter, +is that it's not secure and can be forged. -An example: `/.authorized-committers.nix`: +The reason that a commit only needs one trusted parent, +instead of all parents being trusted like Guix, is that +this allows merging non-trusted commits, while the merge +commit itself would be trusted. + +### The format of `/.well-known/authorized-committers.nix` + +An example: `/.well-known/authorized-committers.nix`: ```nix { committers = { @@ -159,54 +96,101 @@ An example: `/.authorized-committers.nix`: } ``` -Specifically, it will contain a Nix expression, that evaluates -to a set with a single attribute `committers`, which contains +Specifically, it will contain a Nix a set with a single attribute `committers`, which contains another set where names are mapped to PGP fingerprints. This is a set instead of a list to make it easy to get the fingerprint for a specific person. +The fingerprints listed should be registered on at least https://keys.openpgp.org/. + +The file must contain no thunks, and will be a restricted subset of Nix, +like the top-level of `flake.nix`. + +### The Nix interface -### New flake Git inputs +A new command, `nix verify-git` will be added: +`nix verify-git [--always-trust ]` -When a flake input is initialized, there is no good way to check who to trust -automatically, i.e. it is [Trust on First Use](https://en.wikipedia.org/wiki/Trust_on_first_use). +The command will in addition accept all arguments that `builtins.fetchGit` supports, +except `rev`, `name`, and `submodules`. -To secure initializations, new attributes are added to the `git` input type: -- `startsAt` (optional): This is the first commit to use, therefore verification - starts from this commit on. +When run, Nix will fetch the `new` commit, and check if it's +a descendant of `old`. +If not, the command will err. +If it is, then according to the algorithm described above, each +following commit until `new` will be verified for trust, +and the trusted commit that is closest to `new` will be output to stdout. -The standard registry entries will have the `startsAt` attribute -added, to ensure that NixOS users fetch trusted source code. +Users of the command can then check if the output matches `new`, +or use the newest trusted commit if they so wish. -### Other new input attributes +The `--always-trust` argument allows bypassing the usual +algorithm, by always trusting commits signed by the specified +fingerprint. +You can specify this multiple times. -- `insecureUpdate` (optional): If set to true, then the flake will update without errors - to untrusted commits, however it will still emit a warning. -- `alwaysTrust` (optional): Commits signed by these PGP fingerprints will always be trusted. +For example `niv` can then use this to verify that updates to +dependencies are in fact trusted. -## Speeding up fetching Git +### Flakes (experimental) + +While flakes are experimental, they will also be affected by this change. +If flakes are not stabilized, then this section will be of no importance. + +Flake Git inputs will support 3 new optional attributes: +- `verifyFrom`: + The hash for the commit from which verification should start, + if the input is not registered in the lock file. + If not specified, then verification will start from the latest + commit found, which will then be automatically trusted. +- `insecureNoVerify`: If set to `true`, then verification will not be done. +- `alwaysTrust`: A list of PGP fingerprints which should always be trusted, + bypassing the usual verification measures. + +When running `nix flake update` or similar, the Git inputs +would be verified and then set to the newest trusted commit. +In the case that there is a newer commit that isn't trusted, +the user will get a warning like the following: +``` +* 'someinput': 'git+https://github.com/some/input.git?ref=master&rev=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' -> 'git+https://github.com/some/input.git?ref=master&rev=bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' (Untrusted newer commits are available) +``` +In most cases the above situation is likely only temporary, and due to +the untrusted commits being ignored, if the situation is resolved upstream, +downstream users will have no problem and won't have to pay attention to it. + +## Speeding up Git +[speeding up git](#speeding-up-git) + +Taking the below benchmarks into account, we want to make Nix +by default fetch with `--filter=tree:0`. + +### Rationale Cryptographically verifying Git commits is easy, but -Git is currently often not suitable for using as a flake input. +Git is currently often not suitable for fetching in Nix. Nixpkgs is growing at an extreme rate, and with each revision cloning it becomes slower. -For the author, a full clone from scratch takes over 4 minutes. +For the author, a full clone from scratch takes over 4 minutes! -To avoid this problem with the Git protocol, Nix currently -supports the `github` type, which fetches archives from GitHub, -and updates the flake input using proprietary GitHub APIs. -This is GitHub specific, isn't usable on other platforms, and can -not take advantage of the above method for verifying source code -integrity. +Because of this, fetching the tarball through GitHub's APIs +is preferred, as it is much faster (around 60 times for the author). -We can however speed up fetching Git repositories heavily -by passing filters (see man page for `git-clone(1)` and `git-rev-list(1)`): +Since cryptographic verification of updates of repositories +through tarballs coming from GitHub is much harder, +we must fetch the Git commits instead so that we can verify them. +To speed up fetching Git commits, we can make use of relatively new Git features +to only download the parts we need: +- https://github.blog/2020-12-21-get-up-to-speed-with-partial-clone-and-shallow-clone/ +- https://git-scm.com/docs/partial-clone +- https://git-scm.com/docs/shallow +- See man page for `git-clone(1)` and `git-rev-list(1)` and search for `--filter` + +A benchmark from the author of this RFC: - `git clone git://github.com/NixOS/nixpkgs --single-branch --branch=21.05-beta` 4:17 - `git clone git://github.com/NixOS/nixpkgs --single-branch --branch=21.05-beta --filter=blob:none` 1:05 - `git clone git://github.com/NixOS/nixpkgs --single-branch --branch=21.05-beta --filter=tree:0` 0:22 - `git clone git://github.com/NixOS/nixpkgs --single-branch --branch=21.05-beta --depth 1` 0:08 (Almost supported already, see https://github.com/NixOS/nix/issues/5119) -- `curl https://github.com/NixOS/nixpkgs/archive/21.05-beta.tar.gz -LO | tar -xf -` - 0:04 (roughly equivalent to `github:NixOS/nixpkgs?ref=21.05-beta`) +- `curl https://github.com/NixOS/nixpkgs/archive/21.05-beta.tar.gz -LO | tar -xf -` 0:04 Then after doing `cd nixpkgs`, we try fetching `21.05-beta`, which is 659 commits more to pull: @@ -214,81 +198,146 @@ pull: - `git pull --ff-only origin 21.05` 0:08 (after having fetched with `--filter=blob:none`) - `git pull --ff-only origin 21.05` 0:07 (after having fetched with `--filter=tree:0`) - `git clone git://github.com/NixOS/nixpkgs --single-branch --branch=21.05 --depth 1` 0:08 (pulling doesn't work) -- `curl https://github.com/NixOS/nixpkgs/archive/21.05.tar.gz -LO | tar -xf -` - 0:04 (roughly equivalent to `github:NixOS/nixpkgs?ref=21.05`) +- `curl https://github.com/NixOS/nixpkgs/archive/21.05.tar.gz -LO | tar -xf -` 0:04 This is with an 850 EVO SSD, the average download speed from GitHub was around 11 MiB/s according to `git`. -Relevant documentation is: -- https://github.blog/2020-12-21-get-up-to-speed-with-partial-clone-and-shallow-clone/ -- https://git-scm.com/docs/partial-clone -- https://git-scm.com/docs/shallow -We likely want to make Nix use `--filter=tree:0` by default when fetching repositories. -`--depth 1` is faster, but it doesn't preserve the commit history, -and it's not clear how it it interacts with PGP signing. +While `--depth 1` is faster, but due to its nature it's not clear how it interacts with PGP signing. -# Examples and Interactions -[examples-and-interactions]: #examples-and-interactions +## Using this in Nixpkgs and related repositories -Committers will need to adapt to the new workflow before March of 2022. -The command they will run is explained in [signing], but further -information about how to sign commits is out of scope for this RFC. +Nixpkgs is heavily dependent on the GitHub PR workflow. Because of this, we +heavily rely on trusting GitHub, and even signing only merge commits is not +easily possible, since the merge would have to be done outside of the traditional +GitHub workflow. -Relevant documentation for setting up GPG: -- https://guix.gnu.org/manual/en/html_node/Commit-Access.html -- https://www.kernel.org/doc/html/latest/process/maintainer-pgp-guide.html +While we could require that people who commit directly to Nixpkgs sign +their commits, it would be a major change, and would require new tooling +to merge the pull requests. -Flake users will need to become aware of the basics of this system -when using forks of Nixpkgs, as updating such flake inputs -will be different from before. -In addition, flake users should also begin taking use of the features -introduced in this RFC, as they are usable and useful for all flakes. +This tooling is not yet ready, and because of that we can not yet +require that people sign their commits before pushing to Nixpkgs. -## Example flake +However, it is recommended that people attempt +to transition soon, with the [tooling available now](#current-solutions-for-signing-merges), +so that we can know how to improve the tooling, +and to ensure that we can enjoy a more trusted Nixpkgs sooner. -```nix -# flake.nix -{ - inputs.someflake = { - url = "https://github.com/some/flake.git"; - startsAt = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; - startsAtKey = "XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX"; - type = "git"; - }; +The required tooling is listed [below](#tooling-for-signing-merges). +When the tooling is somewhat complete, a new RFC to +discuss requiring signing will be made. - outputs = { someflake }: {}; -} +Specifically, for now for now, Nixpkgs will have a list of authorized +committers, `/.well-known/authorized-committers.nix`, as described +in [verifying trust], with all the authorized committers, +**in addition** to GitHub's public PGP key. + +This won't provide much extra security, since anybody +can sign anything with GitHub's key, but it will lay +the foundation for future improvements to security. + +**Notably**, no part of the current workflow will change with this RFC. + +### Tooling for signing merges + +There are several tools that would make this much more ergonomic, for example: +- Support in GitHub's [CLI](https://github.com/cli/cli) for signing merges: https://github.com/cli/cli/issues/1318. +- Support in GitHub's [desktop GUI](https://github.com/desktop/desktop) for signing merges. +- Support in [Refined GitHub](https://github.com/sindresorhus/refined-github) for signing merges, + perhaps by running Sequoia in WASM. +- Work on https://github.com/withoutboats/bpb/ or https://gitlab.com/wiktor/git-gpg-shim to avoid GPG. +- Solution for merging while on-the-go with your smartphone. + + Browser extension for doing the merge like for Refined GitHub. + + Custom app which you can share the link of a PR with to merge it. + +When the tooling is in place, another RFC to untrust GitHub's key can be made. + +### Current solutions for signing merges + +We can make an ad-hoc script for merging and signing, using the GitHub CLI. +This script has been tested on https://github.com/L-as/test/, +and works for most common scenarios. The PR will be marked as +merged, and in the case that pushing fails due to upstream +having moved, it retries the merge. You need to specify the directory in which +the repository will be in, and it will destroy all +uncommitted changes, since it does a `git reset --hard`. +```bash +#!/bin/sh + +set -xe + +cd /my/nixpkgs/ +git switch master +while true; do + git fetch origin master + git reset --hard origin/master + gh pr checkout "$1" + git switch master + git merge -m "Merged #$1" --no-ff --gpg-sign - + git push origin master && break || true +done ``` -```nix -# some/flake/authorized-committers.nix -{ - committers.some = "XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX"; -} +Another very useful tool is a pre-push hook to verify +that no untrusted commits are pushed. This depends on the +to-be-implemented `nix verify-git` functionality: +```bash +#!/bin/sh +# Put this in .git/hooks/pre-push. + +set -xe + +# This is the "empty hash" used by Git when pushing a branch deletion. +z40=0000000000000000000000000000000000000000 + +while read local_ref local_hash remote_ref remote_hash +do + # Branch deletion; no signature to verify. + if [ "$local_hash" != $z40 ] + then + test "x$(nix verify-git . "$remote_hash" "$local_hash" --ref "$local_ref")" = "$local_hash" + fi +done ``` -Now if `https://github.com/some/flake.git` receives a new commit that can -*not* be trusted according to the algorithm specified in [updating], -we'd get an error like the following if we run `nix flake update`: +## SHA-1 + +Currently, [SHA-1 is a Shambles](https://eprint.iacr.org/2020/014.pdf), meaning that signatures for +commits hashed with SHA-1 can not be trusted fully. +A repository that wishes to improve its security should switch to SHA-256 +(though experimental): +- https://git-scm.com/docs/hash-function-transition/ +- [Git 2.29.0 release notes](https://github.com/git/git/blob/master/Documentation/RelNotes/2.29.0.txt) +- https://sha-mbles.github.io/ (Readable version of the paper) + +In addition, GPG users ought to put the following in `$HOME/.gnupg/gpg.conf`: ``` -* **Failed trust verification!** 'someflake': 'git+https://github.com/some/flake.git?ref=master&rev=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' -!> 'git+https://github.com/some/flake.git?ref=master&rev=bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' (Not signed by a trusted party!) +digest-algo sha512 ``` -Notably, there is nothing that tells the user how to bypass the check -using the `insecureUpdate` attribute, -since if there were, users might very often ignore the error even if valid. +This way they can be sure that they do not use SHA-1 for digestion. + +# Examples and Interactions +[examples-and-interactions]: #examples-and-interactions + +Users who wish to allow others to check their repositories for +trust can choose to use GPG to sign their commits. +Relevant documentation for setting up GPG: +- https://guix.gnu.org/manual/en/html_node/Commit-Access.html +- https://www.kernel.org/doc/html/latest/process/maintainer-pgp-guide.html + +They can also choose from some experimental alternatives: +- https://github.com/withoutboats/bpb/ +- https://gitlab.com/wiktor/git-gpg-shim + +The author of this RFC uses Sequoia for key management, but +GPG to sign their commits. # Drawbacks [drawbacks]: #drawbacks -- Merging PRs can not be done through GitHub. -- Setting up PGP signatures will be a bit extra work for the committers. -- Committers will need to maintain the list of authorized committers. - Fetching Nixpkgs with Nix will take around [5 times](#speeding-up-fetching-git) the time, depending on your hardware. -- Currently building a fork of Nixpkgs (for e.g. a PR) will still work fine, since - the latest commit will be trusted when adding a new flake input, or referring - to one from the commandline, but updating the flake input will fail - since the commits are likely not signed by authorized committers. +- Commits in PRs are not trustable relative to previous ones. # Alternatives [alternatives]: #alternatives @@ -298,34 +347,14 @@ since if there were, users might very often ignore the error even if valid. 2) Not signing every commit prevents you from using the algorithm described in [updating]. Somewhat the same thing can be achieved by the "redirection flake" design described in [future], however. -- We could trust GitHub's PGP key, so that merging can still be done through GitHub. - -# Unresolved questions -[unresolved]: #unresolved-questions -- Should `/.authorized-committers.nix` perhaps not support computation like `flake.nix`? - If it supports computation, in Nixpkgs it could be derived from the maintainer list partially. -- Should we require that repositories that use this mechanism contain - the public keys corresponding to the fingerprints to remove the need for key servers? +Because of this, signing only tags does not make much sense for us. # Future work [future]: #future-work -- Currently, Git still uses SHA-1, which means that you can't - completely trust signatures on SHA-1 repositories, since it is a combination - of the commit message, parent hashes, and tree hashes, that are seemingly signed. - To avoid this, all Git repositories must eventually be transitioned to - SHA-256 when Git support for SHA-256 is stabilized. Users can already - try SHA-256 if they want extra security for their own repositories. - See: - - https://git-scm.com/docs/hash-function-transition/ - - [Git 2.29.0 release notes](https://github.com/git/git/blob/master/Documentation/RelNotes/2.29.0.txt) - - [SHA-1 is a Shambles](https://eprint.iacr.org/2020/014.pdf) - - https://sha-mbles.github.io/ for a more readable version. -- The `github` flake input type could potentially be removed since it doesn't seem to be necessary anymore. -- Instead of an ad-hoc workflow for signing merges, functionality - could be added to https://github.com/desktop/desktop and https://github.com/cli/cli - to support signing merge commits. See https://github.com/cli/cli/issues/1318. +- The `github` flake input type could fetch through Git, since the extra complexity + of the dedicated code for fetching from GitHub doesn't give an extreme speed-up anymore. - To reduce the amount of time fetching Nixpkgs takes, redirection flakes could be introduced. A redirection flake must have no inputs and no outputs. It would have a single `redirection` attribute, with the same format as an input. @@ -339,8 +368,9 @@ since if there were, users might very often ignore the error even if valid. Redirection flakes would have lock files, `/.authorized-committers` as usual. This would be used to make a "lightweight" Nixpkgs repository that tracks the main repository, redirecting using the `tarball` input type. - This repository would also be verified using the method described in [Updating flake Git inputs][updating]. - CI would be put in place to check that the tarballs' contents are the same - as the corresponding commits. + This repository would also be verified using the method described in [verifying trust]. + CI would be put in place to check that: + 1) the tarballs' contents are the same as the corresponding commits. + 2) the new commit is trusted using `nix verify-git`. - Verify the sources used in Nixpkgs to the extent possible. This would be done on a per-package basis since it depends on how upstream signs their source code (if at all). From 05e13852be6f32e7167171c9816a98cc94a51622 Mon Sep 17 00:00:00 2001 From: Las Safin Date: Sun, 15 Aug 2021 17:02:46 +0000 Subject: [PATCH 09/11] Make wording more clear --- rfcs/0100-sign-commits.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rfcs/0100-sign-commits.md b/rfcs/0100-sign-commits.md index 941edf677..f037941d4 100644 --- a/rfcs/0100-sign-commits.md +++ b/rfcs/0100-sign-commits.md @@ -230,7 +230,8 @@ discuss requiring signing will be made. Specifically, for now for now, Nixpkgs will have a list of authorized committers, `/.well-known/authorized-committers.nix`, as described in [verifying trust], with all the authorized committers, -**in addition** to GitHub's public PGP key. +**in addition** to GitHub's public PGP key, +but only until the tooling is done. This won't provide much extra security, since anybody can sign anything with GitHub's key, but it will lay From 54236bd41e4086da0001d2f999c425f9ef8337ec Mon Sep 17 00:00:00 2001 From: Las Safin Date: Sun, 15 Aug 2021 17:11:44 +0000 Subject: [PATCH 10/11] [RFC 0100 work] Further improve wording --- rfcs/0100-sign-commits.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/rfcs/0100-sign-commits.md b/rfcs/0100-sign-commits.md index f037941d4..93f2241f2 100644 --- a/rfcs/0100-sign-commits.md +++ b/rfcs/0100-sign-commits.md @@ -227,7 +227,8 @@ The required tooling is listed [below](#tooling-for-signing-merges). When the tooling is somewhat complete, a new RFC to discuss requiring signing will be made. -Specifically, for now for now, Nixpkgs will have a list of authorized +Specifically, for now for now, we will +have a transitional phase, where Nixpkgs will have a list of authorized committers, `/.well-known/authorized-committers.nix`, as described in [verifying trust], with all the authorized committers, **in addition** to GitHub's public PGP key, @@ -235,7 +236,9 @@ but only until the tooling is done. This won't provide much extra security, since anybody can sign anything with GitHub's key, but it will lay -the foundation for future improvements to security. +the foundation for future improvements to security, +so that eventually we can remove GitHub's key and +get out of the transitional phase. **Notably**, no part of the current workflow will change with this RFC. From a30e134741d1604cbd25c67eb80ae53ffc0dd14d Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 3 Nov 2021 15:17:08 +0100 Subject: [PATCH 11/11] Add shepherds --- rfcs/0100-sign-commits.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rfcs/0100-sign-commits.md b/rfcs/0100-sign-commits.md index 93f2241f2..acc5056d5 100644 --- a/rfcs/0100-sign-commits.md +++ b/rfcs/0100-sign-commits.md @@ -3,8 +3,8 @@ feature: sign-commits start-date: 2021-08-14 author: Las Safin co-authors: -shepherd-team: -shepherd-leader: +shepherd-team: znewman01, tomberek, hmenke +shepherd-leader: tomberek related-issues: https://github.com/NixOS/rfcs/pull/34 ---