about summary refs log tree commit diff
path: root/src/libutil
diff options
context:
space:
mode:
Diffstat (limited to 'src/libutil')
-rw-r--r--src/libutil/hash.cc64
-rw-r--r--src/libutil/hash.hh9
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 */