diff options
Diffstat (limited to 'third_party/nix/src/libutil/hash.cc')
-rw-r--r-- | third_party/nix/src/libutil/hash.cc | 536 |
1 files changed, 252 insertions, 284 deletions
diff --git a/third_party/nix/src/libutil/hash.cc b/third_party/nix/src/libutil/hash.cc index 1c14ebb187cc..647822213278 100644 --- a/third_party/nix/src/libutil/hash.cc +++ b/third_party/nix/src/libutil/hash.cc @@ -1,355 +1,323 @@ -#include <iostream> -#include <cstring> - +#include "hash.hh" +#include <fcntl.h> #include <openssl/md5.h> #include <openssl/sha.h> - -#include "hash.hh" +#include <sys/stat.h> +#include <sys/types.h> +#include <cstring> +#include <iostream> #include "archive.hh" -#include "util.hh" #include "istringstream_nocopy.hh" - -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> +#include "util.hh" namespace nix { - -void Hash::init() -{ - if (type == htMD5) hashSize = md5HashSize; - else if (type == htSHA1) hashSize = sha1HashSize; - else if (type == htSHA256) hashSize = sha256HashSize; - else if (type == htSHA512) hashSize = sha512HashSize; - else abort(); - assert(hashSize <= maxHashSize); - memset(hash, 0, maxHashSize); -} - - -bool Hash::operator == (const Hash & h2) const -{ - if (hashSize != h2.hashSize) return false; - for (unsigned int i = 0; i < hashSize; i++) - if (hash[i] != h2.hash[i]) return false; - return true; +void Hash::init() { + if (type == htMD5) + hashSize = md5HashSize; + else if (type == htSHA1) + hashSize = sha1HashSize; + else if (type == htSHA256) + hashSize = sha256HashSize; + else if (type == htSHA512) + hashSize = sha512HashSize; + else + abort(); + assert(hashSize <= maxHashSize); + memset(hash, 0, maxHashSize); } - -bool Hash::operator != (const Hash & h2) const -{ - return !(*this == h2); +bool Hash::operator==(const Hash& h2) const { + if (hashSize != h2.hashSize) return false; + for (unsigned int i = 0; i < hashSize; i++) + if (hash[i] != h2.hash[i]) return false; + return true; } +bool Hash::operator!=(const Hash& h2) const { return !(*this == h2); } -bool Hash::operator < (const Hash & h) const -{ - if (hashSize < h.hashSize) return true; - if (hashSize > h.hashSize) return false; - 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; +bool Hash::operator<(const Hash& h) const { + if (hashSize < h.hashSize) return true; + if (hashSize > h.hashSize) return false; + 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; } - const string base16Chars = "0123456789abcdef"; - -static string printHash16(const Hash & hash) -{ - char buf[hash.hashSize * 2]; - for (unsigned int i = 0; i < hash.hashSize; i++) { - buf[i * 2] = base16Chars[hash.hash[i] >> 4]; - buf[i * 2 + 1] = base16Chars[hash.hash[i] & 0x0f]; - } - return string(buf, hash.hashSize * 2); +static string printHash16(const Hash& hash) { + char buf[hash.hashSize * 2]; + for (unsigned int i = 0; i < hash.hashSize; i++) { + buf[i * 2] = base16Chars[hash.hash[i] >> 4]; + buf[i * 2 + 1] = base16Chars[hash.hash[i] & 0x0f]; + } + return string(buf, hash.hashSize * 2); } - // omitted: E O U T const string base32Chars = "0123456789abcdfghijklmnpqrsvwxyz"; - -static string printHash32(const Hash & hash) -{ - assert(hash.hashSize); - size_t len = hash.base32Len(); - assert(len); - - string s; - s.reserve(len); - - for (int n = (int) len - 1; n >= 0; n--) { - 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]); - } - - return s; +static string printHash32(const Hash& hash) { + assert(hash.hashSize); + size_t len = hash.base32Len(); + assert(len); + + string s; + s.reserve(len); + + for (int n = (int)len - 1; n >= 0; n--) { + 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]); + } + + return s; } - -string printHash16or32(const Hash & hash) -{ - return hash.to_string(hash.type == htMD5 ? Base16 : Base32, false); +string printHash16or32(const Hash& hash) { + return hash.to_string(hash.type == htMD5 ? Base16 : Base32, false); } - -std::string Hash::to_string(Base base, bool includeType) const -{ - std::string s; - if (base == SRI || includeType) { - s += printHashType(type); - s += base == SRI ? '-' : ':'; - } - switch (base) { +std::string Hash::to_string(Base base, bool includeType) const { + std::string s; + if (base == SRI || includeType) { + s += printHashType(type); + s += base == SRI ? '-' : ':'; + } + switch (base) { case Base16: - s += printHash16(*this); - break; + s += printHash16(*this); + break; case Base32: - s += printHash32(*this); - break; + s += printHash32(*this); + break; case Base64: case SRI: - s += base64Encode(std::string((const char *) hash, hashSize)); - break; - } - return s; + s += base64Encode(std::string((const char*)hash, hashSize)); + break; + } + return s; } +Hash::Hash(const std::string& s, HashType type) : type(type) { + size_t pos = 0; + bool isSRI = false; -Hash::Hash(const std::string & s, HashType type) - : type(type) -{ - size_t pos = 0; - 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); - } - + auto sep = s.find(':'); + if (sep == string::npos) { + sep = s.find('-'); 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 = sep + 1; - } - - init(); - - size_t size = s.size() - pos; - - if (!isSRI && size == base16Len()) { + isSRI = true; + } else if (type == htUnknown) + throw BadHash("hash '%s' does not include a type", s); + } + + 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 = sep + 1; + } + + init(); + + size_t size = s.size() - pos; + + if (!isSRI && size == base16Len()) { + 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; + throw BadHash("invalid base-16 hash '%s'", s); + }; - 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; - throw BadHash("invalid base-16 hash '%s'", s); - }; - - for (unsigned int i = 0; i < hashSize; i++) { - hash[i] = - parseHexDigit(s[pos + i * 2]) << 4 - | parseHexDigit(s[pos + i * 2 + 1]); - } - } - - else if (!isSRI && size == base32Len()) { - - 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) - throw BadHash("invalid base-32 hash '%s'", s); - 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)) - throw BadHash("invalid base-32 hash '%s'", s); - } - } + for (unsigned int i = 0; i < hashSize; i++) { + hash[i] = parseHexDigit(s[pos + i * 2]) << 4 | + parseHexDigit(s[pos + i * 2 + 1]); } - - else if (isSRI || size == base64Len()) { - auto d = base64Decode(std::string(s, pos)); - if (d.size() != hashSize) - throw BadHash("invalid %s hash '%s'", isSRI ? "SRI" : "base-64", s); - assert(hashSize); - memcpy(hash, d.data(), hashSize); + } + + else if (!isSRI && size == base32Len()) { + 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) throw BadHash("invalid base-32 hash '%s'", s); + 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)) throw BadHash("invalid base-32 hash '%s'", s); + } } - - else - throw BadHash("hash '%s' has wrong length for hash type '%s'", s, printHashType(type)); + } + + else if (isSRI || size == base64Len()) { + auto d = base64Decode(std::string(s, pos)); + if (d.size() != hashSize) + throw BadHash("invalid %s hash '%s'", isSRI ? "SRI" : "base-64", s); + assert(hashSize); + memcpy(hash, d.data(), hashSize); + } + + else + throw BadHash("hash '%s' has wrong length for hash type '%s'", s, + printHashType(type)); } - -union Ctx -{ - MD5_CTX md5; - SHA_CTX sha1; - SHA256_CTX sha256; - SHA512_CTX sha512; +union Ctx { + MD5_CTX md5; + SHA_CTX sha1; + SHA256_CTX sha256; + SHA512_CTX sha512; }; - -static void start(HashType ht, Ctx & ctx) -{ - 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); +static void start(HashType ht, Ctx& ctx) { + 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); } - -static void update(HashType ht, Ctx & ctx, - const unsigned char * bytes, size_t len) -{ - 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); +static void update(HashType ht, Ctx& ctx, const unsigned char* bytes, + size_t len) { + 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); } - -static void finish(HashType ht, Ctx & ctx, unsigned char * hash) -{ - 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); +static void finish(HashType ht, Ctx& ctx, unsigned char* hash) { + 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); } - -Hash hashString(HashType ht, const string & s) -{ - Ctx ctx; - Hash hash(ht); - start(ht, ctx); - update(ht, ctx, (const unsigned char *) s.data(), s.length()); - finish(ht, ctx, hash.hash); - return hash; +Hash hashString(HashType ht, const string& s) { + Ctx ctx; + Hash hash(ht); + start(ht, ctx); + update(ht, ctx, (const unsigned char*)s.data(), s.length()); + finish(ht, ctx, hash.hash); + return hash; } +Hash hashFile(HashType ht, const Path& path) { + Ctx ctx; + Hash hash(ht); + start(ht, ctx); -Hash hashFile(HashType ht, const Path & path) -{ - Ctx ctx; - Hash hash(ht); - start(ht, ctx); - - AutoCloseFD fd = open(path.c_str(), O_RDONLY | O_CLOEXEC); - if (!fd) throw SysError(format("opening file '%1%'") % path); + AutoCloseFD fd = open(path.c_str(), O_RDONLY | O_CLOEXEC); + if (!fd) throw SysError(format("opening file '%1%'") % path); - std::vector<unsigned char> buf(8192); - ssize_t n; - while ((n = read(fd.get(), buf.data(), buf.size()))) { - checkInterrupt(); - if (n == -1) throw SysError(format("reading file '%1%'") % path); - update(ht, ctx, buf.data(), n); - } + std::vector<unsigned char> buf(8192); + ssize_t n; + while ((n = read(fd.get(), buf.data(), buf.size()))) { + checkInterrupt(); + if (n == -1) throw SysError(format("reading file '%1%'") % path); + update(ht, ctx, buf.data(), n); + } - finish(ht, ctx, hash.hash); - return hash; + finish(ht, ctx, hash.hash); + return hash; } - -HashSink::HashSink(HashType ht) : ht(ht) -{ - ctx = new Ctx; - bytes = 0; - start(ht, *ctx); +HashSink::HashSink(HashType ht) : ht(ht) { + ctx = new Ctx; + bytes = 0; + start(ht, *ctx); } -HashSink::~HashSink() -{ - bufPos = 0; - delete ctx; +HashSink::~HashSink() { + bufPos = 0; + delete ctx; } -void HashSink::write(const unsigned char * data, size_t len) -{ - bytes += len; - update(ht, *ctx, data, len); +void HashSink::write(const unsigned char* data, size_t len) { + bytes += len; + update(ht, *ctx, data, len); } -HashResult HashSink::finish() -{ - flush(); - Hash hash(ht); - nix::finish(ht, *ctx, hash.hash); - return HashResult(hash, bytes); +HashResult HashSink::finish() { + flush(); + Hash hash(ht); + nix::finish(ht, *ctx, hash.hash); + return HashResult(hash, bytes); } -HashResult HashSink::currentHash() -{ - flush(); - Ctx ctx2 = *ctx; - Hash hash(ht); - nix::finish(ht, ctx2, hash.hash); - return HashResult(hash, bytes); +HashResult HashSink::currentHash() { + flush(); + Ctx ctx2 = *ctx; + Hash hash(ht); + nix::finish(ht, ctx2, hash.hash); + return HashResult(hash, bytes); } - -HashResult hashPath( - HashType ht, const Path & path, PathFilter & filter) -{ - HashSink sink(ht); - dumpPath(path, sink, filter); - return sink.finish(); +HashResult hashPath(HashType ht, const Path& path, PathFilter& filter) { + HashSink sink(ht); + dumpPath(path, sink, filter); + return sink.finish(); } - -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; +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; } - -HashType parseHashType(const string & s) -{ - if (s == "md5") return htMD5; - else if (s == "sha1") return htSHA1; - else if (s == "sha256") return htSHA256; - else if (s == "sha512") return htSHA512; - else return htUnknown; +HashType parseHashType(const string& s) { + if (s == "md5") + return htMD5; + else if (s == "sha1") + return htSHA1; + else if (s == "sha256") + return htSHA256; + else if (s == "sha512") + return htSHA512; + else + return htUnknown; } - -string printHashType(HashType ht) -{ - if (ht == htMD5) return "md5"; - else if (ht == htSHA1) return "sha1"; - else if (ht == htSHA256) return "sha256"; - else if (ht == htSHA512) return "sha512"; - else abort(); +string printHashType(HashType ht) { + if (ht == htMD5) + return "md5"; + else if (ht == htSHA1) + return "sha1"; + else if (ht == htSHA256) + return "sha256"; + else if (ht == htSHA512) + return "sha512"; + else + abort(); } - -} +} // namespace nix |