From 3abde25757bb3409f4448c50cce8d024fe4f88b6 Mon Sep 17 00:00:00 2001 From: Tom Prince <tom.prince@private.storage> Date: Tue, 7 Dec 2021 14:12:38 -0700 Subject: [PATCH] Add `Pass.from_bytes`. --- src/_zkapauthorizer/_storage_server.py | 9 ++++++--- src/_zkapauthorizer/model.py | 4 ++++ src/_zkapauthorizer/tests/storage_common.py | 2 +- src/_zkapauthorizer/tests/test_controller.py | 7 ++++--- src/_zkapauthorizer/tests/test_model.py | 18 ++++++++++++++++++ 5 files changed, 33 insertions(+), 7 deletions(-) diff --git a/src/_zkapauthorizer/_storage_server.py b/src/_zkapauthorizer/_storage_server.py index 1b54113..b847499 100644 --- a/src/_zkapauthorizer/_storage_server.py +++ b/src/_zkapauthorizer/_storage_server.py @@ -49,6 +49,7 @@ from twisted.python.reflect import namedAny from zope.interface import implementer from .foolscap import RIPrivacyPassAuthorizedStorageServer, ShareStat +from .model import Pass from .storage_common import ( MorePassesRequired, add_lease_message, @@ -112,9 +113,11 @@ class _ValidationResult(object): assert isinstance(message, unicode), "message %r not unicode" % (message,) assert isinstance(pass_, bytes), "pass %r not bytes" % (pass_,) try: - preimage_base64, signature_base64 = pass_.split(b" ") - preimage = TokenPreimage.decode_base64(preimage_base64) - proposed_signature = VerificationSignature.decode_base64(signature_base64) + parsed_pass = Pass.from_bytes(pass_) + preimage = TokenPreimage.decode_base64(parsed_pass.preimage) + proposed_signature = VerificationSignature.decode_base64( + parsed_pass.signature + ) unblinded_token = signing_key.rederive_unblinded_token(preimage) verification_key = unblinded_token.derive_verification_key_sha512() invalid_pass = verification_key.invalid_sha512( diff --git a/src/_zkapauthorizer/model.py b/src/_zkapauthorizer/model.py index 594afc4..7530d2b 100644 --- a/src/_zkapauthorizer/model.py +++ b/src/_zkapauthorizer/model.py @@ -877,6 +877,10 @@ class Pass(object): def pass_bytes(self): return b" ".join((self.preimage, self.signature)) + @classmethod + def from_bytes(cls, pass_): + return cls(*pass_.split(b" ")) + @attr.s(frozen=True) class RandomToken(object): diff --git a/src/_zkapauthorizer/tests/storage_common.py b/src/_zkapauthorizer/tests/storage_common.py index ab4f2be..a72cbb5 100644 --- a/src/_zkapauthorizer/tests/storage_common.py +++ b/src/_zkapauthorizer/tests/storage_common.py @@ -164,7 +164,7 @@ def get_passes(message, count, signing_key): and bound to the given message. """ return list( - Pass(*pass_.split(b" ")) + Pass.from_bytes(pass_) for pass_ in make_passes( signing_key, message, diff --git a/src/_zkapauthorizer/tests/test_controller.py b/src/_zkapauthorizer/tests/test_controller.py index fce655c..e4f08b1 100644 --- a/src/_zkapauthorizer/tests/test_controller.py +++ b/src/_zkapauthorizer/tests/test_controller.py @@ -76,6 +76,7 @@ from ..controller import ( ) from ..model import DoubleSpend as model_DoubleSpend from ..model import Error as model_Error +from ..model import Pass from ..model import Pending as model_Pending from ..model import Redeemed as model_Redeemed from ..model import Redeeming as model_Redeeming @@ -1016,10 +1017,10 @@ def ristretto_verify(signing_key, message, marshaled_passes): """ def decode(marshaled_pass): - t, s = marshaled_pass.split(b" ") + pass_ = Pass.from_bytes(marshaled_pass) return ( - TokenPreimage.decode_base64(t), - VerificationSignature.decode_base64(s), + TokenPreimage.decode_base64(pass_.preimage), + VerificationSignature.decode_base64(pass_.signature), ) servers_passes = list( diff --git a/src/_zkapauthorizer/tests/test_model.py b/src/_zkapauthorizer/tests/test_model.py index bff6a60..93605cd 100644 --- a/src/_zkapauthorizer/tests/test_model.py +++ b/src/_zkapauthorizer/tests/test_model.py @@ -61,6 +61,7 @@ from ..model import ( DoubleSpend, LeaseMaintenanceActivity, NotEnoughTokens, + Pass, Pending, Redeemed, StoreOpenError, @@ -80,6 +81,7 @@ from .strategies import ( voucher_counters, voucher_objects, vouchers, + zkaps, ) @@ -951,3 +953,19 @@ def store_for_test(testcase, get_config, get_now): memory_connect, ) return store + + +class PassTests(TestCase): + """ + Tests for ``Pass``. + """ + + @given(zkaps()) + def test_roundtrip(self, pass_): + """ + ``Pass`` round-trips through ``Pass.from_bytes`` and ``Pass.pass_bytes``. + """ + self.assertThat( + Pass.from_bytes(pass_.pass_bytes), + Equals(pass_), + ) -- GitLab