def test_bad_ristretto_redemption(self, voucher, counter, extra_tokens): """ If the issuer returns a successful result with an invalid proof then ``RistrettoRedeemer.redeem`` returns a ``Deferred`` that fires with a ``Failure`` wrapping ``SecurityException``. """ num_tokens = counter + extra_tokens signing_key = random_signing_key() issuer = RistrettoRedemption(signing_key) # Make it lie about the public key it is using. This causes the proof # to be invalid since it proves the signature was made with a # different key than reported in the response. issuer.public_key = PublicKey.from_signing_key(random_signing_key()) treq = treq_for_loopback_ristretto(issuer) redeemer = RistrettoRedeemer(treq, NOWHERE) random_tokens = redeemer.random_tokens_for_voucher( voucher, counter, num_tokens) d = redeemer.redeemWithCounter( voucher, counter, random_tokens, ) self.addDetail(u"redeem Deferred", text_content(str(d))) self.assertThat( d, failed( AfterPreprocessing( lambda f: f.value, IsInstance(SecurityException), ), ), )
def test_ristretto_pass_construction(self, voucher, counter, extra_tokens): """ The passes constructed using unblinded tokens and messages pass the Ristretto verification check. """ num_tokens = counter + extra_tokens message = b"hello world" signing_key = random_signing_key() issuer = RistrettoRedemption(signing_key) treq = treq_for_loopback_ristretto(issuer) redeemer = RistrettoRedeemer(treq, NOWHERE) random_tokens = redeemer.random_tokens_for_voucher( voucher, counter, num_tokens) d = redeemer.redeemWithCounter( voucher, counter, random_tokens, ) def unblinded_tokens_to_passes(result): passes = redeemer.tokens_to_passes(message, result.unblinded_tokens) return passes d.addCallback(unblinded_tokens_to_passes) self.assertThat( d, succeeded( AfterPreprocessing( partial(ristretto_verify, signing_key, message), Equals(True), ), ), )
def test_good_ristretto_redemption(self, voucher, counter, num_tokens): """ If the issuer returns a successful result then ``RistrettoRedeemer.redeem`` returns a ``Deferred`` that fires with a list of ``UnblindedToken`` instances. """ signing_key = random_signing_key() issuer = RistrettoRedemption(signing_key) treq = treq_for_loopback_ristretto(issuer) redeemer = RistrettoRedeemer(treq, NOWHERE) random_tokens = redeemer.random_tokens_for_voucher( voucher, counter, num_tokens) d = redeemer.redeemWithCounter( voucher, counter, random_tokens, ) self.assertThat( d, succeeded( MatchesStructure( unblinded_tokens=MatchesAll( AllMatch(IsInstance(UnblindedToken), ), HasLength(num_tokens), ), public_key=Equals( PublicKey.from_signing_key( signing_key).encode_base64(), ), ), ), )
def setUp(self): super(PassValidationTests, self).setUp() self.clock = Clock() # anonymous_storage_server uses time.time() so get our Clock close to # the same time so we can do lease expiration calculations more # easily. self.clock.advance(time()) self.anonymous_storage_server = self.useFixture(AnonymousStorageServer()).storage_server self.signing_key = random_signing_key() self.storage_server = ZKAPAuthorizerStorageServer( self.anonymous_storage_server, self.pass_value, self.signing_key, self.clock, )
def run(): # server setup skey = p.random_signing_key() pk = p.PublicKey(skey) ## signing # client prepares a random token and blinding scalar token = p.RandomToken() # client blinds the token and sends it to the server blinded_token = token.blind() encoded = blinded_token.marshal_text() server_blinded_token = p.BlindedToken.unmarshal_text(encoded) # server signs blinded token signed_token = skey.sign(server_blinded_token)
def setUp(self): super(ShareTests, self).setUp() self.canary = LocalReferenceable(None) self.anonymous_storage_server = self.useFixture( AnonymousStorageServer()).storage_server self.signing_key = random_signing_key() self.pass_factory = pass_factory( get_passes=privacypass_passes(self.signing_key)) self.server = ZKAPAuthorizerStorageServer( self.anonymous_storage_server, self.pass_value, self.signing_key, ) self.local_remote_server = LocalRemote(self.server) self.client = ZKAPAuthorizerStorageClient( self.pass_value, get_rref=lambda: self.local_remote_server, get_passes=self.pass_factory.get, )
def setUp(self): super(ShareTests, self).setUp() self.canary = LocalReferenceable(None) self.anonymous_storage_server = self.useFixture( AnonymousStorageServer()).storage_server self.signing_key = random_signing_key() self.spent_passes = 0 def counting_get_passes(message, count): self.spent_passes += count return get_passes(message, count, self.signing_key) self.server = ZKAPAuthorizerStorageServer( self.anonymous_storage_server, self.pass_value, self.signing_key, ) self.local_remote_server = LocalRemote(self.server) self.client = ZKAPAuthorizerStorageClient( self.pass_value, get_rref=lambda: self.local_remote_server, get_passes=counting_get_passes, )
def test_rejected_passes_reported(self, storage_index, renew_secret, cancel_secret, sharenums, size, data): """ Any passes rejected by the storage server are reported with a ``MorePassesRequired`` exception sent to the client. """ # Hypothesis causes our storage server to be used many times. Clean # up between iterations. cleanup_storage_server(self.anonymous_storage_server) num_passes = required_passes(self.pass_value, [size] * len(sharenums)) # Pick some passes to mess with. bad_pass_indexes = data.draw( lists( integers( min_value=0, max_value=num_passes - 1, ), min_size=1, max_size=num_passes, unique=True, ), ) # Make some passes with a key untrusted by the server. bad_passes = get_passes( allocate_buckets_message(storage_index), len(bad_pass_indexes), random_signing_key(), ) # Make some passes with a key trusted by the server. good_passes = get_passes( allocate_buckets_message(storage_index), num_passes - len(bad_passes), self.signing_key, ) all_passes = [] for i in range(num_passes): if i in bad_pass_indexes: all_passes.append(bad_passes.pop()) else: all_passes.append(good_passes.pop()) # Sanity checks self.assertThat(bad_passes, Equals([])) self.assertThat(good_passes, Equals([])) self.assertThat(all_passes, HasLength(num_passes)) self.assertThat( # Bypass the client handling of MorePassesRequired so we can see # it. self.local_remote_server.callRemote( "allocate_buckets", list(pass_.pass_text.encode("ascii") for pass_ in all_passes), storage_index, renew_secret, cancel_secret, sharenums, size, canary=self.canary, ), failed( AfterPreprocessing( lambda f: f.value, Equals( MorePassesRequired( valid_count=num_passes - len(bad_pass_indexes), required_count=num_passes, signature_check_failed=bad_pass_indexes, ), ), ), ), )
def setUp(self): super(ValidationResultTests, self).setUp() self.signing_key = random_signing_key()