[Nix#6414] SRI SHA256 hashes are not 1 to 1 with hexadecimal versions #138

Open
opened 2024-03-16 06:45:07 +00:00 by lix-bot · 1 comment
Member

Upstream-Issue: NixOS/nix#6414

SRI SHA256 hashes are encoded in base64, which is 6 bits per character in 4-character blocks. 256 / 24 = ~10.7 and 256 - (10 * 24) = 16, so the last block of 24 bits and 4 characters will only be encoding 16 bits. The extra 8 bits are ignored in Nix.

There is no longer a 1-1 correspondence between the SRI SHA256 hash and the actual contents that is being hashed. Here I use the conversion tool but this happens internally in nix:

$  nix --version
nix (Nix) 2.3.16
# Unchanged in 2.5.1

$ nix to-sri --type sha256 0000000000000000000000000000000000000000000000000000000000000000
sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=

$ nix to-base16 sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
0000000000000000000000000000000000000000000000000000000000000000

$ nix to-base16 sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB=
0000000000000000000000000000000000000000000000000000000000000000

$ nix to-base16 sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC=
0000000000000000000000000000000000000000000000000000000000000000

$ nix to-base16 sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD=
0000000000000000000000000000000000000000000000000000000000000000

$ nix to-base16 sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE=
0000000000000000000000000000000000000000000000000000000000000001

When upgrading packages, it is sometimes suggested to change the hash of a resource, run a build, and get the correct hash from the resulting error. This is how I discovered this bug - changing the resource hash continued to use the old resource!

I propose validating that the extra 8 bits in SRI SHA256 hashes are unset. If any are set, throw "error: invalid SRI hash".

Upstream-Issue: https://git.lix.systems/NixOS/nix/issues/6414 SRI SHA256 hashes are encoded in base64, which is 6 bits per character in 4-character blocks. 256 / 24 = ~10.7 and 256 - (10 * 24) = 16, so the last block of 24 bits and 4 characters will only be encoding 16 bits. The extra 8 bits are ignored in Nix. There is no longer a 1-1 correspondence between the SRI SHA256 hash and the actual contents that is being hashed. Here I use the conversion tool but this happens internally in nix: ``` $ nix --version nix (Nix) 2.3.16 # Unchanged in 2.5.1 $ nix to-sri --type sha256 0000000000000000000000000000000000000000000000000000000000000000 sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= $ nix to-base16 sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= 0000000000000000000000000000000000000000000000000000000000000000 $ nix to-base16 sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB= 0000000000000000000000000000000000000000000000000000000000000000 $ nix to-base16 sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC= 0000000000000000000000000000000000000000000000000000000000000000 $ nix to-base16 sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD= 0000000000000000000000000000000000000000000000000000000000000000 $ nix to-base16 sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE= 0000000000000000000000000000000000000000000000000000000000000001 ``` When upgrading packages, it is sometimes suggested to change the hash of a resource, run a build, and get the correct hash from the resulting error. This is how I discovered this bug - changing the resource hash continued to use the old resource! I propose validating that the extra 8 bits in SRI SHA256 hashes are unset. If any are set, throw "error: invalid SRI hash".
lix-bot added the
bug
imported
labels 2024-03-16 06:45:07 +00:00
lunaphied self-assigned this 2024-03-19 05:16:04 +00:00
Owner

This will be subtle to fix, as we likely want to do a staged rollout of this tightening: Before all else, put a hard assertion in nixpkgs that the hashes don't have random junk at the end; this will eliminate any excuses for new ones showing up, or compat breakage caused by doing it.

First, warn and fix the hashes going into the derivation builder, then in the next release deny by default with an unprivileged setting to allow them, still fixing as they go into the builder.

This will be subtle to fix, as we likely want to do a staged rollout of this tightening: Before all else, put a hard assertion in nixpkgs that the hashes don't have random junk at the end; this will eliminate any excuses for new ones showing up, or compat breakage caused by doing it. First, warn *and fix the hashes going into the derivation builder*, then in the next release deny by default with an unprivileged setting to allow them, still fixing as they go into the builder.
Sign in to join this conversation.
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lix-project/lix#138
No description provided.