aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/libexpr/primops.cc10
-rw-r--r--src/libutil/hash.cc34
-rw-r--r--src/libutil/hash.hh7
-rw-r--r--src/nix-store/nix-store.cc3
-rw-r--r--src/nix/hash.cc23
5 files changed, 45 insertions, 32 deletions
diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc
index 7372134e2..60698f740 100644
--- a/src/libexpr/primops.cc
+++ b/src/libexpr/primops.cc
@@ -724,16 +724,14 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
if (outputs.size() != 1 || *(outputs.begin()) != "out")
throw Error(format("multiple outputs are not supported in fixed-output derivations, at %1%") % posDrvName);
- HashType ht = parseHashType(outputHashAlgo);
- if (ht == htUnknown)
- throw EvalError(format("unknown hash algorithm '%1%', at %2%") % outputHashAlgo % posDrvName);
+ HashType ht = outputHashAlgo.empty() ? htUnknown : parseHashType(outputHashAlgo);
Hash h(*outputHash, ht);
- outputHash = h.to_string(Base16, false);
- if (outputHashRecursive) outputHashAlgo = "r:" + outputHashAlgo;
Path outPath = state.store->makeFixedOutputPath(outputHashRecursive, h, drvName);
if (!jsonObject) drv.env["out"] = outPath;
- drv.outputs["out"] = DerivationOutput(outPath, outputHashAlgo, *outputHash);
+ drv.outputs["out"] = DerivationOutput(outPath,
+ (outputHashRecursive ? "r:" : "") + printHashType(h.type),
+ h.to_string(Base16, false));
}
else {
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);
}
diff --git a/src/libutil/hash.hh b/src/libutil/hash.hh
index fd7a61df8..2dbc3b630 100644
--- a/src/libutil/hash.hh
+++ b/src/libutil/hash.hh
@@ -20,7 +20,7 @@ const int sha512HashSize = 64;
extern const string base32Chars;
-enum Base : int { Base64, Base32, Base16 };
+enum Base : int { Base64, Base32, Base16, SRI };
struct Hash
@@ -38,8 +38,9 @@ struct Hash
Hash(HashType type) : type(type) { init(); };
/* Initialize the hash from a string representation, in the format
- "[<type>:]<base16|base32|base64>". If the 'type' argument is
- htUnknown, then the hash type must be specified in the
+ "[<type>:]<base16|base32|base64>" or "<type>-<base64>" (a
+ Subresource Integrity hash expression). If the 'type' argument
+ is htUnknown, then the hash type must be specified in the
string. */
Hash(const std::string & s, HashType type = htUnknown);
diff --git a/src/nix-store/nix-store.cc b/src/nix-store/nix-store.cc
index a9ad14762..5b37237eb 100644
--- a/src/nix-store/nix-store.cc
+++ b/src/nix-store/nix-store.cc
@@ -1000,6 +1000,9 @@ static int _main(int argc, char * * argv)
Strings opFlags, opArgs;
Operation op = 0;
+ Hash h("sha512-Q2bFTOhEALkN8hOms2FKTDLy7eugP2zFZ1T8LCvX42Fp3WoNr3bjZSAHeOsHrbV1Fu9/A0EzCinRE7Af1ofPrw==");
+ printError("GOT HASH %s", h.to_string(Base64));
+
parseCmdLine(argc, argv, [&](Strings::iterator & arg, const Strings::iterator & end) {
Operation oldOp = op;
diff --git a/src/nix/hash.cc b/src/nix/hash.cc
index 64062fb97..af4105e28 100644
--- a/src/nix/hash.cc
+++ b/src/nix/hash.cc
@@ -9,13 +9,14 @@ struct CmdHash : Command
{
enum Mode { mFile, mPath };
Mode mode;
- Base base = Base16;
+ Base base = SRI;
bool truncate = false;
- HashType ht = htSHA512;
+ HashType ht = htSHA256;
std::vector<std::string> paths;
CmdHash(Mode mode) : mode(mode)
{
+ mkFlag(0, "sri", "print hash in SRI format", &base, SRI);
mkFlag(0, "base64", "print hash in base-64", &base, Base64);
mkFlag(0, "base32", "print hash in base-32 (Nix-specific)", &base, Base32);
mkFlag(0, "base16", "print hash in base-16", &base, Base16);
@@ -43,7 +44,7 @@ struct CmdHash : Command
Hash h = mode == mFile ? hashFile(ht, path) : hashPath(ht, path).first;
if (truncate && h.hashSize > 20) h = compressHash(h, 20);
std::cout << format("%1%\n") %
- h.to_string(base, false);
+ h.to_string(base, base == SRI);
}
}
};
@@ -54,7 +55,7 @@ static RegisterCommand r2(make_ref<CmdHash>(CmdHash::mPath));
struct CmdToBase : Command
{
Base base;
- HashType ht = htSHA512;
+ HashType ht = htUnknown;
std::vector<std::string> args;
CmdToBase(Base base) : base(base)
@@ -70,26 +71,30 @@ struct CmdToBase : Command
return
base == Base16 ? "to-base16" :
base == Base32 ? "to-base32" :
- "to-base64";
+ base == Base64 ? "to-base64" :
+ "to-sri";
}
std::string description() override
{
- return fmt("convert a hash to base-%d representation",
- base == Base16 ? 16 :
- base == Base32 ? 32 : 64);
+ return fmt("convert a hash to %s representation",
+ base == Base16 ? "base-16" :
+ base == Base32 ? "base-32" :
+ base == Base64 ? "base-64" :
+ "SRI");
}
void run() override
{
for (auto s : args)
- std::cout << fmt("%s\n", Hash(s, ht).to_string(base, false));
+ std::cout << fmt("%s\n", Hash(s, ht).to_string(base, base == SRI));
}
};
static RegisterCommand r3(make_ref<CmdToBase>(Base16));
static RegisterCommand r4(make_ref<CmdToBase>(Base32));
static RegisterCommand r5(make_ref<CmdToBase>(Base64));
+static RegisterCommand r6(make_ref<CmdToBase>(SRI));
/* Legacy nix-hash command. */
static int compatNixHash(int argc, char * * argv)