diff options
Diffstat (limited to 'src/libutil')
-rw-r--r-- | src/libutil/hash.cc | 64 | ||||
-rw-r--r-- | src/libutil/hash.hh | 9 |
2 files changed, 67 insertions, 6 deletions
diff --git a/src/libutil/hash.cc b/src/libutil/hash.cc index 324e2bf7f4c2..5c93c41dc613 100644 --- a/src/libutil/hash.cc +++ b/src/libutil/hash.cc @@ -132,6 +132,55 @@ string printHash32(const Hash & hash) } +static bool mul(uint16_t * words, unsigned short y, int maxSize) +{ + unsigned short carry = 0; + + for (int pos = 0; pos < maxSize; ++pos) { + unsigned int m = words[pos] * y + carry; + words[pos] = m & 0xffff; + carry = m >> 16; + } + + return carry; +} + + +static bool add(uint16_t * words, unsigned short y, int maxSize) +{ + unsigned short carry = y; + + for (int pos = 0; pos < maxSize; ++pos) { + unsigned int m = words[pos] + carry; + words[pos] = m & 0xffff; + carry = m >> 16; + if (carry == 0) break; + } + + return carry; +} + + +Hash parseHash32(HashType ht, const string & s) +{ + Hash hash(ht); + + for (unsigned int i = 0; i < s.length(); ++i) { + char c = s[i]; + unsigned char digit; + for (digit = 0; digit < sizeof(chars); ++digit) /* !!! slow */ + if (chars[digit] == c) break; + if (digit >= 32) + throw Error(format("invalid base-32 hash `%1%'") % s); + if (mul((uint16_t *) hash.hash, 32, hash.hashSize / 2) || + add((uint16_t *) hash.hash, digit, hash.hashSize / 2)) + throw Error(format("base-32 hash `%1%' is too large") % s); + } + + return hash; +} + + bool isHash(const string & s) { if (s.length() != 32) return false; @@ -181,7 +230,7 @@ static void finish(HashType ht, Ctx & ctx, unsigned char * hash) } -Hash hashString(const string & s, HashType ht) +Hash hashString(HashType ht, const string & s) { Ctx ctx; Hash hash(ht); @@ -192,7 +241,7 @@ Hash hashString(const string & s, HashType ht) } -Hash hashFile(const Path & path, HashType ht) +Hash hashFile(HashType ht, const Path & path) { Ctx ctx; Hash hash(ht); @@ -226,7 +275,7 @@ struct HashSink : DumpSink }; -Hash hashPath(const Path & path, HashType ht) +Hash hashPath(HashType ht, const Path & path) { HashSink sink; sink.ht = ht; @@ -246,3 +295,12 @@ Hash compressHash(const Hash & hash, unsigned int newSize) 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 return htUnknown; +} diff --git a/src/libutil/hash.hh b/src/libutil/hash.hh index 0c9d7b9cb936..398b17421644 100644 --- a/src/libutil/hash.hh +++ b/src/libutil/hash.hh @@ -58,18 +58,21 @@ Hash parseHash32(HashType ht, const string & s); bool isHash(const string & s); /* Compute the hash of the given string. */ -Hash hashString(const string & s, HashType ht); +Hash hashString(HashType ht, const string & s); /* Compute the hash of the given file. */ -Hash hashFile(const Path & path, HashType ht); +Hash hashFile(HashType ht, const Path & path); /* Compute the hash of the given path. The hash is defined as md5(dump(path)). */ -Hash hashPath(const Path & path, HashType ht); +Hash hashPath(HashType ht, const Path & path); /* Compress a hash to the specified number of bytes by cyclically XORing bytes together. */ Hash compressHash(const Hash & hash, unsigned int newSize); +/* Parse a string representing a hash type. */ +HashType parseHashType(const string & s); + #endif /* !__HASH_H */ |