aboutsummaryrefslogtreecommitdiff
path: root/src/libutil/hash.cc
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2018-12-13 14:30:52 +0100
committerEelco Dolstra <edolstra@gmail.com>2018-12-13 14:30:52 +0100
commit6024dc1d97212130c19d3ff5ce6b1d102837eee6 (patch)
tree71ad514b53863fc00ed4b8cff710dec1e792b056 /src/libutil/hash.cc
parentc37e6d77ea86df249aeaf65d329a6be3b837ad62 (diff)
Support SRI hashes
SRI hashes (https://www.w3.org/TR/SRI/) combine the hash algorithm and a base-64 hash. This allows more concise and standard hash specifications. For example, instead of import <nix/fetchurl.nl> { url = https://nixos.org/releases/nix/nix-2.1.3/nix-2.1.3.tar.xz; sha256 = "5d22dad058d5c800d65a115f919da22938c50dd6ba98c5e3a183172d149840a4"; }; you can write import <nix/fetchurl.nl> { url = https://nixos.org/releases/nix/nix-2.1.3/nix-2.1.3.tar.xz; hash = "sha256-XSLa0FjVyADWWhFfkZ2iKTjFDda6mMXjoYMXLRSYQKQ="; }; In fixed-output derivations, the outputHashAlgo is no longer mandatory if outputHash specifies the hash (either as an SRI or in the old "<type>:<hash>" format). 'nix hash-{file,path}' now print hashes in SRI format by default. I also reverted them to use SHA-256 by default because that's what we're using most of the time in Nixpkgs. Suggested by @zimbatm.
Diffstat (limited to 'src/libutil/hash.cc')
-rw-r--r--src/libutil/hash.cc34
1 files changed, 20 insertions, 14 deletions
diff --git a/src/libutil/hash.cc b/src/libutil/hash.cc
index 9d82f13a5..1c14ebb18 100644
--- a/src/libutil/hash.cc
+++ b/src/libutil/hash.cc
@@ -105,9 +105,9 @@ string printHash16or32(const Hash & hash)
std::string Hash::to_string(Base base, bool includeType) const
{
std::string s;
- if (includeType) {
+ if (base == SRI || includeType) {
s += printHashType(type);
- s += ':';
+ s += base == SRI ? '-' : ':';
}
switch (base) {
case Base16:
@@ -117,6 +117,7 @@ std::string Hash::to_string(Base base, bool includeType) const
s += printHash32(*this);
break;
case Base64:
+ case SRI:
s += base64Encode(std::string((const char *) hash, hashSize));
break;
}
@@ -127,28 +128,33 @@ std::string Hash::to_string(Base base, bool includeType) const
Hash::Hash(const std::string & s, HashType type)
: type(type)
{
- auto colon = s.find(':');
-
size_t pos = 0;
-
- if (colon == string::npos) {
- if (type == htUnknown)
+ bool isSRI = false;
+
+ auto sep = s.find(':');
+ if (sep == string::npos) {
+ sep = s.find('-');
+ if (sep != string::npos) {
+ isSRI = true;
+ } else if (type == htUnknown)
throw BadHash("hash '%s' does not include a type", s);
- } else {
- string hts = string(s, 0, colon);
+ }
+
+ if (sep != string::npos) {
+ string hts = string(s, 0, sep);
this->type = parseHashType(hts);
if (this->type == htUnknown)
throw BadHash("unknown hash type '%s'", hts);
if (type != htUnknown && type != this->type)
throw BadHash("hash '%s' should have type '%s'", s, printHashType(type));
- pos = colon + 1;
+ pos = sep + 1;
}
init();
size_t size = s.size() - pos;
- if (size == base16Len()) {
+ if (!isSRI && size == base16Len()) {
auto parseHexDigit = [&](char c) {
if (c >= '0' && c <= '9') return c - '0';
@@ -164,7 +170,7 @@ Hash::Hash(const std::string & s, HashType type)
}
}
- else if (size == base32Len()) {
+ else if (!isSRI && size == base32Len()) {
for (unsigned int n = 0; n < size; ++n) {
char c = s[pos + size - n - 1];
@@ -187,10 +193,10 @@ Hash::Hash(const std::string & s, HashType type)
}
}
- else if (size == base64Len()) {
+ else if (isSRI || size == base64Len()) {
auto d = base64Decode(std::string(s, pos));
if (d.size() != hashSize)
- throw BadHash("invalid base-64 hash '%s'", s);
+ throw BadHash("invalid %s hash '%s'", isSRI ? "SRI" : "base-64", s);
assert(hashSize);
memcpy(hash, d.data(), hashSize);
}