async def get_farmer(self, request_obj) -> web.Response: # TODO(pool): add rate limiting launcher_id = hexstr_to_bytes(request_obj.rel_url.query["launcher_id"]) authentication_token = uint64(request_obj.rel_url.query["authentication_token"]) authentication_token_error: Optional[web.Response] = check_authentication_token( launcher_id, authentication_token, self.pool.authentication_token_timeout ) if authentication_token_error is not None: return authentication_token_error farmer_record: Optional[FarmerRecord] = await self.pool.store.get_farmer_record(launcher_id) if farmer_record is None: return error_response( PoolErrorCode.FARMER_NOT_KNOWN, f"Farmer with launcher_id {launcher_id.hex()} unknown." ) # Validate provided signature signature: G2Element = G2Element.from_bytes(hexstr_to_bytes(request_obj.rel_url.query["signature"])) message = std_hash(launcher_id + bytes(authentication_token)) if not AugSchemeMPL.verify(farmer_record.authentication_public_key, message, signature): return error_response( PoolErrorCode.INVALID_SIGNATURE, f"Failed to verify signature {signature} for launcher_id {launcher_id.hex()}.", ) response: GetFarmerResponse = GetFarmerResponse( farmer_record.authentication_public_key, farmer_record.payout_instructions, farmer_record.difficulty, farmer_record.points, ) self.pool.log.info(f"get_farmer response {response.to_json_dict()}, " f"launcher_id: {launcher_id.hex()}") return obj_to_response(response)
def test_schemes(): # fmt: off seed = bytes([ 0, 50, 6, 244, 24, 199, 1, 25, 52, 88, 192, 19, 18, 12, 89, 6, 220, 18, 102, 58, 209, 82, 12, 62, 89, 110, 182, 9, 44, 20, 254, 22 ]) # fmt: on msg = bytes([100, 2, 254, 88, 90, 45, 23]) msg2 = bytes([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) sk = BasicSchemeMPL.key_gen(seed) pk = sk.get_g1() assert sk == PrivateKey.from_bytes(bytes(sk)) assert pk == G1Element.from_bytes(bytes(pk)) for Scheme in (BasicSchemeMPL, AugSchemeMPL, PopSchemeMPL): sig = Scheme.sign(sk, msg) assert sig == G2Element.from_bytes(bytes(sig)) assert Scheme.verify(pk, msg, sig) seed = bytes([1]) + seed[1:] sk1 = BasicSchemeMPL.key_gen(seed) pk1 = sk1.get_g1() seed = bytes([2]) + seed[1:] sk2 = BasicSchemeMPL.key_gen(seed) pk2 = sk2.get_g1() for Scheme in (BasicSchemeMPL, AugSchemeMPL, PopSchemeMPL): # Aggregate same message agg_pk = pk1 + pk2 if Scheme is AugSchemeMPL: sig1 = Scheme.sign(sk1, msg, agg_pk) sig2 = Scheme.sign(sk2, msg, agg_pk) else: sig1 = Scheme.sign(sk1, msg) sig2 = Scheme.sign(sk2, msg) agg_sig = Scheme.aggregate([sig1, sig2]) assert Scheme.verify(agg_pk, msg, agg_sig) # Aggregate different message sig1 = Scheme.sign(sk1, msg) sig2 = Scheme.sign(sk2, msg2) agg_sig = Scheme.aggregate([sig1, sig2]) assert Scheme.aggregate_verify([pk1, pk2], [msg, msg2], agg_sig) # HD keys child = Scheme.derive_child_sk(sk1, 123) childU = Scheme.derive_child_sk_unhardened(sk1, 123) childUPk = Scheme.derive_child_pk_unhardened(pk1, 123) sig_child = Scheme.sign(child, msg) assert Scheme.verify(child.get_g1(), msg, sig_child) sigU_child = Scheme.sign(childU, msg) assert Scheme.verify(childUPk, msg, sigU_child)
async def get_login(self, request_obj) -> web.Response: # TODO(pool): add rate limiting launcher_id: bytes32 = hexstr_to_bytes( request_obj.rel_url.query["launcher_id"]) authentication_token: uint64 = uint64( request_obj.rel_url.query["authentication_token"]) authentication_token_error = check_authentication_token( launcher_id, authentication_token, self.pool.authentication_token_timeout) if authentication_token_error is not None: return authentication_token_error farmer_record: Optional[ FarmerRecord] = await self.pool.store.get_farmer_record(launcher_id ) if farmer_record is None: return error_response( PoolErrorCode.FARMER_NOT_KNOWN, f"Farmer with launcher_id {launcher_id.hex()} unknown.") # Validate provided signature signature: G2Element = G2Element.from_bytes( hexstr_to_bytes(request_obj.rel_url.query["signature"])) message: bytes32 = std_hash( AuthenticationPayload("get_login", launcher_id, self.pool.default_target_puzzle_hash, authentication_token)) if not AugSchemeMPL.verify(farmer_record.authentication_public_key, message, signature): return error_response( PoolErrorCode.INVALID_SIGNATURE, f"Failed to verify signature {signature} for launcher_id {launcher_id.hex()}.", ) self.pool.log.info( f"Login successful for launcher_id: {launcher_id.hex()}") record: Optional[ FarmerRecord] = await self.pool.store.get_farmer_record(launcher_id ) response = {} if record is not None: response["farmer_record"] = record recent_partials = await self.pool.store.get_recent_partials( launcher_id, 20) response["recent_partials"] = recent_partials # TODO(pool) Do what ever you like with the successful login return obj_to_response(response)
def verify(args): if args.message is None: print("Please specify the message argument -d") quit() if args.public_key is None: print("Please specify the public_key argument -p") quit() if args.signature is None: print("Please specify the signature argument -s") quit() assert args.message is not None assert args.public_key is not None assert args.signature is not None message = bytes(args.message, "utf-8") public_key = G1Element.from_bytes(bytes.fromhex(args.public_key)) signature = G2Element.from_bytes(bytes.fromhex(args.signature)) print(AugSchemeMPL.verify(public_key, message, signature))
def batch_verification(): numIters = 100000 sig_bytes = [] pk_bytes = [] ms = [] for i in range(numIters): message = b"%d" % i sk: PrivateKey = AugSchemeMPL.key_gen(secrets.token_bytes(32)) pk: G1Element = sk.get_g1() sig: G2Element = AugSchemeMPL.sign(sk, message) sig_bytes.append(bytes(sig)) pk_bytes.append(bytes(pk)) ms.append(message) pks = [] start = startStopwatch(); for pk in pk_bytes: pks.append(G1Element.from_bytes(pk)) endStopwatch("Public key validation", start, numIters); sigs = [] start = startStopwatch() for sig in sig_bytes: sigs.append(G2Element.from_bytes(sig)) endStopwatch("Signature validation", start, numIters); start = startStopwatch() aggSig = AugSchemeMPL.aggregate(sigs) endStopwatch("Aggregation", start, numIters); start = startStopwatch() ok = AugSchemeMPL.aggregate_verify(pks, ms, aggSig); endStopwatch("Batch verification", start, numIters); if not ok: print("aggregate_verification failed!") sys.exit(1)
def verify(message: str, public_key: str, signature: str): messageBytes = bytes(message, "utf-8") public_key = G1Element.from_bytes(bytes.fromhex(public_key)) signature = G2Element.from_bytes(bytes.fromhex(signature)) print(AugSchemeMPL.verify(public_key, messageBytes, signature))
def test_readme(): seed: bytes = bytes([ 0, 50, 6, 244, 24, 199, 1, 25, 52, 88, 192, 19, 18, 12, 89, 6, 220, 18, 102, 58, 209, 82, 12, 62, 89, 110, 182, 9, 44, 20, 254, 22, ]) sk: PrivateKey = AugSchemeMPL.key_gen(seed) pk: G1Element = sk.get_g1() message: bytes = bytes([1, 2, 3, 4, 5]) signature: G2Element = AugSchemeMPL.sign(sk, message) ok: bool = AugSchemeMPL.verify(pk, message, signature) assert ok sk_bytes: bytes = bytes(sk) # 32 bytes pk_bytes: bytes = bytes(pk) # 48 bytes signature_bytes: bytes = bytes(signature) # 96 bytes print(sk_bytes.hex(), pk_bytes.hex(), signature_bytes.hex()) sk = PrivateKey.from_bytes(sk_bytes) pk = G1Element.from_bytes(pk_bytes) signature = G2Element.from_bytes(signature_bytes) seed = bytes([1]) + seed[1:] sk1: PrivateKey = AugSchemeMPL.key_gen(seed) seed = bytes([2]) + seed[1:] sk2: PrivateKey = AugSchemeMPL.key_gen(seed) message2: bytes = bytes([1, 2, 3, 4, 5, 6, 7]) pk1: G1Element = sk1.get_g1() sig1: G2Element = AugSchemeMPL.sign(sk1, message) pk2: G1Element = sk2.get_g1() sig2: G2Element = AugSchemeMPL.sign(sk2, message2) agg_sig: G2Element = AugSchemeMPL.aggregate([sig1, sig2]) ok = AugSchemeMPL.aggregate_verify([pk1, pk2], [message, message2], agg_sig) assert ok seed = bytes([3]) + seed[1:] sk3: PrivateKey = AugSchemeMPL.key_gen(seed) pk3: G1Element = sk3.get_g1() message3: bytes = bytes([100, 2, 254, 88, 90, 45, 23]) sig3: G2Element = AugSchemeMPL.sign(sk3, message3) agg_sig_final: G2Element = AugSchemeMPL.aggregate([agg_sig, sig3]) ok = AugSchemeMPL.aggregate_verify([pk1, pk2, pk3], [message, message2, message3], agg_sig_final) assert ok pop_sig1: G2Element = PopSchemeMPL.sign(sk1, message) pop_sig2: G2Element = PopSchemeMPL.sign(sk2, message) pop_sig3: G2Element = PopSchemeMPL.sign(sk3, message) pop1: G2Element = PopSchemeMPL.pop_prove(sk1) pop2: G2Element = PopSchemeMPL.pop_prove(sk2) pop3: G2Element = PopSchemeMPL.pop_prove(sk3) ok = PopSchemeMPL.pop_verify(pk1, pop1) assert ok ok = PopSchemeMPL.pop_verify(pk2, pop2) assert ok ok = PopSchemeMPL.pop_verify(pk3, pop3) assert ok pop_sig_agg: G2Element = PopSchemeMPL.aggregate( [pop_sig1, pop_sig2, pop_sig3]) ok = PopSchemeMPL.fast_aggregate_verify([pk1, pk2, pk3], message, pop_sig_agg) assert ok pop_agg_pk: G1Element = pk1 + pk2 + pk3 ok = PopSchemeMPL.verify(pop_agg_pk, message, pop_sig_agg) assert ok pop_agg_sk: PrivateKey = PrivateKey.aggregate([sk1, sk2, sk3]) ok = PopSchemeMPL.sign(pop_agg_sk, message) == pop_sig_agg assert ok master_sk: PrivateKey = AugSchemeMPL.key_gen(seed) child: PrivateKey = AugSchemeMPL.derive_child_sk(master_sk, 152) grandchild: PrivateKey = AugSchemeMPL.derive_child_sk(child, 952) master_pk: G1Element = master_sk.get_g1() child_u: PrivateKey = AugSchemeMPL.derive_child_sk_unhardened( master_sk, 22) grandchild_u: PrivateKey = AugSchemeMPL.derive_child_sk_unhardened( child_u, 0) child_u_pk: G1Element = AugSchemeMPL.derive_child_pk_unhardened( master_pk, 22) grandchild_u_pk: G1Element = AugSchemeMPL.derive_child_pk_unhardened( child_u_pk, 0) ok = grandchild_u_pk == grandchild_u.get_g1() assert ok
def signature_for_coinbase(coin: Coin, pool_private_key: PrivateKey): # noinspection PyTypeChecker return G2Element.from_bytes(bytes(AugSchemeMPL.sign(pool_private_key, bytes(coin))))
def test_schemes(): # fmt: off seed = bytes([ 0, 50, 6, 244, 24, 199, 1, 25, 52, 88, 192, 19, 18, 12, 89, 6, 220, 18, 102, 58, 209, 82, 12, 62, 89, 110, 182, 9, 44, 20, 254, 22 ]) # fmt: on msg = bytes([100, 2, 254, 88, 90, 45, 23]) msg2 = bytes([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) sk = BasicSchemeMPL.key_gen(seed) pk = sk.get_g1() assert sk == PrivateKey.from_bytes(bytes(sk)) assert pk == G1Element.from_bytes(bytes(pk)) for Scheme in (BasicSchemeMPL, AugSchemeMPL, PopSchemeMPL): sig = Scheme.sign(sk, msg) assert sig == G2Element.from_bytes(bytes(sig)) assert Scheme.verify(pk, msg, sig) seed = bytes([1]) + seed[1:] sk1 = BasicSchemeMPL.key_gen(seed) pk1 = sk1.get_g1() seed = bytes([2]) + seed[1:] sk2 = BasicSchemeMPL.key_gen(seed) pk2 = sk2.get_g1() for Scheme in (BasicSchemeMPL, AugSchemeMPL, PopSchemeMPL): # Aggregate same message agg_pk = pk1 + pk2 if Scheme is AugSchemeMPL: sig1 = Scheme.sign(sk1, msg, agg_pk) sig2 = Scheme.sign(sk2, msg, agg_pk) else: sig1 = Scheme.sign(sk1, msg) sig2 = Scheme.sign(sk2, msg) agg_sig = Scheme.aggregate([sig1, sig2]) assert Scheme.verify(agg_pk, msg, agg_sig) # Aggregate different message sig1 = Scheme.sign(sk1, msg) sig2 = Scheme.sign(sk2, msg2) agg_sig = Scheme.aggregate([sig1, sig2]) assert Scheme.aggregate_verify([pk1, pk2], [msg, msg2], agg_sig) # Manual pairing calculation and verification if Scheme is AugSchemeMPL: # AugSchemeMPL requires prepending the public key to message aug_msg1 = bytes(pk1) + msg aug_msg2 = bytes(pk2) + msg2 else: aug_msg1 = msg aug_msg2 = msg2 pair1 = pk1.pair(Scheme.g2_from_message(aug_msg1)) pair2 = pk2.pair(Scheme.g2_from_message(aug_msg2)) pair = pair1 * pair2 agg_sig_pair = G1Element.generator().pair(agg_sig) assert pair == agg_sig_pair # HD keys child = Scheme.derive_child_sk(sk1, 123) childU = Scheme.derive_child_sk_unhardened(sk1, 123) childUPk = Scheme.derive_child_pk_unhardened(pk1, 123) sig_child = Scheme.sign(child, msg) assert Scheme.verify(child.get_g1(), msg, sig_child) sigU_child = Scheme.sign(childU, msg) assert Scheme.verify(childUPk, msg, sigU_child)
def signature_for_coinbase(coin: Coin, pool_private_key: PrivateKey): return G2Element.from_bytes( bytes(AugSchemeMPL.sign(pool_private_key, bytes(coin))))