2003-06-16 15:59:23 +00:00
|
|
|
#include <iostream>
|
2008-05-21 11:17:31 +00:00
|
|
|
#include <cstring>
|
2003-06-16 15:59:23 +00:00
|
|
|
|
2006-02-13 19:52:43 +00:00
|
|
|
#include <openssl/md5.h>
|
|
|
|
#include <openssl/sha.h>
|
2003-06-15 13:41:32 +00:00
|
|
|
|
2020-06-02 15:52:13 +00:00
|
|
|
#include "args.hh"
|
2003-06-15 13:41:32 +00:00
|
|
|
#include "hash.hh"
|
2003-06-20 10:40:25 +00:00
|
|
|
#include "archive.hh"
|
2006-09-04 21:06:23 +00:00
|
|
|
#include "util.hh"
|
2017-03-21 13:43:03 +00:00
|
|
|
#include "istringstream_nocopy.hh"
|
2003-06-15 13:41:32 +00:00
|
|
|
|
2005-01-13 17:39:26 +00:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
2006-09-04 21:06:23 +00:00
|
|
|
namespace nix {
|
|
|
|
|
|
|
|
|
2017-07-04 12:47:59 +00:00
|
|
|
void Hash::init()
|
2005-01-14 16:04:03 +00:00
|
|
|
{
|
2020-06-02 20:35:17 +00:00
|
|
|
if (!type) abort();
|
|
|
|
switch (*type) {
|
2020-06-18 22:09:22 +00:00
|
|
|
case htMD5: hashSize = md5HashSize; break;
|
|
|
|
case htSHA1: hashSize = sha1HashSize; break;
|
|
|
|
case htSHA256: hashSize = sha256HashSize; break;
|
|
|
|
case htSHA512: hashSize = sha512HashSize; break;
|
2020-06-02 20:35:17 +00:00
|
|
|
}
|
2005-01-14 13:51:38 +00:00
|
|
|
assert(hashSize <= maxHashSize);
|
2005-01-14 16:04:03 +00:00
|
|
|
memset(hash, 0, maxHashSize);
|
2003-06-15 13:41:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-07-15 22:28:27 +00:00
|
|
|
bool Hash::operator == (const Hash & h2) const
|
2003-06-15 13:41:32 +00:00
|
|
|
{
|
2005-01-13 15:44:44 +00:00
|
|
|
if (hashSize != h2.hashSize) return false;
|
2003-06-15 13:41:32 +00:00
|
|
|
for (unsigned int i = 0; i < hashSize; i++)
|
|
|
|
if (hash[i] != h2.hash[i]) return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-07-15 22:28:27 +00:00
|
|
|
bool Hash::operator != (const Hash & h2) const
|
2003-06-15 13:41:32 +00:00
|
|
|
{
|
|
|
|
return !(*this == h2);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-07-15 21:24:05 +00:00
|
|
|
bool Hash::operator < (const Hash & h) const
|
|
|
|
{
|
2017-06-24 00:17:45 +00:00
|
|
|
if (hashSize < h.hashSize) return true;
|
|
|
|
if (hashSize > h.hashSize) return false;
|
2003-07-15 21:24:05 +00:00
|
|
|
for (unsigned int i = 0; i < hashSize; i++) {
|
|
|
|
if (hash[i] < h.hash[i]) return true;
|
|
|
|
if (hash[i] > h.hash[i]) return false;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-03-09 17:07:25 +00:00
|
|
|
const string base16Chars = "0123456789abcdef";
|
|
|
|
|
|
|
|
|
2017-07-04 12:47:59 +00:00
|
|
|
static string printHash16(const Hash & hash)
|
2003-06-15 13:41:32 +00:00
|
|
|
{
|
2006-03-09 17:07:25 +00:00
|
|
|
char buf[hash.hashSize * 2];
|
2005-01-14 16:04:03 +00:00
|
|
|
for (unsigned int i = 0; i < hash.hashSize; i++) {
|
2006-03-09 17:07:25 +00:00
|
|
|
buf[i * 2] = base16Chars[hash.hash[i] >> 4];
|
|
|
|
buf[i * 2 + 1] = base16Chars[hash.hash[i] & 0x0f];
|
2003-06-15 13:41:32 +00:00
|
|
|
}
|
2006-03-09 17:07:25 +00:00
|
|
|
return string(buf, hash.hashSize * 2);
|
2003-06-15 13:41:32 +00:00
|
|
|
}
|
|
|
|
|
2015-02-03 17:35:11 +00:00
|
|
|
|
2005-01-14 16:04:03 +00:00
|
|
|
// omitted: E O U T
|
2005-11-16 08:27:06 +00:00
|
|
|
const string base32Chars = "0123456789abcdfghijklmnpqrsvwxyz";
|
2005-01-14 16:04:03 +00:00
|
|
|
|
|
|
|
|
2017-07-04 12:47:59 +00:00
|
|
|
static string printHash32(const Hash & hash)
|
2005-01-14 16:04:03 +00:00
|
|
|
{
|
2016-07-21 16:39:32 +00:00
|
|
|
assert(hash.hashSize);
|
2016-01-27 16:18:20 +00:00
|
|
|
size_t len = hash.base32Len();
|
2016-04-20 12:12:38 +00:00
|
|
|
assert(len);
|
2005-11-16 08:27:06 +00:00
|
|
|
|
2015-02-03 17:35:11 +00:00
|
|
|
string s;
|
|
|
|
s.reserve(len);
|
|
|
|
|
2018-05-02 11:56:34 +00:00
|
|
|
for (int n = (int) len - 1; n >= 0; n--) {
|
2015-02-03 17:35:11 +00:00
|
|
|
unsigned int b = n * 5;
|
|
|
|
unsigned int i = b / 8;
|
|
|
|
unsigned int j = b % 8;
|
|
|
|
unsigned char c =
|
|
|
|
(hash.hash[i] >> j)
|
|
|
|
| (i >= hash.hashSize - 1 ? 0 : hash.hash[i + 1] << (8 - j));
|
|
|
|
s.push_back(base32Chars[c & 0x1f]);
|
2005-01-14 16:04:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-10-23 16:05:50 +00:00
|
|
|
string printHash16or32(const Hash & hash)
|
|
|
|
{
|
2020-06-18 22:09:22 +00:00
|
|
|
return hash.to_string(hash.type == htMD5 ? Base16 : Base32, false);
|
2012-10-23 16:05:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-06-02 15:52:13 +00:00
|
|
|
HashType assertInitHashType(const Hash & h) {
|
|
|
|
if (h.type)
|
|
|
|
return *h.type;
|
|
|
|
else
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
|
2017-07-04 12:47:59 +00:00
|
|
|
std::string Hash::to_string(Base base, bool includeType) const
|
* Removed the `id' attribute hack.
* Formalise the notion of fixed-output derivations, i.e., derivations
for which a cryptographic hash of the output is known in advance.
Changes to such derivations should not propagate upwards through the
dependency graph. Previously this was done by specifying the hash
component of the output path through the `id' attribute, but this is
insecure since you can lie about it (i.e., you can specify any hash
and then produce a completely different output). Now the
responsibility for checking the output is moved from the builder to
Nix itself.
A fixed-output derivation can be created by specifying the
`outputHash' and `outputHashAlgo' attributes, the latter taking
values `md5', `sha1', and `sha256', and the former specifying the
actual hash in hexadecimal or in base-32 (auto-detected by looking
at the length of the attribute value). MD5 is included for
compatibility but should be considered deprecated.
* Removed the `drvPath' pseudo-attribute in derivation results. It's
no longer necessary.
* Cleaned up the support for multiple output paths in derivation store
expressions. Each output now has a unique identifier (e.g., `out',
`devel', `docs'). Previously there was no way to tell output paths
apart at the store expression level.
* `nix-hash' now has a flag `--base32' to specify that the hash should
be printed in base-32 notation.
* `fetchurl' accepts parameters `sha256' and `sha1' in addition to
`md5'.
* `nix-prefetch-url' now prints out a SHA-1 hash in base-32. (TODO: a
flag to specify the hash.)
2005-01-17 16:55:19 +00:00
|
|
|
{
|
2017-07-04 12:47:59 +00:00
|
|
|
std::string s;
|
2020-06-18 22:09:22 +00:00
|
|
|
if (base == SRI || includeType) {
|
2020-06-02 15:52:13 +00:00
|
|
|
s += printHashType(assertInitHashType(*this));
|
2020-06-18 22:09:22 +00:00
|
|
|
s += base == SRI ? '-' : ':';
|
* Removed the `id' attribute hack.
* Formalise the notion of fixed-output derivations, i.e., derivations
for which a cryptographic hash of the output is known in advance.
Changes to such derivations should not propagate upwards through the
dependency graph. Previously this was done by specifying the hash
component of the output path through the `id' attribute, but this is
insecure since you can lie about it (i.e., you can specify any hash
and then produce a completely different output). Now the
responsibility for checking the output is moved from the builder to
Nix itself.
A fixed-output derivation can be created by specifying the
`outputHash' and `outputHashAlgo' attributes, the latter taking
values `md5', `sha1', and `sha256', and the former specifying the
actual hash in hexadecimal or in base-32 (auto-detected by looking
at the length of the attribute value). MD5 is included for
compatibility but should be considered deprecated.
* Removed the `drvPath' pseudo-attribute in derivation results. It's
no longer necessary.
* Cleaned up the support for multiple output paths in derivation store
expressions. Each output now has a unique identifier (e.g., `out',
`devel', `docs'). Previously there was no way to tell output paths
apart at the store expression level.
* `nix-hash' now has a flag `--base32' to specify that the hash should
be printed in base-32 notation.
* `fetchurl' accepts parameters `sha256' and `sha1' in addition to
`md5'.
* `nix-prefetch-url' now prints out a SHA-1 hash in base-32. (TODO: a
flag to specify the hash.)
2005-01-17 16:55:19 +00:00
|
|
|
}
|
2017-07-04 12:47:59 +00:00
|
|
|
switch (base) {
|
2020-06-18 22:09:22 +00:00
|
|
|
case Base16:
|
2017-07-04 12:47:59 +00:00
|
|
|
s += printHash16(*this);
|
|
|
|
break;
|
2020-06-18 22:09:22 +00:00
|
|
|
case Base32:
|
2017-07-04 12:47:59 +00:00
|
|
|
s += printHash32(*this);
|
|
|
|
break;
|
2020-06-18 22:09:22 +00:00
|
|
|
case Base64:
|
|
|
|
case SRI:
|
2017-07-04 12:47:59 +00:00
|
|
|
s += base64Encode(std::string((const char *) hash, hashSize));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return s;
|
* Removed the `id' attribute hack.
* Formalise the notion of fixed-output derivations, i.e., derivations
for which a cryptographic hash of the output is known in advance.
Changes to such derivations should not propagate upwards through the
dependency graph. Previously this was done by specifying the hash
component of the output path through the `id' attribute, but this is
insecure since you can lie about it (i.e., you can specify any hash
and then produce a completely different output). Now the
responsibility for checking the output is moved from the builder to
Nix itself.
A fixed-output derivation can be created by specifying the
`outputHash' and `outputHashAlgo' attributes, the latter taking
values `md5', `sha1', and `sha256', and the former specifying the
actual hash in hexadecimal or in base-32 (auto-detected by looking
at the length of the attribute value). MD5 is included for
compatibility but should be considered deprecated.
* Removed the `drvPath' pseudo-attribute in derivation results. It's
no longer necessary.
* Cleaned up the support for multiple output paths in derivation store
expressions. Each output now has a unique identifier (e.g., `out',
`devel', `docs'). Previously there was no way to tell output paths
apart at the store expression level.
* `nix-hash' now has a flag `--base32' to specify that the hash should
be printed in base-32 notation.
* `fetchurl' accepts parameters `sha256' and `sha1' in addition to
`md5'.
* `nix-prefetch-url' now prints out a SHA-1 hash in base-32. (TODO: a
flag to specify the hash.)
2005-01-17 16:55:19 +00:00
|
|
|
}
|
|
|
|
|
2020-06-18 21:58:27 +00:00
|
|
|
Hash::Hash(std::string_view s, HashType type) : Hash(s, std::optional { type }) { }
|
|
|
|
Hash::Hash(std::string_view s) : Hash(s, std::optional<HashType>{}) { }
|
* Removed the `id' attribute hack.
* Formalise the notion of fixed-output derivations, i.e., derivations
for which a cryptographic hash of the output is known in advance.
Changes to such derivations should not propagate upwards through the
dependency graph. Previously this was done by specifying the hash
component of the output path through the `id' attribute, but this is
insecure since you can lie about it (i.e., you can specify any hash
and then produce a completely different output). Now the
responsibility for checking the output is moved from the builder to
Nix itself.
A fixed-output derivation can be created by specifying the
`outputHash' and `outputHashAlgo' attributes, the latter taking
values `md5', `sha1', and `sha256', and the former specifying the
actual hash in hexadecimal or in base-32 (auto-detected by looking
at the length of the attribute value). MD5 is included for
compatibility but should be considered deprecated.
* Removed the `drvPath' pseudo-attribute in derivation results. It's
no longer necessary.
* Cleaned up the support for multiple output paths in derivation store
expressions. Each output now has a unique identifier (e.g., `out',
`devel', `docs'). Previously there was no way to tell output paths
apart at the store expression level.
* `nix-hash' now has a flag `--base32' to specify that the hash should
be printed in base-32 notation.
* `fetchurl' accepts parameters `sha256' and `sha1' in addition to
`md5'.
* `nix-prefetch-url' now prints out a SHA-1 hash in base-32. (TODO: a
flag to specify the hash.)
2005-01-17 16:55:19 +00:00
|
|
|
|
2020-06-18 21:58:27 +00:00
|
|
|
Hash::Hash(std::string_view s, std::optional<HashType> type)
|
2017-07-04 12:47:59 +00:00
|
|
|
: type(type)
|
2011-12-02 11:47:06 +00:00
|
|
|
{
|
2017-07-04 12:47:59 +00:00
|
|
|
size_t pos = 0;
|
2018-12-13 13:30:52 +00:00
|
|
|
bool isSRI = false;
|
|
|
|
|
|
|
|
auto sep = s.find(':');
|
|
|
|
if (sep == string::npos) {
|
|
|
|
sep = s.find('-');
|
|
|
|
if (sep != string::npos) {
|
|
|
|
isSRI = true;
|
2020-06-02 15:52:13 +00:00
|
|
|
} else if (! type)
|
2017-07-30 11:27:57 +00:00
|
|
|
throw BadHash("hash '%s' does not include a type", s);
|
2018-12-13 13:30:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (sep != string::npos) {
|
|
|
|
string hts = string(s, 0, sep);
|
2017-07-04 12:47:59 +00:00
|
|
|
this->type = parseHashType(hts);
|
2020-06-02 15:52:13 +00:00
|
|
|
if (!this->type)
|
2017-07-30 11:27:57 +00:00
|
|
|
throw BadHash("unknown hash type '%s'", hts);
|
2020-06-02 15:52:13 +00:00
|
|
|
if (type && type != this->type)
|
|
|
|
throw BadHash("hash '%s' should have type '%s'", s, printHashType(*type));
|
2018-12-13 13:30:52 +00:00
|
|
|
pos = sep + 1;
|
2017-07-04 12:47:59 +00:00
|
|
|
}
|
2011-12-02 11:47:06 +00:00
|
|
|
|
2017-07-04 12:47:59 +00:00
|
|
|
init();
|
2011-12-02 11:47:06 +00:00
|
|
|
|
2017-07-04 12:47:59 +00:00
|
|
|
size_t size = s.size() - pos;
|
|
|
|
|
2018-12-13 13:30:52 +00:00
|
|
|
if (!isSRI && size == base16Len()) {
|
2017-07-04 12:47:59 +00:00
|
|
|
|
|
|
|
auto parseHexDigit = [&](char c) {
|
|
|
|
if (c >= '0' && c <= '9') return c - '0';
|
|
|
|
if (c >= 'A' && c <= 'F') return c - 'A' + 10;
|
|
|
|
if (c >= 'a' && c <= 'f') return c - 'a' + 10;
|
2017-07-30 11:27:57 +00:00
|
|
|
throw BadHash("invalid base-16 hash '%s'", s);
|
2017-07-04 12:47:59 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
for (unsigned int i = 0; i < hashSize; i++) {
|
|
|
|
hash[i] =
|
|
|
|
parseHexDigit(s[pos + i * 2]) << 4
|
|
|
|
| parseHexDigit(s[pos + i * 2 + 1]);
|
|
|
|
}
|
2003-06-15 13:41:32 +00:00
|
|
|
}
|
2017-07-04 12:47:59 +00:00
|
|
|
|
2018-12-13 13:30:52 +00:00
|
|
|
else if (!isSRI && size == base32Len()) {
|
2017-07-04 12:47:59 +00:00
|
|
|
|
|
|
|
for (unsigned int n = 0; n < size; ++n) {
|
|
|
|
char c = s[pos + size - n - 1];
|
|
|
|
unsigned char digit;
|
|
|
|
for (digit = 0; digit < base32Chars.size(); ++digit) /* !!! slow */
|
|
|
|
if (base32Chars[digit] == c) break;
|
|
|
|
if (digit >= 32)
|
2017-07-30 11:27:57 +00:00
|
|
|
throw BadHash("invalid base-32 hash '%s'", s);
|
2017-07-04 12:47:59 +00:00
|
|
|
unsigned int b = n * 5;
|
|
|
|
unsigned int i = b / 8;
|
|
|
|
unsigned int j = b % 8;
|
|
|
|
hash[i] |= digit << j;
|
|
|
|
|
|
|
|
if (i < hashSize - 1) {
|
|
|
|
hash[i + 1] |= digit >> (8 - j);
|
|
|
|
} else {
|
|
|
|
if (digit >> (8 - j))
|
2017-07-30 11:27:57 +00:00
|
|
|
throw BadHash("invalid base-32 hash '%s'", s);
|
2017-07-04 12:47:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-13 13:30:52 +00:00
|
|
|
else if (isSRI || size == base64Len()) {
|
2020-06-12 21:12:36 +00:00
|
|
|
auto d = base64Decode(s.substr(pos));
|
2018-02-19 16:44:30 +00:00
|
|
|
if (d.size() != hashSize)
|
2018-12-13 13:30:52 +00:00
|
|
|
throw BadHash("invalid %s hash '%s'", isSRI ? "SRI" : "base-64", s);
|
2018-03-15 03:53:43 +00:00
|
|
|
assert(hashSize);
|
2017-07-04 12:47:59 +00:00
|
|
|
memcpy(hash, d.data(), hashSize);
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
2020-06-02 15:52:13 +00:00
|
|
|
throw BadHash("hash '%s' has wrong length for hash type '%s'", s, printHashType(*type));
|
2003-06-15 13:41:32 +00:00
|
|
|
}
|
|
|
|
|
2020-06-18 21:58:27 +00:00
|
|
|
Hash newHashAllowEmpty(std::string hashStr, std::optional<HashType> ht)
|
2020-06-12 15:09:42 +00:00
|
|
|
{
|
2020-06-12 17:00:48 +00:00
|
|
|
if (hashStr.empty()) {
|
2020-06-18 21:58:27 +00:00
|
|
|
if (!ht)
|
|
|
|
throw BadHash("empty hash requires explicit hash type");
|
|
|
|
Hash h(*ht);
|
2020-06-18 21:38:15 +00:00
|
|
|
warn("found empty hash, assuming '%s'", h.to_string(Base::SRI, true));
|
2020-06-12 17:00:48 +00:00
|
|
|
return h;
|
2020-06-12 15:09:42 +00:00
|
|
|
} else
|
|
|
|
return Hash(hashStr, ht);
|
|
|
|
}
|
|
|
|
|
2003-06-15 13:41:32 +00:00
|
|
|
|
2006-02-13 18:00:08 +00:00
|
|
|
union Ctx
|
2003-06-16 13:33:38 +00:00
|
|
|
{
|
2006-02-13 19:52:43 +00:00
|
|
|
MD5_CTX md5;
|
|
|
|
SHA_CTX sha1;
|
2005-01-14 12:03:04 +00:00
|
|
|
SHA256_CTX sha256;
|
2015-11-04 15:31:06 +00:00
|
|
|
SHA512_CTX sha512;
|
2005-01-13 17:39:26 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static void start(HashType ht, Ctx & ctx)
|
|
|
|
{
|
2020-06-18 22:09:22 +00:00
|
|
|
if (ht == htMD5) MD5_Init(&ctx.md5);
|
|
|
|
else if (ht == htSHA1) SHA1_Init(&ctx.sha1);
|
|
|
|
else if (ht == htSHA256) SHA256_Init(&ctx.sha256);
|
|
|
|
else if (ht == htSHA512) SHA512_Init(&ctx.sha512);
|
2005-01-13 17:39:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void update(HashType ht, Ctx & ctx,
|
2017-04-28 13:10:29 +00:00
|
|
|
const unsigned char * bytes, size_t len)
|
2005-01-13 17:39:26 +00:00
|
|
|
{
|
2020-06-18 22:09:22 +00:00
|
|
|
if (ht == htMD5) MD5_Update(&ctx.md5, bytes, len);
|
|
|
|
else if (ht == htSHA1) SHA1_Update(&ctx.sha1, bytes, len);
|
|
|
|
else if (ht == htSHA256) SHA256_Update(&ctx.sha256, bytes, len);
|
|
|
|
else if (ht == htSHA512) SHA512_Update(&ctx.sha512, bytes, len);
|
2005-01-13 17:39:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void finish(HashType ht, Ctx & ctx, unsigned char * hash)
|
|
|
|
{
|
2020-06-18 22:09:22 +00:00
|
|
|
if (ht == htMD5) MD5_Final(hash, &ctx.md5);
|
|
|
|
else if (ht == htSHA1) SHA1_Final(hash, &ctx.sha1);
|
|
|
|
else if (ht == htSHA256) SHA256_Final(hash, &ctx.sha256);
|
|
|
|
else if (ht == htSHA512) SHA512_Final(hash, &ctx.sha512);
|
2005-01-13 17:39:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
* Removed the `id' attribute hack.
* Formalise the notion of fixed-output derivations, i.e., derivations
for which a cryptographic hash of the output is known in advance.
Changes to such derivations should not propagate upwards through the
dependency graph. Previously this was done by specifying the hash
component of the output path through the `id' attribute, but this is
insecure since you can lie about it (i.e., you can specify any hash
and then produce a completely different output). Now the
responsibility for checking the output is moved from the builder to
Nix itself.
A fixed-output derivation can be created by specifying the
`outputHash' and `outputHashAlgo' attributes, the latter taking
values `md5', `sha1', and `sha256', and the former specifying the
actual hash in hexadecimal or in base-32 (auto-detected by looking
at the length of the attribute value). MD5 is included for
compatibility but should be considered deprecated.
* Removed the `drvPath' pseudo-attribute in derivation results. It's
no longer necessary.
* Cleaned up the support for multiple output paths in derivation store
expressions. Each output now has a unique identifier (e.g., `out',
`devel', `docs'). Previously there was no way to tell output paths
apart at the store expression level.
* `nix-hash' now has a flag `--base32' to specify that the hash should
be printed in base-32 notation.
* `fetchurl' accepts parameters `sha256' and `sha1' in addition to
`md5'.
* `nix-prefetch-url' now prints out a SHA-1 hash in base-32. (TODO: a
flag to specify the hash.)
2005-01-17 16:55:19 +00:00
|
|
|
Hash hashString(HashType ht, const string & s)
|
2005-01-13 17:39:26 +00:00
|
|
|
{
|
|
|
|
Ctx ctx;
|
|
|
|
Hash hash(ht);
|
|
|
|
start(ht, ctx);
|
2012-02-09 17:27:45 +00:00
|
|
|
update(ht, ctx, (const unsigned char *) s.data(), s.length());
|
2005-01-13 17:39:26 +00:00
|
|
|
finish(ht, ctx, hash.hash);
|
2003-06-16 13:33:38 +00:00
|
|
|
return hash;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
* Removed the `id' attribute hack.
* Formalise the notion of fixed-output derivations, i.e., derivations
for which a cryptographic hash of the output is known in advance.
Changes to such derivations should not propagate upwards through the
dependency graph. Previously this was done by specifying the hash
component of the output path through the `id' attribute, but this is
insecure since you can lie about it (i.e., you can specify any hash
and then produce a completely different output). Now the
responsibility for checking the output is moved from the builder to
Nix itself.
A fixed-output derivation can be created by specifying the
`outputHash' and `outputHashAlgo' attributes, the latter taking
values `md5', `sha1', and `sha256', and the former specifying the
actual hash in hexadecimal or in base-32 (auto-detected by looking
at the length of the attribute value). MD5 is included for
compatibility but should be considered deprecated.
* Removed the `drvPath' pseudo-attribute in derivation results. It's
no longer necessary.
* Cleaned up the support for multiple output paths in derivation store
expressions. Each output now has a unique identifier (e.g., `out',
`devel', `docs'). Previously there was no way to tell output paths
apart at the store expression level.
* `nix-hash' now has a flag `--base32' to specify that the hash should
be printed in base-32 notation.
* `fetchurl' accepts parameters `sha256' and `sha1' in addition to
`md5'.
* `nix-prefetch-url' now prints out a SHA-1 hash in base-32. (TODO: a
flag to specify the hash.)
2005-01-17 16:55:19 +00:00
|
|
|
Hash hashFile(HashType ht, const Path & path)
|
2003-06-15 13:41:32 +00:00
|
|
|
{
|
2018-03-29 22:56:13 +00:00
|
|
|
HashSink sink(ht);
|
|
|
|
readFile(path, sink);
|
|
|
|
return sink.finish().first;
|
2003-06-15 13:41:32 +00:00
|
|
|
}
|
2003-06-16 15:59:23 +00:00
|
|
|
|
|
|
|
|
2007-02-21 14:31:42 +00:00
|
|
|
HashSink::HashSink(HashType ht) : ht(ht)
|
2003-06-16 15:59:23 +00:00
|
|
|
{
|
2007-02-21 14:31:42 +00:00
|
|
|
ctx = new Ctx;
|
2010-11-16 17:11:46 +00:00
|
|
|
bytes = 0;
|
2007-02-21 14:31:42 +00:00
|
|
|
start(ht, *ctx);
|
|
|
|
}
|
2015-02-03 17:35:11 +00:00
|
|
|
|
2007-02-21 14:31:42 +00:00
|
|
|
HashSink::~HashSink()
|
|
|
|
{
|
2011-12-15 16:19:53 +00:00
|
|
|
bufPos = 0;
|
2007-02-21 14:31:42 +00:00
|
|
|
delete ctx;
|
|
|
|
}
|
2003-06-16 15:59:23 +00:00
|
|
|
|
2011-12-15 16:19:53 +00:00
|
|
|
void HashSink::write(const unsigned char * data, size_t len)
|
2007-02-21 14:31:42 +00:00
|
|
|
{
|
2010-11-16 17:11:46 +00:00
|
|
|
bytes += len;
|
2007-02-21 14:31:42 +00:00
|
|
|
update(ht, *ctx, data, len);
|
|
|
|
}
|
2003-06-16 15:59:23 +00:00
|
|
|
|
2010-11-16 17:11:46 +00:00
|
|
|
HashResult HashSink::finish()
|
2003-06-16 15:59:23 +00:00
|
|
|
{
|
2011-12-15 16:19:53 +00:00
|
|
|
flush();
|
2005-01-13 17:39:26 +00:00
|
|
|
Hash hash(ht);
|
2007-02-21 14:31:42 +00:00
|
|
|
nix::finish(ht, *ctx, hash.hash);
|
2010-11-16 17:11:46 +00:00
|
|
|
return HashResult(hash, bytes);
|
2003-06-16 15:59:23 +00:00
|
|
|
}
|
2005-01-14 16:04:03 +00:00
|
|
|
|
2011-12-15 16:19:53 +00:00
|
|
|
HashResult HashSink::currentHash()
|
|
|
|
{
|
|
|
|
flush();
|
|
|
|
Ctx ctx2 = *ctx;
|
|
|
|
Hash hash(ht);
|
|
|
|
nix::finish(ht, ctx2, hash.hash);
|
|
|
|
return HashResult(hash, bytes);
|
|
|
|
}
|
|
|
|
|
2005-01-14 16:04:03 +00:00
|
|
|
|
2010-11-16 17:11:46 +00:00
|
|
|
HashResult hashPath(
|
|
|
|
HashType ht, const Path & path, PathFilter & filter)
|
2007-02-21 14:31:42 +00:00
|
|
|
{
|
|
|
|
HashSink sink(ht);
|
|
|
|
dumpPath(path, sink, filter);
|
|
|
|
return sink.finish();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-01-14 16:04:03 +00:00
|
|
|
Hash compressHash(const Hash & hash, unsigned int newSize)
|
|
|
|
{
|
|
|
|
Hash h;
|
|
|
|
h.hashSize = newSize;
|
|
|
|
for (unsigned int i = 0; i < hash.hashSize; ++i)
|
|
|
|
h.hash[i % newSize] ^= hash.hash[i];
|
|
|
|
return h;
|
|
|
|
}
|
* Removed the `id' attribute hack.
* Formalise the notion of fixed-output derivations, i.e., derivations
for which a cryptographic hash of the output is known in advance.
Changes to such derivations should not propagate upwards through the
dependency graph. Previously this was done by specifying the hash
component of the output path through the `id' attribute, but this is
insecure since you can lie about it (i.e., you can specify any hash
and then produce a completely different output). Now the
responsibility for checking the output is moved from the builder to
Nix itself.
A fixed-output derivation can be created by specifying the
`outputHash' and `outputHashAlgo' attributes, the latter taking
values `md5', `sha1', and `sha256', and the former specifying the
actual hash in hexadecimal or in base-32 (auto-detected by looking
at the length of the attribute value). MD5 is included for
compatibility but should be considered deprecated.
* Removed the `drvPath' pseudo-attribute in derivation results. It's
no longer necessary.
* Cleaned up the support for multiple output paths in derivation store
expressions. Each output now has a unique identifier (e.g., `out',
`devel', `docs'). Previously there was no way to tell output paths
apart at the store expression level.
* `nix-hash' now has a flag `--base32' to specify that the hash should
be printed in base-32 notation.
* `fetchurl' accepts parameters `sha256' and `sha1' in addition to
`md5'.
* `nix-prefetch-url' now prints out a SHA-1 hash in base-32. (TODO: a
flag to specify the hash.)
2005-01-17 16:55:19 +00:00
|
|
|
|
|
|
|
|
2020-06-02 15:52:13 +00:00
|
|
|
std::optional<HashType> parseHashTypeOpt(const string & s)
|
* Removed the `id' attribute hack.
* Formalise the notion of fixed-output derivations, i.e., derivations
for which a cryptographic hash of the output is known in advance.
Changes to such derivations should not propagate upwards through the
dependency graph. Previously this was done by specifying the hash
component of the output path through the `id' attribute, but this is
insecure since you can lie about it (i.e., you can specify any hash
and then produce a completely different output). Now the
responsibility for checking the output is moved from the builder to
Nix itself.
A fixed-output derivation can be created by specifying the
`outputHash' and `outputHashAlgo' attributes, the latter taking
values `md5', `sha1', and `sha256', and the former specifying the
actual hash in hexadecimal or in base-32 (auto-detected by looking
at the length of the attribute value). MD5 is included for
compatibility but should be considered deprecated.
* Removed the `drvPath' pseudo-attribute in derivation results. It's
no longer necessary.
* Cleaned up the support for multiple output paths in derivation store
expressions. Each output now has a unique identifier (e.g., `out',
`devel', `docs'). Previously there was no way to tell output paths
apart at the store expression level.
* `nix-hash' now has a flag `--base32' to specify that the hash should
be printed in base-32 notation.
* `fetchurl' accepts parameters `sha256' and `sha1' in addition to
`md5'.
* `nix-prefetch-url' now prints out a SHA-1 hash in base-32. (TODO: a
flag to specify the hash.)
2005-01-17 16:55:19 +00:00
|
|
|
{
|
2020-06-18 22:09:22 +00:00
|
|
|
if (s == "md5") return htMD5;
|
|
|
|
else if (s == "sha1") return htSHA1;
|
|
|
|
else if (s == "sha256") return htSHA256;
|
|
|
|
else if (s == "sha512") return htSHA512;
|
2020-06-02 15:52:13 +00:00
|
|
|
else return std::optional<HashType> {};
|
* Removed the `id' attribute hack.
* Formalise the notion of fixed-output derivations, i.e., derivations
for which a cryptographic hash of the output is known in advance.
Changes to such derivations should not propagate upwards through the
dependency graph. Previously this was done by specifying the hash
component of the output path through the `id' attribute, but this is
insecure since you can lie about it (i.e., you can specify any hash
and then produce a completely different output). Now the
responsibility for checking the output is moved from the builder to
Nix itself.
A fixed-output derivation can be created by specifying the
`outputHash' and `outputHashAlgo' attributes, the latter taking
values `md5', `sha1', and `sha256', and the former specifying the
actual hash in hexadecimal or in base-32 (auto-detected by looking
at the length of the attribute value). MD5 is included for
compatibility but should be considered deprecated.
* Removed the `drvPath' pseudo-attribute in derivation results. It's
no longer necessary.
* Cleaned up the support for multiple output paths in derivation store
expressions. Each output now has a unique identifier (e.g., `out',
`devel', `docs'). Previously there was no way to tell output paths
apart at the store expression level.
* `nix-hash' now has a flag `--base32' to specify that the hash should
be printed in base-32 notation.
* `fetchurl' accepts parameters `sha256' and `sha1' in addition to
`md5'.
* `nix-prefetch-url' now prints out a SHA-1 hash in base-32. (TODO: a
flag to specify the hash.)
2005-01-17 16:55:19 +00:00
|
|
|
}
|
2006-09-04 21:06:23 +00:00
|
|
|
|
2020-06-02 15:52:13 +00:00
|
|
|
HashType parseHashType(const string & s)
|
|
|
|
{
|
|
|
|
auto opt_h = parseHashTypeOpt(s);
|
|
|
|
if (opt_h)
|
|
|
|
return *opt_h;
|
|
|
|
else
|
|
|
|
throw UsageError("unknown hash algorithm '%1%'", s);
|
|
|
|
}
|
2015-02-03 17:35:11 +00:00
|
|
|
|
2008-12-03 16:10:17 +00:00
|
|
|
string printHashType(HashType ht)
|
|
|
|
{
|
2020-06-02 15:52:13 +00:00
|
|
|
switch (ht) {
|
2020-06-18 22:09:22 +00:00
|
|
|
case htMD5: return "md5"; break;
|
|
|
|
case htSHA1: return "sha1"; break;
|
|
|
|
case htSHA256: return "sha256"; break;
|
|
|
|
case htSHA512: return "sha512"; break;
|
2020-06-02 15:52:13 +00:00
|
|
|
}
|
2020-06-18 22:09:22 +00:00
|
|
|
// illegal hash type enum value internally, as opposed to external input
|
|
|
|
// which should be validated with nice error message.
|
|
|
|
abort();
|
2008-12-03 16:10:17 +00:00
|
|
|
}
|
|
|
|
|
2006-09-04 21:06:23 +00:00
|
|
|
}
|