From: Brian Warner Date: Thu, 7 Feb 2008 02:36:43 +0000 (-0700) Subject: hashutil: add tagged_hash_256d and tagged_hasher_256d X-Git-Tag: allmydata-tahoe-0.8.0~115 X-Git-Url: https://git.rkrishnan.org/%3C?a=commitdiff_plain;h=9f9a45824910633b91bd7adc9a138d76558e392d;p=tahoe-lafs%2Ftahoe-lafs.git hashutil: add tagged_hash_256d and tagged_hasher_256d --- diff --git a/src/allmydata/test/test_util.py b/src/allmydata/test/test_util.py index 116fcbcc..21ed7253 100644 --- a/src/allmydata/test/test_util.py +++ b/src/allmydata/test/test_util.py @@ -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) diff --git a/src/allmydata/util/hashutil.py b/src/allmydata/util/hashutil.py index 1dfcb2a4..8a8dc4c6 100644 --- a/src/allmydata/util/hashutil.py +++ b/src/allmydata/util/hashutil.py @@ -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))