]> git.rkrishnan.org Git - tahoe-lafs/tahoe-lafs.git/commitdiff
hashutil: add tagged_hash_256d and tagged_hasher_256d
authorBrian Warner <warner@allmydata.com>
Thu, 7 Feb 2008 02:36:43 +0000 (19:36 -0700)
committerBrian Warner <warner@allmydata.com>
Thu, 7 Feb 2008 02:36:43 +0000 (19:36 -0700)
src/allmydata/test/test_util.py
src/allmydata/util/hashutil.py

index 116fcbcc7d73e3f28fc2187e5b9dc9319b017c57..21ed725352f451703885c805c6d78ca495463a1c 100644 (file)
@@ -6,7 +6,7 @@ from twisted.trial import unittest
 from twisted.internet import defer
 from twisted.python import failure
 
-from allmydata.util import bencode, idlib, humanreadable, mathutil
+from allmydata.util import bencode, idlib, humanreadable, mathutil, hashutil
 from allmydata.util import assertutil, fileutil, testutil, deferredutil
 
 
@@ -427,3 +427,19 @@ class DeferredUtilTests(unittest.TestCase):
         self.failUnless(isinstance(f, failure.Failure))
         self.failUnless(f.check(RuntimeError))
 
+class HashUtilTests(unittest.TestCase):
+    def test_sha256d(self):
+        h1 = hashutil.tagged_hash_256d("tag1", "value")
+        h2 = hashutil.tagged_hasher_256d("tag1")
+        h2.update("value")
+        h2 = h2.digest()
+        self.failUnlessEqual(h1, h2)
+
+    def test_sha256d_truncated(self):
+        h1 = hashutil.tagged_hash_256d("tag1", "value", 16)
+        h2 = hashutil.tagged_hasher_256d("tag1", 16)
+        h2.update("value")
+        h2 = h2.digest()
+        self.failUnlessEqual(len(h1), 16)
+        self.failUnlessEqual(len(h2), 16)
+        self.failUnlessEqual(h1, h2)
index 1dfcb2a41d0cd93798bb575ae127ce0555b4cad0..8a8dc4c619e8dd65c74cb391336c303641bbfaa7 100644 (file)
@@ -20,6 +20,37 @@ def tagged_hash(tag, val):
     s.update(val)
     return s.digest()
 
+def tagged_hash_256d(tag, val, truncate_to=None):
+    # use SHA-256d, as defined by Ferguson and Schneier: hash the output
+    # again to prevent length-extension attacks
+    s = SHA256()
+    s.update(netstring(tag))
+    s.update(val)
+    h = s.digest()
+    h2 = SHA256(h).digest()
+    if truncate_to:
+        h2 = h2[:truncate_to]
+    return h2
+
+class SHA256d_Hasher:
+    def __init__(self, truncate_to=None):
+        self.h = SHA256()
+        self.truncate_to = truncate_to
+    def update(self, data):
+        self.h.update(data)
+    def digest(self):
+        h1 = self.h.digest()
+        del self.h
+        h2 = SHA256(h1).digest()
+        if self.truncate_to:
+            h2 = h2[:self.truncate_to]
+        return h2
+
+def tagged_hasher_256d(tag, truncate_to=None):
+    hasher = SHA256d_Hasher(truncate_to)
+    hasher.update(netstring(tag))
+    return hasher
+
 def tagged_pair_hash(tag, val1, val2):
     s = SHA256()
     s.update(netstring(tag))