From f1fbd4feae1fb5d7db78a8f4545934a45dbcfc55 Mon Sep 17 00:00:00 2001
From: Zooko O'Whielacronx <zooko@zooko.com>
Date: Sun, 21 Dec 2008 17:35:18 -0700
Subject: [PATCH] dirnode: don't check MAC on entries in dirnodes In an ancient
 version of directories, we needed a MAC on each entry.  In modern times, the
 entire dirnode comes with a digital signature, so the MAC on each entry is
 redundant. With this patch, we no longer check those MACs when reading
 directories, but we still produce them so that older readers will accept
 directories that we write.

---
 src/allmydata/dirnode.py           |  4 +---
 src/allmydata/test/test_dirnode.py | 12 ++++++------
 src/allmydata/util/hashutil.py     |  3 ---
 3 files changed, 7 insertions(+), 12 deletions(-)

diff --git a/src/allmydata/dirnode.py b/src/allmydata/dirnode.py
index 1afa6655..9f2e1d25 100644
--- a/src/allmydata/dirnode.py
+++ b/src/allmydata/dirnode.py
@@ -152,14 +152,12 @@ class NewDirectoryNode:
         mac = hashutil.hmac(key, IV + crypttext)
         assert len(mac) == 32
         return IV + crypttext + mac
+        # The MAC is not checked by readers in Tahoe >= 1.3.0, but we still produce it for the sake of older readers.
 
     def _decrypt_rwcapdata(self, encwrcap):
         IV = encwrcap[:16]
         crypttext = encwrcap[16:-32]
-        mac = encwrcap[-32:]
         key = hashutil.mutable_rwcap_key_hash(IV, self._node.get_writekey())
-        if mac != hashutil.hmac(key, IV+crypttext):
-            raise hashutil.IntegrityCheckError("HMAC does not match, crypttext is corrupted")
         cryptor = AES(key)
         plaintext = cryptor.process(crypttext)
         return plaintext
diff --git a/src/allmydata/test/test_dirnode.py b/src/allmydata/test/test_dirnode.py
index e2a4591a..916c9eaa 100644
--- a/src/allmydata/test/test_dirnode.py
+++ b/src/allmydata/test/test_dirnode.py
@@ -119,17 +119,17 @@ class Dirnode(unittest.TestCase,
                 filenode = dn._node
                 si = IURI(filenode.get_uri()).storage_index
                 old_contents = filenode.all_contents[si]
-                # we happen to know that the writecap is encrypted near the
-                # end of the string. Flip one of its bits and make sure we
-                # detect the corruption.
+                # We happen to know that the writecap MAC is near the end of the string. Flip
+                # one of its bits and make sure we ignore the corruption.
                 new_contents = testutil.flip_bit(old_contents, -10)
                 # TODO: also test flipping bits in the other portions
                 filenode.all_contents[si] = new_contents
             d.addCallback(_corrupt)
             def _check2(res):
-                self.shouldFail(hashutil.IntegrityCheckError, "corrupt",
-                                "HMAC does not match, crypttext is corrupted",
-                                dn.list)
+                d = dn.list()
+                def _c3(res):
+                    self.failUnless(res.has_key('child'))
+                d.addCallback(_c3)
             d.addCallback(_check2)
             return d
         d.addCallback(_created)
diff --git a/src/allmydata/util/hashutil.py b/src/allmydata/util/hashutil.py
index 750543c7..0161e676 100644
--- a/src/allmydata/util/hashutil.py
+++ b/src/allmydata/util/hashutil.py
@@ -13,9 +13,6 @@ from allmydata.util.netstring import netstring
 # kinds.
 CRYPTO_VAL_SIZE=32
 
-class IntegrityCheckError(Exception):
-    pass
-
 class _SHA256d_Hasher:
     # use SHA-256d, as defined by Ferguson and Schneier: hash the output
     # again to prevent length-extension attacks
-- 
2.45.2