def test_signature_proof(): mG = BilinearGroupPair() keypair = BBSPlusKeypair.generate(mG, 9) messages = [Bn(30), Bn(31), Bn(32)] pk, sk = keypair.pk, keypair.sk generators, h0 = keypair.generators, keypair.h0 creator = BBSPlusSignatureCreator(pk) lhs = creator.commit(messages) presignature = sk.sign(lhs.com_message) signature = creator.obtain_signature(presignature) e, s, m1, m2, m3 = (Secret() for _ in range(5)) secret_dict = { e: signature.e, s: signature.s, m1: messages[0], m2: messages[1], m3: messages[2], } p1 = BBSPlusSignatureStmt([e, s, m1, m2, m3], pk, signature) prover = p1.get_prover(secret_dict) p2 = BBSPlusSignatureStmt([Secret() for _ in range(5)], pk) verifier = p2.get_verifier() pc = prover.precommit() verifier.process_precommitment(pc) com = prover.commit() chal = verifier.send_challenge(com) resp = prover.compute_response(chal) assert verifier.verify(resp)
def test_ec_sum(group): g = group.generator() assert group.sum([g] * 10) == (10 * g) order = group.order() h = order.random() * g assert group.wsum([Bn(10), Bn(20)], [g, h]) == 10 * g + 20 * h
def test_signature_non_interactive_proof(): mG = BilinearGroupPair() keypair = BBSPlusKeypair.generate(mG, 9) messages = [Bn(30), Bn(31), Bn(32)] pk, sk = keypair.pk, keypair.sk generators, h0 = keypair.generators, keypair.h0 creator = BBSPlusSignatureCreator(pk) lhs = creator.commit(messages) presignature = sk.sign(lhs.com_message) signature = creator.obtain_signature(presignature) e, s, m1, m2, m3 = (Secret() for _ in range(5)) secret_dict = { e: signature.e, s: signature.s, m1: messages[0], m2: messages[1], m3: messages[2], } p1 = BBSPlusSignatureStmt([e, s, m1, m2, m3], pk, signature) tr = p1.prove(secret_dict) p1 = BBSPlusSignatureStmt([Secret() for _ in range(5)], pk) assert p1.verify(tr)
def test_gt_prod(): g = GT.generator() assert group.prod([g] * 10) == (g ** 10) order = GT.order() h = g ** order.random() assert group.wprod([Bn(10), Bn(20)], [g, h]) == g ** 10 * h ** 20
def create_issue_request(server_pk, attributes): """Gets all known attributes (subscription) of a user and creates an issuance request. You are allowed to add extra attributes to the issuance. You should design the issue_request as you see fit. """ attributes = [Bn.from_binary(hashlib.sha256(attr.encode()).digest()) for attr in attributes] gen_g1 = server_pk[0] t = G1.order().random() #Gen C C = gen_g1 ** t for e in zip(server_pk[1:], attributes): C = C * e[0] ** e[1] #Gen commitment comm_values = [G1.order().random() for _ in range(len(attributes) + 1)] comm = gen_g1 ** comm_values[0] for e in zip(server_pk[1:], comm_values[1:]): comm = comm * e[0] ** e[1] #Gen challenge challenge = hashlib.sha256(jsonpickle.encode(C).encode()) challenge.update(jsonpickle.encode(comm).encode()) challenge.update(jsonpickle.encode(server_pk).encode()) challenge = Bn.from_binary(challenge.digest()) #Generate response response = [e[0].mod_sub(challenge * e[1],G1.order()) for e in zip(comm_values, [t] + attributes)] return IssuanceRequest(C, comm, challenge, response),t
def test_gt_exponentiation(): g = GT.generator() assert g ** 3 == g * g * g assert g ** (-1) == g.inverse() assert g ** 10 == g.pow(10) assert g ** Bn(10) == g.pow(Bn(10))
def test_bn_prime(): for safe in (0, 1): p = Bn.get_prime(128, safe=safe) assert p > Bn(0) assert p.is_prime() assert not Bn(16).is_prime() assert p.num_bits() > 127
def test_gt_exponentiation(): group = GTGroup() g = group.generator() assert g**3 == g * g * g assert g**(-1) == g.inv() assert g**10 == g.exp(10) assert g**Bn(10) == g.exp(Bn(10))
def sign(self, message, revealed_attr): """Signs the message. Args: message (byte []): message revealed_attr (string []): a list of revealed attributes Return: Signature: signature """ #public_key separation nb_attr_public_key = (len(self.server_pk) - 3) // 2 gen_g1_pk = self.server_pk[0] public_key1 = self.server_pk[1:nb_attr_public_key + 1] gen_g2_pk = self.server_pk[nb_attr_public_key + 1] x_g2_pk = self.server_pk[nb_attr_public_key + 2] public_key2 = self.server_pk[nb_attr_public_key + 3:] #Gen signature r = G1.order().random() t = G1.order().random() signature = (self.credential[0] ** r, (self.credential[1] * self.credential[0]**t)**r) #attributes work revealed_attributes_idx = [self.attributes.index(attr) for attr in self.attributes if attr in revealed_attr] revealed_attributes_bn = [Bn.from_binary(hashlib.sha256(attr.encode()).digest()) for attr in revealed_attr] hidden_attributes_idx = [self.attributes.index(attr) for attr in self.attributes if attr not in revealed_attr] hidden_attributes_bn = [Bn.from_binary(hashlib.sha256(attr.encode()).digest()) for attr in self.attributes if attr not in revealed_attr] #Gen C (left-hand side) C = signature[1].pair(gen_g2_pk) / signature[0].pair(x_g2_pk) for i in range(len(revealed_attr)): C = C * signature[0].pair(public_key2[revealed_attributes_idx[i]]) ** (-revealed_attributes_bn[i] % G1.order()) #Gen commitment (to prove right-hand side) comm_values = [G1.order().random() for _ in range(len(hidden_attributes_idx) + 1)] comm = signature[0].pair(gen_g2_pk) ** comm_values[0] for e in zip(hidden_attributes_idx, comm_values[1:]): comm = comm * signature[0].pair(public_key2[e[0]])**e[1] #Gen Challenge challenge = hashlib.sha256(jsonpickle.encode(C).encode()) challenge.update(jsonpickle.encode(comm).encode()) challenge.update(jsonpickle.encode(self.server_pk).encode()) challenge.update(message) challenge = Bn.from_binary(challenge.digest()) #Gen Responses response = [e[0].mod_sub(challenge * e[1],G1.order()) for e in zip(comm_values, [t] + hidden_attributes_bn)] return Signature(signature, comm, challenge, response, revealed_attributes_idx)
def test_odd(): assert Bn(1).is_odd() assert Bn(1).is_bit_set(0) assert not Bn(1).is_bit_set(1) assert Bn(3).is_odd() assert Bn(3).is_bit_set(0) assert Bn(3).is_bit_set(1) assert not Bn(0).is_odd() assert not Bn(2).is_odd() assert Bn(100).is_bit_set(Bn(100).num_bits() - 1)
def test_wsum_groups(group): g = group.generator() g1 = 10 * g g2 = 20 * g a1 = Bn(2) a2 = Bn(4) s = group.wsum([g1, g2], [a1, a2]) assert s == 100 * g # Make sure the type is still correct assert s.__class__ == g.__class__
def test_signature_setup(): mG = BilinearGroupPair() keypair = BBSPlusKeypair.generate(mG, 9) messages = [Bn(30), Bn(31), Bn(32), Bn(12)] pk, sk = keypair.pk, keypair.sk generators, h0 = keypair.generators, keypair.h0 creator = BBSPlusSignatureCreator(pk) com = creator.commit(messages, zkp=True) presignature = sk.sign(com.com_message) signature = creator.obtain_signature(presignature) assert com.verify_blinding(pk) and signature.verify_signature(pk, messages)
def verify(self, issuer_public_info, public_attrs, message): """Verifies a signature. Args: issuer_public_info (): output of issuer's 'get_serialized_public_key' method public_attrs (dict): public attributes message (byte []): list of messages returns: valid (boolean): is signature valid """ #public_key separation nb_attr_public_key = (len(issuer_public_info) - 3) // 2 gen_g1_pk = issuer_public_info[0] public_key1 = issuer_public_info[1:nb_attr_public_key + 1] gen_g2_pk = issuer_public_info[nb_attr_public_key + 1] x_g2_pk = issuer_public_info[nb_attr_public_key + 2] public_key2 = issuer_public_info[nb_attr_public_key + 3:] #attributes work nb_attr = len(self.response) - 1 + len(public_attrs) public_attributes_idx = self.attributes_idx public_attributes_bn = [Bn.from_binary(hashlib.sha256(attr.encode()).digest()) for attr in public_attrs] hidden_attributes_idx = [i for i in range(nb_attr) if i not in public_attributes_idx] #Gen C (left-hand side) C = self.signature[1].pair(gen_g2_pk) / self.signature[0].pair(x_g2_pk) for i in range(len(public_attrs)): C = C * self.signature[0].pair(public_key2[public_attributes_idx[i]]) ** (-public_attributes_bn[i] % G1.order()) #Gen Challenge challenge = hashlib.sha256(jsonpickle.encode(C).encode()) challenge.update(jsonpickle.encode(self.commitment).encode()) challenge.update(jsonpickle.encode(issuer_public_info).encode()) challenge.update(message) challenge = Bn.from_binary(challenge.digest()) #check challenge challenge_valid = challenge == self.challenge #Compute zkp candidate = C ** challenge * self.signature[0].pair(gen_g2_pk) ** self.response[0] for e in zip(hidden_attributes_idx, self.response[1:]): candidate = candidate * self.signature[0].pair(public_key2[e[0]]) ** e[1] proof_valid = candidate == self.commitment return challenge_valid and proof_valid
def sign(cls, sk, messages): m = Bn.from_binary(hashlib.sha256(messages).digest()) h = G1.generator() ** G1.order().random() while h == G1.neutral_element(): h = G1.generator() ** G1.order().random() sig = [h, h ** (sk[0] + sk[1] * m)] return sig
def test_ec_arithmetic(group): g = group.generator() assert not g == 5 assert g != 5 assert g + g == g + g assert g + g == g.double() assert g + g == Bn(2) * g assert g + g == 2 * g assert g + g != g + g + g assert g + (-g) == group.neutral_element() d = {} d[2 * g] = 2 assert d[2 * g] == 2 q = group.generator() q *= 10 assert q == g * 10 q *= 10 assert q == g * 10 * 10 # Test long names assert (g + g).eq(g + g) assert g + g == g.add(g) assert -g == g.neg() assert 10 * g == g.mul(10) assert len(str(g)) > 0 # Bug for large factors multiplication. a = 4 * group.order() assert (g * a).is_neutral_element()
def test_ec_arithmetic(group): g = group.generator() assert g + g == g + g assert g + g == g.double() assert g + g == Bn(2) * g assert g + g == 2 * g assert g + g != g + g + g assert g + (-g) == group.neutral_element() d = {} d[2 * g] = 2 assert d[2 * g] == 2 # Test long names assert (g + g).eq(g + g) assert g + g == g.add(g) assert -g == g.neg() assert 10 * g == g.mul(10) assert len(str(g)) > 0 neutral_element = group.neutral_element() assert group.infinity() == neutral_element assert g + neutral_element == g assert neutral_element + neutral_element == neutral_element
def test_gt_multiplication(): group = GTGroup() g = group.generator() assert g * g == g * g assert g * g == g.mul(g) assert g * g == g.sqr() assert g * g == g**Bn(2) assert g * g == g**2 assert g * g != g * g * g
def test_gt_multiplication(): g = GT.generator() assert not g == 5 assert g != 5 assert g * g == g * g assert g * g == g.square() assert g * g == g ** Bn(2) assert g * g == g ** 2 assert g * g * g == g ** 3 assert g * g != g * g * g
def bench_group(name, group): global grp, generator, scalars, points, points2 global input_strings, input_strings_long order = group.order() # Generate scalars and elements for benchmark grp = group generator = group.generator() scalars = [order.random() for _ in range(NR_ELEMS)] points = [order.random() * group.generator() for _ in range(NR_ELEMS)] points2 = [order.random() * group.generator() for _ in range(NR_ELEMS)] input_strings = [secrets.token_bytes(32) for _ in range(NR_ELEMS)] input_strings_long = [secrets.token_bytes(1024) for _ in range(NR_ELEMS)] print("\n") print_header("Group " + name) print_time("Square", "[p.double() for p in points]") print_time("Multiplication", "[p + q for p, q in zip(points, points2)]") print_time("Exponentiation (generator)", "[s * generator for s in scalars]") print_time("Exponentiation (point)", "[s * p for s, p in zip(scalars, points)]") for bits in [2**x for x in range(3, 9)]: scalars = [Bn.get_random(bits) for _ in range(NR_ELEMS)] print_time( " (scalar is {:>4} bits)".format(bits), "[s * p for s, p in zip(scalars, points)]", ) if name != "GT": print_time( "Hash to point (32 bytes input)", "[grp.hash_to_point(s) for s in input_strings]", ) print_time( "Hash to point (1024 bytes input)", "[grp.hash_to_point(s) for s in input_strings]", ) print_time("Export", "[p for p in points]") print_footer()
def test_ec_arithmetic(group): g = group.generator() assert g + g == g + g assert g + g == g.pt_double() assert g + g == Bn(2) * g assert g + g == 2 * g assert g + g != g + g + g assert g + (-g) == group.infinite() d = {} d[2 * g] = 2 assert d[2 * g] == 2 # Test long names assert (g + g).pt_eq(g + g) assert g + g == g.pt_add(g) assert -g == g.pt_neg() assert 10 * g == g.pt_mul(10) assert len(str(g)) > 0
def issue(sk, request, username, attributes): """Issues a credential for a new user. This function should receive a issuance request from the user (AnonCredential.create_issue_request), and a list of known attributes of the user (e.g. the server received bank notes for subscriptions x, y, and z). You should design the issue_request as you see fit. """ #extract public and secret key secret_key = sk[0] public_key = sk[1] #Derive challenge challenge = hashlib.sha256(jsonpickle.encode(request.C).encode()) challenge.update(jsonpickle.encode(request.commitment).encode()) challenge.update(jsonpickle.encode(public_key).encode()) challenge = Bn.from_binary(challenge.digest()) #Compare the derived challenge to the received challenge challenge_valid = challenge == request.challenge #Compute the zkp candidate = request.C ** challenge for e in zip(public_key, request.response): candidate = candidate * e[0] ** e[1] proof_valid = request.commitment == candidate #If the proof and the derived challenge is valid, sig the credential if proof_valid and challenge_valid: u = G1.order().random() sig = (public_key[0] ** u,(secret_key * request.C) ** u) return sig else : raise ValueError
def test_bn_pow(): assert Bn(2).pow(Bn(8)) == Bn(256) assert Bn(2).pow(8) == Bn(256)
def test_bn_abs(): assert abs(Bn(1)) == Bn(1) assert abs(Bn(-1)) == Bn(1) assert Bn(5).abs() == Bn(5) assert Bn(-5).abs() == Bn(5)
def _get_coords(self): x, y, z = Bn(), Bn(), Bn() _C.fp_prime_back(x.bn, self.pt[0].x) _C.fp_prime_back(y.bn, self.pt[0].y) _C.fp_prime_back(z.bn, self.pt[0].z) return (x, y, z)
def test_bn_arithmetic(): assert Bn(1) + Bn(1) == Bn(2) assert Bn(1).int_add(Bn(1)) == Bn(2) assert Bn(1) + 1 == Bn(2) # assert (1 + Bn(1) == Bn(2)) assert Bn(1) + Bn(-1) == Bn(0) assert Bn(10) + Bn(10) == Bn(20) assert Bn(-1) * Bn(-1) == Bn(1) assert Bn(-1).int_mul(Bn(-1)) == Bn(1) assert Bn(10) * Bn(10) == Bn(100) assert Bn(10) - Bn(10) == Bn(0) assert Bn(10) - Bn(100) == Bn(-90) assert Bn(10) + (-Bn(10)) == Bn(0) s = -Bn(100) assert Bn(10) + s == Bn(-90) assert Bn(10) - (-Bn(10)) == Bn(20) assert -Bn(-10) == 10 assert Bn(-10).int_neg() == 10 assert divmod(Bn(10), Bn(3)) == (Bn(3), Bn(1)) assert Bn(10).divmod(Bn(3)) == (Bn(3), Bn(1)) assert Bn(10) // Bn(3) == Bn(3) assert Bn(10).int_div(Bn(3)) == Bn(3) assert Bn(10) % Bn(3) == Bn(1) assert Bn(10).mod(Bn(3)) == Bn(1) assert Bn(2)**Bn(8) == Bn(2**8) assert pow(Bn(2), Bn(8), Bn(27)) == Bn(2**8 % 27) pow(Bn(10), Bn(10)).binary() with pytest.raises(Exception): pow(Bn(10), -1) assert pow(Bn(2), -1, 27) == 14 assert pow(Bn(2), 0, 27) == 1 assert pow(Bn(2), 8, 27) == 2**8 % 27 assert Bn(3).mod_inverse(16) == 11 with pytest.raises(Exception) as excinfo: Bn(3).mod_inverse(0) print("Got inverse") assert "No inverse" in str(excinfo.value) with pytest.raises(Exception) as excinfo: x = Bn(0).mod_inverse(Bn(13)) print("!!! Got inverse", x) assert "No inverse" in str(excinfo.value) # with pytest.raises(Exception) as excinfo: # x = Bn(0).mod_inverse(Bn(13)) # print("Got inverse", x) # assert 'No inverse' in str(excinfo.value) assert Bn(10).mod_add(10, 15) == (10 + 10) % 15 assert Bn(10).mod_sub(100, 15) == (10 - 100) % 15 assert Bn(10).mod_mul(10, 15) == (10 * 10) % 15 assert Bn(-1).bool()
def test_bn_constructors(): assert Bn.from_num(100) == 100 assert Bn.from_num(-100) == -100 assert Bn.from_num(Bn(100)) == 100 assert Bn.from_num(Bn(-100)) == -100 assert Bn.from_num("100") == NotImplemented assert Bn.from_decimal("100") == 100 assert Bn.from_decimal("-100") == -100 with pytest.raises(Exception): Bn.from_decimal("100ABC") with pytest.raises(Exception): Bn.from_hex("100ABCZ") assert Bn.from_hex(Bn(-100).hex()) == -100 assert Bn(15).hex() == Bn(15).hex() with pytest.raises(Exception) as excinfo: Bn(-100).binary() assert "negative" in str(excinfo.value) # assert Bn.from_binary(Bn(-100).binary()) == 100 assert Bn.from_binary(Bn(100).binary()) == Bn(100) assert Bn.from_binary(Bn(100).binary()) == 100 # assert Bn.from_binary(Bn(-100).binary()) != Bn(50) assert int(Bn(-100)) == -100 assert repr(Bn(5)) == Bn(5).repr() assert repr(Bn(5)) == Bn(5).repr() == "Bn(5)" assert range(10)[Bn(4)] == 4 d = {Bn(5): 5, Bn(6): 6} assert Bn(5) in d
def verify(cls, pk, messages, signature): m = Bn.from_binary(hashlib.sha256(messages).digest()) is_gen = signature[0] == G1.neutral_element() is_valid = signature[0].pair(pk[1] * pk[2] ** m) == signature[1].pair(pk[0]) return is_valid and not is_gen
def test_bn_large_integer(): num = 2**128 + 1 a = Bn(num) assert a.num_bits() == 129 assert a == Bn(2)**128 + 1
def restore(self, obj): return Bn.from_binary(base64.b64decode(obj["b64repr"]))
def test_bn_large_negative_integer(): num = -2**128 + 1 a = Bn(num) assert a.num_bits() == 128 assert a == -Bn(2)**128 + 1