From: Brian Warner Date: Fri, 15 Feb 2008 02:58:01 +0000 (-0700) Subject: BIG COMPATIBILITY BREAK: update hash tags, switch to SHA-256d everywhere X-Git-Tag: allmydata-tahoe-0.8.0~44 X-Git-Url: https://git.rkrishnan.org/pf/COPYING.TGPPL.html?a=commitdiff_plain;h=72874390fe598683904d77e311578efaf2c16318;p=tahoe-lafs%2Ftahoe-lafs.git BIG COMPATIBILITY BREAK: update hash tags, switch to SHA-256d everywhere --- diff --git a/src/allmydata/test/test_cli.py b/src/allmydata/test/test_cli.py index fe1dad44..0868d5a4 100644 --- a/src/allmydata/test/test_cli.py +++ b/src/allmydata/test/test_cli.py @@ -88,38 +88,38 @@ class CLI(unittest.TestCase): total_shares=total_shares, size=size) output = self._dump_cap(u.to_string()) - self.failUnless("CHK File:" in output) + self.failUnless("CHK File:" in output, output) self.failUnless("key: aaaqeayeaudaocajbifqydiob4" in output, output) - self.failUnless("UEB hash: 4d5euev6djvynq6vrg34mpy5xi3vl5x7oumdthqky6ovcy4wbvtq" in output, output) - self.failUnless("size: 1234" in output) - self.failUnless("k/N: 25/100" in output) - self.failUnless("storage index: kmkbjguwmkxej3wejdcvu74zki" in output, output) + self.failUnless("UEB hash: nf3nimquen7aeqm36ekgxomalstenpkvsdmf6fplj7swdatbv5oa" in output, output) + self.failUnless("size: 1234" in output, output) + self.failUnless("k/N: 25/100" in output, output) + self.failUnless("storage index: hdis5iaveku6lnlaiccydyid7q" in output, output) output = self._dump_cap("--client-secret", "5s33nk3qpvnj2fw3z4mnm2y6fa", u.to_string()) - self.failUnless("client renewal secret: jltcy6cppghq6ha3uzcawqr2lvwpzmw4teeqj2if6jd2vfpit6hq" in output, output) + self.failUnless("client renewal secret: znxmki5zdibb5qlt46xbdvk2t55j7hibejq3i5ijyurkr6m6jkhq" in output, output) output = self._dump_cap(u.get_verifier().to_string()) - self.failIf("key: " in output) - self.failUnless("UEB hash: 4d5euev6djvynq6vrg34mpy5xi3vl5x7oumdthqky6ovcy4wbvtq" in output, output) - self.failUnless("size: 1234" in output) - self.failUnless("k/N: 25/100" in output) - self.failUnless("storage index: kmkbjguwmkxej3wejdcvu74zki" in output, output) + self.failIf("key: " in output, output) + self.failUnless("UEB hash: nf3nimquen7aeqm36ekgxomalstenpkvsdmf6fplj7swdatbv5oa" in output, output) + self.failUnless("size: 1234" in output, output) + self.failUnless("k/N: 25/100" in output, output) + self.failUnless("storage index: hdis5iaveku6lnlaiccydyid7q" in output, output) prefixed_u = "http://127.0.0.1/uri/%s" % urllib.quote(u.to_string()) output = self._dump_cap(prefixed_u) - self.failUnless("CHK File:" in output) + self.failUnless("CHK File:" in output, output) self.failUnless("key: aaaqeayeaudaocajbifqydiob4" in output, output) - self.failUnless("UEB hash: 4d5euev6djvynq6vrg34mpy5xi3vl5x7oumdthqky6ovcy4wbvtq" in output, output) - self.failUnless("size: 1234" in output) - self.failUnless("k/N: 25/100" in output) - self.failUnless("storage index: kmkbjguwmkxej3wejdcvu74zki" in output, output) + self.failUnless("UEB hash: nf3nimquen7aeqm36ekgxomalstenpkvsdmf6fplj7swdatbv5oa" in output, output) + self.failUnless("size: 1234" in output, output) + self.failUnless("k/N: 25/100" in output, output) + self.failUnless("storage index: hdis5iaveku6lnlaiccydyid7q" in output, output) def test_dump_cap_lit(self): u = uri.LiteralFileURI("this is some data") output = self._dump_cap(u.to_string()) - self.failUnless("Literal File URI:" in output) - self.failUnless("data: this is some data" in output) + self.failUnless("Literal File URI:" in output, output) + self.failUnless("data: this is some data" in output, output) def test_dump_cap_ssk(self): writekey = "\x01" * 16 @@ -127,52 +127,52 @@ class CLI(unittest.TestCase): u = uri.WriteableSSKFileURI(writekey, fingerprint) output = self._dump_cap(u.to_string()) - self.failUnless("SSK Writeable URI:" in output) + self.failUnless("SSK Writeable URI:" in output, output) self.failUnless("writekey: aeaqcaibaeaqcaibaeaqcaibae" in output, output) - self.failUnless("readkey: x4gowaektauqze4y2sbsd5peye" in output, output) - self.failUnless("storage index: rqx7xnpexjxuqprto6pezagdxi" in output, output) + self.failUnless("readkey: nvgh5vj2ekzzkim5fgtb4gey5y" in output, output) + self.failUnless("storage index: nt4fwemuw7flestsezvo2eveke" in output, output) self.failUnless("fingerprint: 737p57x6737p57x6737p57x6737p57x6737p57x6737p57x6737a" in output, output) - output = self._dump_cap("--client-secret", "tylkpgr364eav3ipsnq57yyafu", + output = self._dump_cap("--client-secret", "5s33nk3qpvnj2fw3z4mnm2y6fa", u.to_string()) - self.failUnless("file renewal secret: cs54qwurfjmeduruapo46kqwexpcvav5oemczblonglj6xmoyvkq" in output, output) + self.failUnless("file renewal secret: arpszxzc2t6kb4okkg7sp765xgkni5z7caavj7lta73vmtymjlxq" in output, output) fileutil.make_dirs("cli/test_dump_cap/private") f = open("cli/test_dump_cap/private/secret", "w") - f.write("y6c7q34mjbt5kkf6hb3utuoj7u\n") + f.write("5s33nk3qpvnj2fw3z4mnm2y6fa\n") f.close() output = self._dump_cap("--client-dir", "cli/test_dump_cap", u.to_string()) - self.failUnless("file renewal secret: 4jkip4ie2zgmbhcni6g4vmsivwuakpbw7hwnmdancsc6fkrv27kq" in output, output) + self.failUnless("file renewal secret: arpszxzc2t6kb4okkg7sp765xgkni5z7caavj7lta73vmtymjlxq" in output, output) output = self._dump_cap("--client-dir", "cli/test_dump_cap_BOGUS", u.to_string()) - self.failIf("file renewal secret:" in output) + self.failIf("file renewal secret:" in output, output) output = self._dump_cap("--nodeid", "tqc35esocrvejvg4mablt6aowg6tl43j", u.to_string()) - self.failUnless("write_enabler: eok7o6u26dvl3abw4ok7kqrka4omdolnsx627hpcvtx3kkjwsu5q" in output, output) - self.failIf("file renewal secret:" in output) + self.failUnless("write_enabler: mgcavriox2wlb5eer26unwy5cw56elh3sjweffckkmivvsxtaknq" in output, output) + self.failIf("file renewal secret:" in output, output) output = self._dump_cap("--nodeid", "tqc35esocrvejvg4mablt6aowg6tl43j", - "--client-secret", "6orzlv22ggdhphjpmsixcbwufq", + "--client-secret", "5s33nk3qpvnj2fw3z4mnm2y6fa", u.to_string()) - self.failUnless("write_enabler: eok7o6u26dvl3abw4ok7kqrka4omdolnsx627hpcvtx3kkjwsu5q" in output, output) - self.failUnless("file renewal secret: aabhsp6kfsxb57jzdan4dnyzcd3m2prx34jd4z5nj5t5a7guf5fq" in output, output) - self.failUnless("lease renewal secret: bajcslergse474ga775msalmxxapgwr27lngeja4u7ef5j7yh4bq" in output, output) + self.failUnless("write_enabler: mgcavriox2wlb5eer26unwy5cw56elh3sjweffckkmivvsxtaknq" in output, output) + self.failUnless("file renewal secret: arpszxzc2t6kb4okkg7sp765xgkni5z7caavj7lta73vmtymjlxq" in output, output) + self.failUnless("lease renewal secret: 7pjtaumrb7znzkkbvekkmuwpqfjyfyamznfz4bwwvmh4nw33lorq" in output, output) u = u.get_readonly() output = self._dump_cap(u.to_string()) - self.failUnless("SSK Read-only URI:" in output) - self.failUnless("readkey: x4gowaektauqze4y2sbsd5peye" in output, output) - self.failUnless("storage index: rqx7xnpexjxuqprto6pezagdxi" in output, output) - self.failUnless("fingerprint: 737p57x6737p57x6737p57x6737p57x6737p57x6737p57x6737a" in output) + self.failUnless("SSK Read-only URI:" in output, output) + self.failUnless("readkey: nvgh5vj2ekzzkim5fgtb4gey5y" in output, output) + self.failUnless("storage index: nt4fwemuw7flestsezvo2eveke" in output, output) + self.failUnless("fingerprint: 737p57x6737p57x6737p57x6737p57x6737p57x6737p57x6737a" in output, output) u = u.get_verifier() output = self._dump_cap(u.to_string()) - self.failUnless("SSK Verifier URI:" in output) - self.failUnless("storage index: rqx7xnpexjxuqprto6pezagdxi" in output, output) - self.failUnless("fingerprint: 737p57x6737p57x6737p57x6737p57x6737p57x6737p57x6737a" in output) + self.failUnless("SSK Verifier URI:" in output, output) + self.failUnless("storage index: nt4fwemuw7flestsezvo2eveke" in output, output) + self.failUnless("fingerprint: 737p57x6737p57x6737p57x6737p57x6737p57x6737p57x6737a" in output, output) def test_dump_cap_directory(self): writekey = "\x01" * 16 @@ -181,38 +181,40 @@ class CLI(unittest.TestCase): u = uri.NewDirectoryURI(u1) output = self._dump_cap(u.to_string()) - self.failUnless("Directory Writeable URI:" in output) - self.failUnless("writekey: aeaqcaibaeaqcaibaeaqcaibae" in output, output) - self.failUnless("readkey: x4gowaektauqze4y2sbsd5peye" in output, output) - self.failUnless("storage index: rqx7xnpexjxuqprto6pezagdxi" in output, output) + self.failUnless("Directory Writeable URI:" in output, output) + self.failUnless("writekey: aeaqcaibaeaqcaibaeaqcaibae" in output, + output) + self.failUnless("readkey: nvgh5vj2ekzzkim5fgtb4gey5y" in output, output) + self.failUnless("storage index: nt4fwemuw7flestsezvo2eveke" in output, + output) self.failUnless("fingerprint: 737p57x6737p57x6737p57x6737p57x6737p57x6737p57x6737a" in output, output) - output = self._dump_cap("--client-secret", "a3nyfbnkorp377jhguslgc2dqi", + output = self._dump_cap("--client-secret", "5s33nk3qpvnj2fw3z4mnm2y6fa", u.to_string()) - self.failUnless("file renewal secret: zwmq2azrd7lfcmhkrhpgjsxeb2vfpixgvrczbo2asqzdfbmiemwq" in output, output) + self.failUnless("file renewal secret: arpszxzc2t6kb4okkg7sp765xgkni5z7caavj7lta73vmtymjlxq" in output, output) output = self._dump_cap("--nodeid", "tqc35esocrvejvg4mablt6aowg6tl43j", u.to_string()) - self.failUnless("write_enabler: eok7o6u26dvl3abw4ok7kqrka4omdolnsx627hpcvtx3kkjwsu5q" in output, output) - self.failIf("file renewal secret:" in output) + self.failUnless("write_enabler: mgcavriox2wlb5eer26unwy5cw56elh3sjweffckkmivvsxtaknq" in output, output) + self.failIf("file renewal secret:" in output, output) output = self._dump_cap("--nodeid", "tqc35esocrvejvg4mablt6aowg6tl43j", - "--client-secret", "rzaq5to2xm6e5otctpdvzw6bfa", + "--client-secret", "5s33nk3qpvnj2fw3z4mnm2y6fa", u.to_string()) - self.failUnless("write_enabler: eok7o6u26dvl3abw4ok7kqrka4omdolnsx627hpcvtx3kkjwsu5q" in output, output) - self.failUnless("file renewal secret: wdmu6rwefvmp2venbb4xz5u3273oybmuu553mi7uic37gfu6bacq" in output, output) - self.failUnless("lease renewal secret: tlvwfudyfeqyss5kybt6ya72foedqxdovumlbt6ok7u5pyrf2mfq" in output, output) + self.failUnless("write_enabler: mgcavriox2wlb5eer26unwy5cw56elh3sjweffckkmivvsxtaknq" in output, output) + self.failUnless("file renewal secret: arpszxzc2t6kb4okkg7sp765xgkni5z7caavj7lta73vmtymjlxq" in output, output) + self.failUnless("lease renewal secret: 7pjtaumrb7znzkkbvekkmuwpqfjyfyamznfz4bwwvmh4nw33lorq" in output, output) u = u.get_readonly() output = self._dump_cap(u.to_string()) - self.failUnless("Directory Read-only URI:" in output) - self.failUnless("readkey: x4gowaektauqze4y2sbsd5peye" in output, output) - self.failUnless("storage index: rqx7xnpexjxuqprto6pezagdxi" in output, output) - self.failUnless("fingerprint: 737p57x6737p57x6737p57x6737p57x6737p57x6737p57x6737a" in output) + self.failUnless("Directory Read-only URI:" in output, output) + self.failUnless("readkey: nvgh5vj2ekzzkim5fgtb4gey5y" in output, output) + self.failUnless("storage index: nt4fwemuw7flestsezvo2eveke" in output, output) + self.failUnless("fingerprint: 737p57x6737p57x6737p57x6737p57x6737p57x6737p57x6737a" in output, output) u = u.get_verifier() output = self._dump_cap(u.to_string()) - self.failUnless("Directory Verifier URI:" in output) - self.failUnless("storage index: rqx7xnpexjxuqprto6pezagdxi" in output, output) + self.failUnless("Directory Verifier URI:" in output, output) + self.failUnless("storage index: nt4fwemuw7flestsezvo2eveke" in output, output) self.failUnless("fingerprint: 737p57x6737p57x6737p57x6737p57x6737p57x6737p57x6737a" in output, output) diff --git a/src/allmydata/test/test_util.py b/src/allmydata/test/test_util.py index 1a8a4d1b..9c2c0cca 100644 --- a/src/allmydata/test/test_util.py +++ b/src/allmydata/test/test_util.py @@ -385,15 +385,17 @@ class DeferredUtilTests(unittest.TestCase): class HashUtilTests(unittest.TestCase): def test_sha256d(self): - h1 = hashutil.tagged_hash_256d("tag1", "value") - h2 = hashutil.tagged_hasher_256d("tag1") + h1 = hashutil.tagged_hash("tag1", "value") + h2 = hashutil.tagged_hasher("tag1") h2.update("value") - h2 = h2.digest() - self.failUnlessEqual(h1, h2) + h2a = h2.digest() + h2b = h2.digest() + self.failUnlessEqual(h1, h2a) + self.failUnlessEqual(h2a, h2b) def test_sha256d_truncated(self): - h1 = hashutil.tagged_hash_256d("tag1", "value", 16) - h2 = hashutil.tagged_hasher_256d("tag1", 16) + h1 = hashutil.tagged_hash("tag1", "value", 16) + h2 = hashutil.tagged_hasher("tag1", 16) h2.update("value") h2 = h2.digest() self.failUnlessEqual(len(h1), 16) diff --git a/src/allmydata/util/hashutil.py b/src/allmydata/util/hashutil.py index ee2b0cd2..6f6f90ea 100644 --- a/src/allmydata/util/hashutil.py +++ b/src/allmydata/util/hashutil.py @@ -1,7 +1,12 @@ from pycryptopp.hash.sha256 import SHA256 import os -# Various crypto values are this size: hash outputs (from SHA-256), +# Be very very cautious when modifying this file. Almost any change will +# cause a compatibility break, invalidating all outstanding URIs and making +# any previously uploaded files become inaccessible. BE CONSERVATIVE AND TEST +# AGAINST OLD DATA! + +# Various crypto values are this size: hash outputs (from SHA-256d), # randomly-generated secrets such as the lease secret, and symmetric encryption # keys. In the near future we will add DSA private keys, and salts of various # kinds. @@ -11,57 +16,78 @@ class IntegrityCheckError(Exception): pass def netstring(s): - assert isinstance(s, str), s + assert isinstance(s, str), s # no unicode here return "%d:%s," % (len(s), s,) -def tagged_hash(tag, val): - s = SHA256() - s.update(netstring(tag)) - s.update(val) - return s.digest() - -def tagged_hash_256d(tag, val, truncate_to=None): +class _SHA256d_Hasher: # 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 + self._digest = None def update(self, data): + assert isinstance(data, str) # no unicode 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) + if self._digest is None: + h1 = self.h.digest() + del self.h + h2 = SHA256(h1).digest() + if self.truncate_to: + h2 = h2[:self.truncate_to] + self._digest = h2 + return self._digest + + + +def tagged_hasher(tag, truncate_to=None): + hasher = _SHA256d_Hasher(truncate_to) hasher.update(netstring(tag)) return hasher -def tagged_pair_hash(tag, val1, val2): - s = SHA256() +def tagged_hash(tag, val, truncate_to=None): + hasher = tagged_hasher(tag, truncate_to) + hasher.update(val) + return hasher.digest() + +def tagged_pair_hash(tag, val1, val2, truncate_to=None): + s = _SHA256d_Hasher(truncate_to) s.update(netstring(tag)) s.update(netstring(val1)) s.update(netstring(val2)) return s.digest() -# specific hash tags that we use - -def tagged_hasher(tag): - return SHA256(netstring(tag)) +## specific hash tags that we use + +# immutable +STORAGE_INDEX_TAG = "allmydata_immutable_key_to_storage_index_v1" +BLOCK_TAG = "allmydata_encoded_subshare_v1" +UEB_TAG = "allmydata_uri_extension_v1" +PLAINTEXT_TAG = "allmydata_plaintext_v1" +CIPHERTEXT_TAG = "allmydata_crypttext_v1" +CIPHERTEXT_SEGMENT_TAG = "allmydata_crypttext_segment_v1" +PLAINTEXT_SEGMENT_TAG = "allmydata_plaintext_segment_v1" +CONTENT_HASH_KEY_TAG = "allmydata_immutable_content_to_key_v1+" + +CLIENT_RENEWAL_TAG = "allmydata_client_renewal_secret_v1" +CLIENT_CANCEL_TAG = "allmydata_client_cancel_secret_v1" +FILE_RENEWAL_TAG = "allmydata_file_renewal_secret_v1" +FILE_CANCEL_TAG = "allmydata_file_cancel_secret_v1" +BUCKET_RENEWAL_TAG = "allmydata_bucket_renewal_secret_v1" +BUCKET_CANCEL_TAG = "allmydata_bucket_cancel_secret_v1" + +# mutable +MUTABLE_WRITEKEY_TAG = "allmydata_mutable_privkey_to_writekey_v1" +MUTABLE_WRITE_ENABLER_MASTER_TAG = "allmydata_mutable_writekey_to_write_enabler_master_v1" +MUTABLE_WRITE_ENABLER_TAG = "allmydata_mutable_write_enabler_master_and_nodeid_to_write_enabler_v1" +MUTABLE_PUBKEY_TAG = "allmydata_mutable_pubkey_to_fingerprint_v1" +MUTABLE_READKEY_TAG = "allmydata_mutable_writekey_to_readkey_v1" +MUTABLE_DATAKEY_TAG = "allmydata_mutable_readkey_to_datakey_v1" +MUTABLE_STORAGEINDEX_TAG = "allmydata_mutable_readkey_to_storage_index_v1" + +# dirnodes +DIRNODE_CHILD_WRITECAP_TAG = "allmydata_mutable_writekey_and_salt_to_dirnode_child_capkey_v1" def storage_index_hash(key): # storage index is truncated to 128 bits (16 bytes). We're only hashing a @@ -69,94 +95,77 @@ def storage_index_hash(key): # We use this same tagged hash to go from encryption key to storage index # for random-keyed immutable files and content-hash-keyed immutabie # files. Mutable files use ssk_storage_index_hash(). - return tagged_hash_256d("allmydata_immutable_storage_index_v2", key, 16) + return tagged_hash(STORAGE_INDEX_TAG, key, 16) def block_hash(data): - return tagged_hash("allmydata_encoded_subshare_v1", data) + return tagged_hash(BLOCK_TAG, data) def block_hasher(): - return tagged_hasher("allmydata_encoded_subshare_v1") + return tagged_hasher(BLOCK_TAG) def uri_extension_hash(data): - return tagged_hash("allmydata_uri_extension_v1", data) + return tagged_hash(UEB_TAG, data) def uri_extension_hasher(): - return tagged_hasher("allmydata_uri_extension_v1") + return tagged_hasher(UEB_TAG) def plaintext_hash(data): - return tagged_hash("allmydata_plaintext_hash_v1", data) + return tagged_hash(PLAINTEXT_TAG, data) def plaintext_hasher(): - return tagged_hasher("allmydata_plaintext_hash_v1") + return tagged_hasher(PLAINTEXT_TAG) def crypttext_hash(data): - return tagged_hash("allmydata_crypttext_hash_v1", data) + return tagged_hash(CIPHERTEXT_TAG, data) def crypttext_hasher(): - return tagged_hasher("allmydata_crypttext_hash_v1") + return tagged_hasher(CIPHERTEXT_TAG) def crypttext_segment_hash(data): - return tagged_hash("allmydata_crypttext_segment_v1", data) + return tagged_hash(CIPHERTEXT_SEGMENT_TAG, data) def crypttext_segment_hasher(): - return tagged_hasher("allmydata_crypttext_segment_v1") + return tagged_hasher(CIPHERTEXT_SEGMENT_TAG) def plaintext_segment_hash(data): - return tagged_hash("allmydata_plaintext_segment_v1", data) + return tagged_hash(PLAINTEXT_SEGMENT_TAG, data) def plaintext_segment_hasher(): - return tagged_hasher("allmydata_plaintext_segment_v1") + return tagged_hasher(PLAINTEXT_SEGMENT_TAG) + +KEYLEN = 16 def content_hash_key_hash(k, n, segsize, data): - # This is defined to return a 16-byte AES key. We use SHA-256d here. + # this is defined to return a 16-byte AES key. We use SHA-256d here.. # we'd like to use it everywhere, but we're only switching algorithms # when we can hide the compatibility breaks in other necessary changes. param_tag = netstring("%d,%d,%d" % (k, n, segsize)) - h = tagged_hash_256d("allmydata_encryption_key_v2+" + param_tag, data, 16) + tag = CONTENT_HASH_KEY_TAG + param_tag + h = tagged_hash(tag, data, KEYLEN) return h def content_hash_key_hasher(k, n, segsize): param_tag = netstring("%d,%d,%d" % (k, n, segsize)) - return tagged_hasher_256d("allmydata_encryption_key_v2+" + param_tag, 16) + tag = CONTENT_HASH_KEY_TAG + param_tag + return tagged_hasher(tag, KEYLEN) -KEYLEN = 16 def random_key(): return os.urandom(KEYLEN) def my_renewal_secret_hash(my_secret): - return tagged_hash(my_secret, "bucket_renewal_secret") + return tagged_hash(my_secret, CLIENT_RENEWAL_TAG) def my_cancel_secret_hash(my_secret): - return tagged_hash(my_secret, "bucket_cancel_secret") + return tagged_hash(my_secret, CLIENT_CANCEL_TAG) def file_renewal_secret_hash(client_renewal_secret, storage_index): - return tagged_pair_hash("file_renewal_secret", + return tagged_pair_hash(FILE_RENEWAL_TAG, client_renewal_secret, storage_index) def file_cancel_secret_hash(client_cancel_secret, storage_index): - return tagged_pair_hash("file_cancel_secret", + return tagged_pair_hash(FILE_CANCEL_TAG, client_cancel_secret, storage_index) def bucket_renewal_secret_hash(file_renewal_secret, peerid): assert len(peerid) == 20, "%s: %r" % (len(peerid), peerid) # binary! - return tagged_pair_hash("bucket_renewal_secret", - file_renewal_secret, peerid) + return tagged_pair_hash(BUCKET_RENEWAL_TAG, file_renewal_secret, peerid) def bucket_cancel_secret_hash(file_cancel_secret, peerid): assert len(peerid) == 20, "%s: %r" % (len(peerid), peerid) # binary! - return tagged_pair_hash("bucket_cancel_secret", - file_cancel_secret, peerid) - -def dir_write_enabler_hash(write_key): - return tagged_hash("allmydata_dir_write_enabler_v1", write_key) -def dir_read_key_hash(write_key): - return tagged_hash("allmydata_dir_read_key_v1", write_key)[:KEYLEN] -def dir_index_hash(read_key): - return tagged_hash("allmydata_dir_index_v1", read_key) -def dir_name_hash(readkey, name): - return tagged_pair_hash("allmydata_dir_name_v1", readkey, name) - -def generate_dirnode_keys_from_writekey(write_key): - readkey = dir_read_key_hash(write_key) - write_enabler = dir_write_enabler_hash(write_key) - index = dir_index_hash(readkey) - return write_key, write_enabler, readkey, index - -def generate_dirnode_keys_from_readkey(read_key): - index = dir_index_hash(read_key) - return None, None, read_key, index + return tagged_pair_hash(BUCKET_CANCEL_TAG, file_cancel_secret, peerid) + def _xor(a, b): return "".join([chr(ord(c) ^ ord(b)) for c in a]) @@ -169,22 +178,23 @@ def hmac(tag, data): return h2 def mutable_rwcap_key_hash(iv, writekey): - return tagged_pair_hash("allmydata_mutable_rwcap_key_v1", iv, writekey)[:16] + return tagged_pair_hash(DIRNODE_CHILD_WRITECAP_TAG, iv, writekey, KEYLEN) + def ssk_writekey_hash(privkey): - return tagged_hash("allmydata_mutable_writekey_v1", privkey)[:16] + return tagged_hash(MUTABLE_WRITEKEY_TAG, privkey, KEYLEN) def ssk_write_enabler_master_hash(writekey): - return tagged_hash("allmydata_mutable_write_enabler_master_v1", writekey) + return tagged_hash(MUTABLE_WRITE_ENABLER_MASTER_TAG, writekey) def ssk_write_enabler_hash(writekey, peerid): assert len(peerid) == 20, "%s: %r" % (len(peerid), peerid) # binary! wem = ssk_write_enabler_master_hash(writekey) - return tagged_pair_hash("allmydata_mutable_write_enabler_v1", wem, peerid) + return tagged_pair_hash(MUTABLE_WRITE_ENABLER_TAG, wem, peerid) def ssk_pubkey_fingerprint_hash(pubkey): - return tagged_hash("allmydata_mutable_pubkey_v1", pubkey) + return tagged_hash(MUTABLE_PUBKEY_TAG, pubkey) def ssk_readkey_hash(writekey): - return tagged_hash("allmydata_mutable_readkey_v1", writekey)[:16] + return tagged_hash(MUTABLE_READKEY_TAG, writekey, KEYLEN) def ssk_readkey_data_hash(IV, readkey): - return tagged_pair_hash("allmydata_mutable_readkey_data_v1", IV, readkey)[:16] + return tagged_pair_hash(MUTABLE_DATAKEY_TAG, IV, readkey, KEYLEN) def ssk_storage_index_hash(readkey): - return tagged_hash("allmydata_mutable_storage_index_v1", readkey)[:16] + return tagged_hash(MUTABLE_STORAGEINDEX_TAG, readkey, KEYLEN)