Merge pull request #968 from LeastAuthority/3592.convergence-hasher-tag-tests

convergence hasher tag tests

Fixes: ticket:3592
This commit is contained in:
Jean-Paul Calderone 2021-02-11 16:25:41 -05:00 committed by GitHub
commit 9ad4d31d9d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 71 additions and 1 deletions

0
newsfragments/3592.minor Normal file
View File

View File

@ -126,6 +126,42 @@ class HashUtilTests(unittest.TestCase):
base32.a2b(b"2ckv3dfzh6rgjis6ogfqhyxnzy"), base32.a2b(b"2ckv3dfzh6rgjis6ogfqhyxnzy"),
) )
def test_convergence_hasher_tag(self):
"""
``_convergence_hasher_tag`` constructs the convergence hasher tag from a
unique prefix, the required, total, and segment size parameters, and a
convergence secret.
"""
self.assertEqual(
b"allmydata_immutable_content_to_key_with_added_secret_v1+"
b"16:\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42,"
b"9:3,10,1024,",
hashutil._convergence_hasher_tag(
k=3,
n=10,
segsize=1024,
convergence=b"\x42" * 16,
),
)
def test_convergence_hasher_out_of_bounds(self):
"""
``_convergence_hasher_tag`` raises ``ValueError`` if k or n is not between
1 and 256 inclusive or if k is greater than n.
"""
segsize = 1024
secret = b"\x42" * 16
for bad_k in (0, 2, 257):
with self.assertRaises(ValueError):
hashutil._convergence_hasher_tag(
k=bad_k, n=1, segsize=segsize, convergence=secret,
)
for bad_n in (0, 1, 257):
with self.assertRaises(ValueError):
hashutil._convergence_hasher_tag(
k=2, n=bad_n, segsize=segsize, convergence=secret,
)
def test_known_answers(self): def test_known_answers(self):
""" """
Verify backwards compatibility by comparing hash outputs for some Verify backwards compatibility by comparing hash outputs for some

View File

@ -176,10 +176,44 @@ def convergence_hash(k, n, segsize, data, convergence):
return h.digest() return h.digest()
def convergence_hasher(k, n, segsize, convergence): def _convergence_hasher_tag(k, n, segsize, convergence):
"""
Create the convergence hashing tag.
:param int k: Required shares (in [1..256]).
:param int n: Total shares (in [1..256]).
:param int segsize: Maximum segment size.
:param bytes convergence: The convergence secret.
:return bytes: The bytestring to use as a tag in the convergence hash.
"""
assert isinstance(convergence, bytes) assert isinstance(convergence, bytes)
if k > n:
raise ValueError(
"k > n not allowed; k = {}, n = {}".format(k, n),
)
if k < 1 or n < 1:
# It doesn't make sense to have zero shares. Zero shares carry no
# information, cannot encode any part of the application data.
raise ValueError(
"k, n < 1 not allowed; k = {}, n = {}".format(k, n),
)
if k > 256 or n > 256:
# ZFEC supports encoding application data into a maximum of 256
# shares. If we ignore the limitations of ZFEC, it may be fine to use
# a configuration with more shares than that and it may be fine to
# construct a convergence tag from such a configuration. Since ZFEC
# is the only supported encoder, though, this is moot for now.
raise ValueError(
"k, n > 256 not allowed; k = {}, n = {}".format(k, n),
)
param_tag = netstring(b"%d,%d,%d" % (k, n, segsize)) param_tag = netstring(b"%d,%d,%d" % (k, n, segsize))
tag = CONVERGENT_ENCRYPTION_TAG + netstring(convergence) + param_tag tag = CONVERGENT_ENCRYPTION_TAG + netstring(convergence) + param_tag
return tag
def convergence_hasher(k, n, segsize, convergence):
tag = _convergence_hasher_tag(k, n, segsize, convergence)
return tagged_hasher(tag, KEYLEN) return tagged_hasher(tag, KEYLEN)