nix-hash: support base-64 and SRI format

Add the --base64 and --sri flags for the Base64 and SRI format output.

Add the --base16 flag to explicitly specify the hexadecimal format.

Add the --to-base64 and --to-sri flag to convert a hash to the above
mentioned format.
This commit is contained in:
Yueh-Shun Li 2023-03-16 00:33:58 +08:00
parent 08510c5ed0
commit c27d358abb
4 changed files with 91 additions and 17 deletions

View file

@ -6,9 +6,7 @@
`nix-hash` [`--flat`] [`--base32`] [`--truncate`] [`--type` *hashAlgo*] *path…* `nix-hash` [`--flat`] [`--base32`] [`--truncate`] [`--type` *hashAlgo*] *path…*
`nix-hash` `--to-base16` *hash…* `nix-hash` [`--to-base16`|`--to-base32`|`--to-base64`|`--to-sri`] [`--type` *hashAlgo*] *hash…*
`nix-hash` `--to-base32` *hash…*
# Description # Description
@ -35,11 +33,23 @@ md5sum`.
The result is identical to that produced by the GNU commands The result is identical to that produced by the GNU commands
`md5sum` and `sha1sum`. `md5sum` and `sha1sum`.
- `--base16`\
Print the hash in a hexadecimal representation (default).
- `--base32`\ - `--base32`\
Print the hash in a base-32 representation rather than hexadecimal. Print the hash in a base-32 representation rather than hexadecimal.
This base-32 representation is more compact and can be used in Nix This base-32 representation is more compact and can be used in Nix
expressions (such as in calls to `fetchurl`). expressions (such as in calls to `fetchurl`).
- `--base64`\
Similar to --base32, but print the hash in a base-64 representation,
which is more compact than the base-32 one.
- `--sri`\
Print the hash in SRI format with base-64 encoding.
The type of hash algorithm will be prepended to the hash string,
followed by a hyphen (-) and the base-64 hash body.
- `--truncate`\ - `--truncate`\
Truncate hashes longer than 160 bits (such as SHA-256) to 160 bits. Truncate hashes longer than 160 bits (such as SHA-256) to 160 bits.
@ -55,6 +65,14 @@ md5sum`.
Dont hash anything, but convert the hexadecimal hash representation Dont hash anything, but convert the hexadecimal hash representation
*hash* to base-32. *hash* to base-32.
- `--to-base64`\
Dont hash anything, but convert the hexadecimal hash representation
*hash* to base-64.
- `--to-sri`\
Dont hash anything, but convert the hexadecimal hash representation
*hash* to SRI.
# Examples # Examples
Computing the same hash as `nix-prefetch-url`: Computing the same hash as `nix-prefetch-url`:
@ -81,9 +99,18 @@ $ nix-store --dump test/ | md5sum (for comparison)
$ nix-hash --type sha1 test/ $ nix-hash --type sha1 test/
e4fd8ba5f7bbeaea5ace89fe10255536cd60dab6 e4fd8ba5f7bbeaea5ace89fe10255536cd60dab6
$ nix-hash --type sha1 --base16 test/
e4fd8ba5f7bbeaea5ace89fe10255536cd60dab6
$ nix-hash --type sha1 --base32 test/ $ nix-hash --type sha1 --base32 test/
nvd61k9nalji1zl9rrdfmsmvyyjqpzg4 nvd61k9nalji1zl9rrdfmsmvyyjqpzg4
$ nix-hash --type sha1 --base64 test/
5P2Lpfe76upazon+ECVVNs1g2rY=
$ nix-hash --type sha1 --sri test/
sha1-5P2Lpfe76upazon+ECVVNs1g2rY=
$ nix-hash --type sha256 --flat test/ $ nix-hash --type sha256 --flat test/
error: reading file `test/': Is a directory error: reading file `test/': Is a directory
@ -91,7 +118,7 @@ $ nix-hash --type sha256 --flat test/world
5891b5b522d5df086d0ff0b110fbd9d21bb4fc7163af34d08286a2e846f6be03 5891b5b522d5df086d0ff0b110fbd9d21bb4fc7163af34d08286a2e846f6be03
``` ```
Converting between hexadecimal and base-32: Converting between hexadecimal, base-32, base-64, and SRI:
```console ```console
$ nix-hash --type sha1 --to-base32 e4fd8ba5f7bbeaea5ace89fe10255536cd60dab6 $ nix-hash --type sha1 --to-base32 e4fd8ba5f7bbeaea5ace89fe10255536cd60dab6
@ -99,4 +126,13 @@ nvd61k9nalji1zl9rrdfmsmvyyjqpzg4
$ nix-hash --type sha1 --to-base16 nvd61k9nalji1zl9rrdfmsmvyyjqpzg4 $ nix-hash --type sha1 --to-base16 nvd61k9nalji1zl9rrdfmsmvyyjqpzg4
e4fd8ba5f7bbeaea5ace89fe10255536cd60dab6 e4fd8ba5f7bbeaea5ace89fe10255536cd60dab6
$ nix-hash --type sha1 --to-base64 e4fd8ba5f7bbeaea5ace89fe10255536cd60dab6
5P2Lpfe76upazon+ECVVNs1g2rY=
$ nix-hash --type sha1 --to-sri nvd61k9nalji1zl9rrdfmsmvyyjqpzg4
sha1-5P2Lpfe76upazon+ECVVNs1g2rY=
$ nix-hash --to-base16 sha1-5P2Lpfe76upazon+ECVVNs1g2rY=
e4fd8ba5f7bbeaea5ace89fe10255536cd60dab6
``` ```

View file

@ -4,6 +4,13 @@
passed the `--stdin` flag. This is primarily useful when you have a large amount of paths which passed the `--stdin` flag. This is primarily useful when you have a large amount of paths which
exceed the OS arg limit. exceed the OS arg limit.
* The `nix-hash` command now supports Base64 and SRI. Use the flags `--base64`
or `--sri` to specify the format of output hash as Base64 or SRI, and `--to-base64`
or `--to-sri` to convert a hash to Base64 or SRI format, respectively.
As the choice of hash formats is no longer binary, the `--base16` flag is also added
to explicitly specify the Base16 format, which is still the default.
* The special handling of an [installable](../command-ref/new-cli/nix.md#installables) with `.drv` suffix being interpreted as all of the given [store derivation](../glossary.md#gloss-store-derivation)'s output paths is removed, and instead taken as the literal store path that it represents. * The special handling of an [installable](../command-ref/new-cli/nix.md#installables) with `.drv` suffix being interpreted as all of the given [store derivation](../glossary.md#gloss-store-derivation)'s output paths is removed, and instead taken as the literal store path that it represents.
The new `^` syntax for store paths introduced in Nix 2.13 allows explicitly referencing output paths of a derivation. The new `^` syntax for store paths introduced in Nix 2.13 allows explicitly referencing output paths of a derivation.

View file

@ -161,11 +161,11 @@ static auto rCmdHash = registerCommand<CmdHash>("hash");
/* Legacy nix-hash command. */ /* Legacy nix-hash command. */
static int compatNixHash(int argc, char * * argv) static int compatNixHash(int argc, char * * argv)
{ {
HashType ht = htMD5; std::optional<HashType> ht;
bool flat = false; bool flat = false;
bool base32 = false; Base base = Base16;
bool truncate = false; bool truncate = false;
enum { opHash, opTo32, opTo16 } op = opHash; enum { opHash, opTo } op = opHash;
std::vector<std::string> ss; std::vector<std::string> ss;
parseCmdLine(argc, argv, [&](Strings::iterator & arg, const Strings::iterator & end) { parseCmdLine(argc, argv, [&](Strings::iterator & arg, const Strings::iterator & end) {
@ -174,14 +174,31 @@ static int compatNixHash(int argc, char * * argv)
else if (*arg == "--version") else if (*arg == "--version")
printVersion("nix-hash"); printVersion("nix-hash");
else if (*arg == "--flat") flat = true; else if (*arg == "--flat") flat = true;
else if (*arg == "--base32") base32 = true; else if (*arg == "--base16") base = Base16;
else if (*arg == "--base32") base = Base32;
else if (*arg == "--base64") base = Base64;
else if (*arg == "--sri") base = SRI;
else if (*arg == "--truncate") truncate = true; else if (*arg == "--truncate") truncate = true;
else if (*arg == "--type") { else if (*arg == "--type") {
std::string s = getArg(*arg, arg, end); std::string s = getArg(*arg, arg, end);
ht = parseHashType(s); ht = parseHashType(s);
} }
else if (*arg == "--to-base16") op = opTo16; else if (*arg == "--to-base16") {
else if (*arg == "--to-base32") op = opTo32; op = opTo;
base = Base16;
}
else if (*arg == "--to-base32") {
op = opTo;
base = Base32;
}
else if (*arg == "--to-base64") {
op = opTo;
base = Base64;
}
else if (*arg == "--to-sri") {
op = opTo;
base = SRI;
}
else if (*arg != "" && arg->at(0) == '-') else if (*arg != "" && arg->at(0) == '-')
return false; return false;
else else
@ -191,17 +208,18 @@ static int compatNixHash(int argc, char * * argv)
if (op == opHash) { if (op == opHash) {
CmdHashBase cmd(flat ? FileIngestionMethod::Flat : FileIngestionMethod::Recursive); CmdHashBase cmd(flat ? FileIngestionMethod::Flat : FileIngestionMethod::Recursive);
cmd.ht = ht; if (!ht.has_value()) ht = htMD5;
cmd.base = base32 ? Base32 : Base16; cmd.ht = ht.value();
cmd.base = base;
cmd.truncate = truncate; cmd.truncate = truncate;
cmd.paths = ss; cmd.paths = ss;
cmd.run(); cmd.run();
} }
else { else {
CmdToBase cmd(op == opTo32 ? Base32 : Base16); CmdToBase cmd(base);
cmd.args = ss; cmd.args = ss;
cmd.ht = ht; if (ht.has_value()) cmd.ht = ht;
cmd.run(); cmd.run();
} }

View file

@ -2,9 +2,14 @@ source common.sh
try () { try () {
printf "%s" "$2" > $TEST_ROOT/vector printf "%s" "$2" > $TEST_ROOT/vector
hash="$(nix-hash --flat ${FORMAT_FLAG-} --type "$1" "$TEST_ROOT/vector")"
if ! (( "${NO_TEST_CLASSIC-}" )) && test "$hash" != "$3"; then
echo "try nix-hash: hash $1, expected $3, got $hash"
exit 1
fi
hash="$(nix hash file ${FORMAT_FLAG-} --type "$1" "$TEST_ROOT/vector")" hash="$(nix hash file ${FORMAT_FLAG-} --type "$1" "$TEST_ROOT/vector")"
if test "$hash" != "$3"; then if ! (( "${NO_TEST_NIX_COMMAND-}" )) && test "$hash" != "$3"; then
echo "hash $1, expected $3, got $hash" echo "try nix hash: hash $1, expected $3, got $hash"
exit 1 exit 1
fi fi
} }
@ -42,7 +47,11 @@ try sha512 "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" "sha512-IE
try sha256 "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" "sha256-JI1qYdIGOLjlwCaTDD5gOaM85Flk/yFn9uzt1BnbBsE=" try sha256 "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" "sha256-JI1qYdIGOLjlwCaTDD5gOaM85Flk/yFn9uzt1BnbBsE="
unset FORMAT_FLAG unset FORMAT_FLAG
try sha512 "abc" "sha512-3a81oZNherrMQXNJriBBMRLm+k6JqX6iCp7u5ktV05ohkpkqJ0/BqDa6PCOj/uu9RU1EI2Q86A4qmslPpUyknw==" # nix-hash [--flat] defaults to the Base16 format
NO_TEST_NIX_COMMAND=1 try sha512 "abc" "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"
# nix hash [file|path] defaults to the SRI format
NO_TEST_CLASSIC=1 try sha512 "abc" "sha512-3a81oZNherrMQXNJriBBMRLm+k6JqX6iCp7u5ktV05ohkpkqJ0/BqDa6PCOj/uu9RU1EI2Q86A4qmslPpUyknw=="
try2 () { try2 () {
hash=$(nix-hash --type "$1" $TEST_ROOT/hash-path) hash=$(nix-hash --type "$1" $TEST_ROOT/hash-path)
@ -74,8 +83,12 @@ try2 md5 "f78b733a68f5edbdf9413899339eaa4a"
# Conversion. # Conversion.
try3() { try3() {
h64=$(nix-hash --type "$1" --to-base64 "$2")
[ "$h64" = "$4" ]
h64=$(nix hash to-base64 --type "$1" "$2") h64=$(nix hash to-base64 --type "$1" "$2")
[ "$h64" = "$4" ] [ "$h64" = "$4" ]
sri=$(nix-hash --type "$1" --to-sri "$2")
[ "$sri" = "$1-$4" ]
sri=$(nix hash to-sri --type "$1" "$2") sri=$(nix hash to-sri --type "$1" "$2")
[ "$sri" = "$1-$4" ] [ "$sri" = "$1-$4" ]
h32=$(nix-hash --type "$1" --to-base32 "$2") h32=$(nix-hash --type "$1" --to-base32 "$2")