diff --git a/src/_zkapauthorizer/controller.py b/src/_zkapauthorizer/controller.py index 46a495ffdc06ab2517f3d69aecd9f3724bbc383b..9d9663b92b0b9a8f7c4b24a83db3653c27801ba1 100644 --- a/src/_zkapauthorizer/controller.py +++ b/src/_zkapauthorizer/controller.py @@ -137,7 +137,7 @@ class IRedeemer(Interface): """ An ``IRedeemer`` can exchange a voucher for one or more passes. """ - def random_tokens_for_voucher(voucher, count): + def random_tokens_for_voucher(voucher, counter, count): """ Generate a number of random tokens to use in the redemption process for the given voucher. @@ -212,8 +212,8 @@ class NonRedeemer(object): def make(cls, section_name, node_config, announcement, reactor): return cls() - def random_tokens_for_voucher(self, voucher, count): - return dummy_random_tokens(voucher, count) + def random_tokens_for_voucher(self, voucher, counter, count): + return dummy_random_tokens(voucher, counter, count) def redeemWithCounter(self, voucher, counter, random_tokens): # Don't try to redeem them. @@ -242,8 +242,8 @@ class ErrorRedeemer(object): ).decode("ascii") return cls(details) - def random_tokens_for_voucher(self, voucher, count): - return dummy_random_tokens(voucher, count) + def random_tokens_for_voucher(self, voucher, counter, count): + return dummy_random_tokens(voucher, counter, count) def redeemWithCounter(self, voucher, counter, random_tokens): return fail(Exception(self.details)) @@ -265,8 +265,8 @@ class DoubleSpendRedeemer(object): def make(cls, section_name, node_config, announcement, reactor): return cls() - def random_tokens_for_voucher(self, voucher, count): - return dummy_random_tokens(voucher, count) + def random_tokens_for_voucher(self, voucher, counter, count): + return dummy_random_tokens(voucher, counter, count) def redeemWithCounter(self, voucher, counter, random_tokens): return fail(AlreadySpent(voucher)) @@ -283,21 +283,21 @@ class UnpaidRedeemer(object): def make(cls, section_name, node_config, announcement, reactor): return cls() - def random_tokens_for_voucher(self, voucher, count): - return dummy_random_tokens(voucher, count) + def random_tokens_for_voucher(self, voucher, counter, count): + return dummy_random_tokens(voucher, counter, count) def redeemWithCounter(self, voucher, counter, random_tokens): return fail(Unpaid(voucher)) -def dummy_random_tokens(voucher, count): +def dummy_random_tokens(voucher, counter, count): v = urlsafe_b64decode(voucher.number.encode("ascii")) def dummy_random_token(n): return RandomToken( # Padding is 96 (random token length) - 32 (decoded voucher - # length) + # length) - 4 (fixed-width counter) b64encode( - v + u"{:0>64}".format(n).encode("ascii"), + v + u"{:0>4}{:0>60}".format(counter, n).encode("ascii"), ).decode("ascii"), ) return list( @@ -321,12 +321,12 @@ class DummyRedeemer(object): def make(cls, section_name, node_config, announcement, reactor): return cls() - def random_tokens_for_voucher(self, voucher, count): + def random_tokens_for_voucher(self, voucher, counter, count): """ Generate some number of random tokens to submit along with a voucher for redemption. """ - return dummy_random_tokens(voucher, count) + return dummy_random_tokens(voucher, counter, count) def redeemWithCounter(self, voucher, counter, random_tokens): """ @@ -440,7 +440,7 @@ class RistrettoRedeemer(object): URL.from_text(configured_issuer), ) - def random_tokens_for_voucher(self, voucher, count): + def random_tokens_for_voucher(self, voucher, counter, count): return list( RandomToken( challenge_bypass_ristretto.RandomToken.create().encode_base64().decode("ascii"), @@ -748,6 +748,7 @@ class PaymentController(object): ) return self.redeemer.random_tokens_for_voucher( Voucher(voucher), + counter, num_tokens, ) diff --git a/src/_zkapauthorizer/tests/test_controller.py b/src/_zkapauthorizer/tests/test_controller.py index 9c618973a3ae0ca633e8b4416cc1dda25ab2e19b..678d0d7d6c25524413c248d9048cc0b948dd8409 100644 --- a/src/_zkapauthorizer/tests/test_controller.py +++ b/src/_zkapauthorizer/tests/test_controller.py @@ -416,7 +416,7 @@ class RistrettoRedeemerTests(TestCase): issuer = RistrettoRedemption(signing_key) treq = treq_for_loopback_ristretto(issuer) redeemer = RistrettoRedeemer(treq, NOWHERE) - random_tokens = redeemer.random_tokens_for_voucher(voucher, num_tokens) + random_tokens = redeemer.random_tokens_for_voucher(voucher, counter, num_tokens) d = redeemer.redeemWithCounter( voucher, counter, @@ -450,7 +450,7 @@ class RistrettoRedeemerTests(TestCase): issuer = AlreadySpentRedemption() treq = treq_for_loopback_ristretto(issuer) redeemer = RistrettoRedeemer(treq, NOWHERE) - random_tokens = redeemer.random_tokens_for_voucher(voucher, num_tokens) + random_tokens = redeemer.random_tokens_for_voucher(voucher, counter, num_tokens) d = redeemer.redeemWithCounter( voucher, counter, @@ -477,7 +477,7 @@ class RistrettoRedeemerTests(TestCase): issuer = UnpaidRedemption() treq = treq_for_loopback_ristretto(issuer) redeemer = RistrettoRedeemer(treq, NOWHERE) - random_tokens = redeemer.random_tokens_for_voucher(voucher, num_tokens) + random_tokens = redeemer.random_tokens_for_voucher(voucher, counter, num_tokens) d = redeemer.redeemWithCounter( voucher, counter, @@ -510,7 +510,7 @@ class RistrettoRedeemerTests(TestCase): treq = treq_for_loopback_ristretto(issuer) redeemer = RistrettoRedeemer(treq, NOWHERE) - random_tokens = redeemer.random_tokens_for_voucher(voucher, num_tokens) + random_tokens = redeemer.random_tokens_for_voucher(voucher, counter, num_tokens) d = redeemer.redeemWithCounter( voucher, counter, @@ -540,7 +540,7 @@ class RistrettoRedeemerTests(TestCase): treq = treq_for_loopback_ristretto(issuer) redeemer = RistrettoRedeemer(treq, NOWHERE) - random_tokens = redeemer.random_tokens_for_voucher(voucher, num_tokens) + random_tokens = redeemer.random_tokens_for_voucher(voucher, counter, num_tokens) d = redeemer.redeemWithCounter( voucher, counter,