def get_pubkey_addresses(pubkey): """ Get the compressed and uncompressed addresses for a public key. Useful for verifying signatures by key address. If we're running in testnet mode, then use the testnet version byte. Return (compressed address, uncompressed address) """ version_byte = virtualchain.version_byte compressed_address, uncompressed_address = None, None pubkey = ECPublicKey(pubkey, version_byte=version_byte) pubkey_bin = pubkey.to_bin() if pubkey._type == PubkeyType.compressed: compressed_address = pubkey.address() uncompressed_address = decompress(pubkey_bin) hashed_address = bin_hash160(uncompressed_address) uncompressed_address = bin_hash160_to_address( hashed_address, version_byte=version_byte) elif pubkey._type == PubkeyType.uncompressed: uncompressed_address = pubkey.address() compressed_address = compress(pubkey_bin) hashed_address = bin_hash160(compressed_address) compressed_address = bin_hash160_to_address(hashed_address, version_byte=version_byte) else: raise Exception('Invalid public key') return compressed_address, uncompressed_address
def get_pubkey_addresses( pubkey ): """ Get the compressed and uncompressed addresses for a public key. Useful for verifying signatures by key address. Return (compressed address, uncompressed address) """ public_key_object = ECPublicKey(pubkey) compressed_address = None uncompressed_address = None if public_key_object._type == PubkeyType.compressed: compressed_address = public_key_object.address() uncompressed_address = bin_hash160_to_address( bin_hash160( decompress(public_key_object.to_bin()) ) ) elif public_key_object._type == PubkeyType.uncompressed: compressed_address = bin_hash160_to_address( bin_hash160( compress(public_key_object.to_bin()) ) ) uncompressed_address = public_key_object.address() else: raise Exception("Invalid public key") return (compressed_address, uncompressed_address)
class BitcoinCompressedPublicKeyTest(unittest.TestCase): def setUp(self): self.reference = { 'hex_public_key': '02068fd9d47283fb310e6dfb66b141dd78fbabc76d073d48cddc770ffb2bd262d7', 'bin_public_key': '\x02\x06\x8f\xd9\xd4r\x83\xfb1\x0em\xfbf\xb1A\xddx\xfb\xab\xc7m\x07=H\xcd\xdcw\x0f\xfb+\xd2b\xd7', 'hex_hash160': '25488b0d3bb770d6e0ef07e1f19d33ab59931dee', 'bin_hash160': '%H\x8b\r;\xb7p\xd6\xe0\xef\x07\xe1\xf1\x9d3\xabY\x93\x1d\xee', 'address': '14Q8uVAX29RUMvqPGXL5sg6NiwwMRFCm8C', } self.public_key = ECPublicKey(self.reference['hex_public_key']) def tearDown(self): pass def test_address(self): self.assertEqual(self.public_key.address(), self.reference['address']) def test_bin_hash160(self): self.assertEqual( self.public_key.bin_hash160(), self.reference['bin_hash160']) def test_hex_hash160(self): self.assertEqual( self.public_key.hash160(), self.reference['hex_hash160']) def test_bin_public_key(self): self.assertEqual( self.public_key.to_bin(), self.reference['bin_public_key']) def test_hex_public_key(self): self.assertEqual( self.public_key.to_hex(), self.reference['hex_public_key'])
class BitcoinCompressedPublicKeyTest(unittest.TestCase): def setUp(self): self.reference = { 'hex_public_key': '02068fd9d47283fb310e6dfb66b141dd78fbabc76d073d48cddc770ffb2bd262d7', 'bin_public_key': '\x02\x06\x8f\xd9\xd4r\x83\xfb1\x0em\xfbf\xb1A\xddx\xfb\xab\xc7m\x07=H\xcd\xdcw\x0f\xfb+\xd2b\xd7', 'hex_hash160': '25488b0d3bb770d6e0ef07e1f19d33ab59931dee', 'bin_hash160': '%H\x8b\r;\xb7p\xd6\xe0\xef\x07\xe1\xf1\x9d3\xabY\x93\x1d\xee', 'address': '14Q8uVAX29RUMvqPGXL5sg6NiwwMRFCm8C', } self.public_key = ECPublicKey(self.reference['hex_public_key']) def tearDown(self): pass def test_address(self): self.assertEqual(self.public_key.address(), self.reference['address']) def test_bin_hash160(self): self.assertEqual(self.public_key.bin_hash160(), self.reference['bin_hash160']) def test_hex_hash160(self): self.assertEqual(self.public_key.hash160(), self.reference['hex_hash160']) def test_bin_public_key(self): self.assertEqual(self.public_key.to_bin(), self.reference['bin_public_key']) def test_hex_public_key(self): self.assertEqual(self.public_key.to_hex(), self.reference['hex_public_key'])
class BitcoinUncompressedPublicKeyTest(unittest.TestCase): reference = _reference_info def setUp(self): self.public_key = ECPublicKey(self.reference['hex_public_key']) def tearDown(self): pass def test_address(self): self.assertEqual(self.public_key.address(), self.reference['address']) def test_hex_hash160(self): self.assertEqual( self.public_key.hash160(), self.reference['hex_hash160']) def test_hex_public_key(self): self.assertEqual( self.public_key.to_hex(), self.reference['hex_public_key']) def test_pem_public_key(self): self.assertEqual( self.public_key.to_pem(), self.reference['pem_public_key']) def test_der_public_key(self): self.assertEqual( self.public_key.to_der(), self.reference['der_public_key'])
class BitcoinUncompressedPublicKeyTest(unittest.TestCase): reference = _reference_info def setUp(self): self.public_key = ECPublicKey(self.reference['hex_public_key']) def tearDown(self): pass def test_address(self): self.assertEqual(self.public_key.address(), self.reference['address']) def test_hex_hash160(self): self.assertEqual(self.public_key.hash160(), self.reference['hex_hash160']) def test_hex_public_key(self): self.assertEqual(self.public_key.to_hex(), self.reference['hex_public_key']) def test_pem_public_key(self): self.assertEqual(self.public_key.to_pem(), self.reference['pem_public_key']) def test_der_public_key(self): self.assertEqual(self.public_key.to_der(), self.reference['der_public_key'])
def setUp(self): self.reference = { 'hex_public_key': '02068fd9d47283fb310e6dfb66b141dd78fbabc76d073d48cddc770ffb2bd262d7', 'bin_public_key': '\x02\x06\x8f\xd9\xd4r\x83\xfb1\x0em\xfbf\xb1A\xddx\xfb\xab\xc7m\x07=H\xcd\xdcw\x0f\xfb+\xd2b\xd7', 'hex_hash160': '25488b0d3bb770d6e0ef07e1f19d33ab59931dee', 'bin_hash160': '%H\x8b\r;\xb7p\xd6\xe0\xef\x07\xe1\xf1\x9d3\xabY\x93\x1d\xee', 'address': '14Q8uVAX29RUMvqPGXL5sg6NiwwMRFCm8C', } self.public_key = ECPublicKey(self.reference['hex_public_key'])
def secp256k1_compressed_pubkey_to_uncompressed_pubkey( pubkey ): """ convert a secp256k1 compressed public key into an uncompressed public key. taken from https://bitcointalk.org/index.php?topic=644919.msg7205689#msg7205689 """ pubk = ECPublicKey(pubkey).to_hex() assert len(pubk) == 66, "Not a compressed hex public key" def pow_mod(x, y, z): "Calculate (x ** y) % z efficiently." number = 1 while y: if y & 1: number = number * x % z y >>= 1 x = x * x % z return number p = ecdsa.SECP256k1.curve.p() b = ecdsa.SECP256k1.curve.b() y_parity = int(pubk[:2]) - 2 x = int(pubk[2:], 16) a = (pow_mod(x, 3, p) + b) % p y = pow_mod(a, (p+1)//4, p) if y % 2 != y_parity: y = -y % p uncompressed_pubk = '04{:x}{:x}'.format(x, y) return uncompressed_pubk
def load_verifying_key(verifying_key, crypto_backend=default_backend()): """ Optional: crypto backend object from the "cryptography" python library """ if isinstance(verifying_key, EllipticCurvePublicKey): return verifying_key elif isinstance(verifying_key, (str, unicode)): if is_hex(verifying_key): try: public_key_pem = ECPublicKey(verifying_key).to_pem() except: pass else: try: return load_pem_public_key(public_key_pem, backend=crypto_backend) except Exception as e: traceback.print_exc() raise InvalidPublicKeyError() try: return load_der_public_key(verifying_key, backend=crypto_backend) except: raise InvalidPublicKeyError() else: try: return load_pem_public_key(verifying_key, backend=crypto_backend) except Exception as e: raise InvalidPublicKeyError() else: raise ValueError('Verifying key must be in string or unicode format.')
def get_pubkey_addresses( pubkey ): """ Get the compressed and uncompressed addresses for a public key. Useful for verifying signatures by key address. If we're running in testnet mode, then use the testnet version byte. Return (compressed address, uncompressed address) """ public_key_object = ECPublicKey(pubkey, version_byte=virtualchain.version_byte) compressed_address = None uncompressed_address = None if public_key_object._type == PubkeyType.compressed: compressed_address = public_key_object.address() uncompressed_address = bin_hash160_to_address( bin_hash160( decompress(public_key_object.to_bin()) ), version_byte=virtualchain.version_byte ) elif public_key_object._type == PubkeyType.uncompressed: compressed_address = bin_hash160_to_address( bin_hash160( compress(public_key_object.to_bin()) ), version_byte=virtualchain.version_byte ) uncompressed_address = public_key_object.address() else: raise Exception("Invalid public key") return (compressed_address, uncompressed_address)
class BitcoinCompressedPublicKeyTest(unittest.TestCase): def setUp(self): self.ref = _compressed_info_2 self.public_key = ECPublicKey(self.ref['hex_public_key']) def tearDown(self): pass def test_address(self): self.assertEqual(self.public_key.address(), self.ref['address']) def test_bin_hash160(self): self.assertEqual(self.public_key.bin_hash160(), self.ref['bin_hash160']) def test_hex_hash160(self): self.assertEqual(self.public_key.hash160(), self.ref['hex_hash160']) def test_bin_public_key(self): self.assertEqual(self.public_key.to_bin(), self.ref['bin_public_key']) def test_hex_public_key(self): self.assertEqual(self.public_key.to_hex(), self.ref['hex_public_key'])
def verify_token(token, public_key_or_address, signing_algorithm="ES256K"): """ A function for validating an individual token. """ decoded_token = decode_token(token) decoded_token_payload = decoded_token["payload"] if "subject" not in decoded_token_payload: raise ValueError("Token doesn't have a subject") if "publicKey" not in decoded_token_payload["subject"]: raise ValueError("Token doesn't have a subject public key") if "issuer" not in decoded_token_payload: raise ValueError("Token doesn't have an issuer") if "publicKey" not in decoded_token_payload["issuer"]: raise ValueError("Token doesn't have an issuer public key") if "claim" not in decoded_token_payload: raise ValueError("Token doesn't have a claim") issuer_public_key = str(decoded_token_payload["issuer"]["publicKey"]) public_key_object = ECPublicKey(issuer_public_key) compressed_public_key = compress(issuer_public_key) decompressed_public_key = decompress(issuer_public_key) if public_key_object._type == PubkeyType.compressed: compressed_address = public_key_object.address() uncompressed_address = bin_hash160_to_address( bin_hash160( decompress(public_key_object.to_bin()) ) ) elif public_key_object._type == PubkeyType.uncompressed: compressed_address = bin_hash160_to_address( bin_hash160( compress(public_key_object.to_bin()) ) ) uncompressed_address = public_key_object.address() else: raise ValueError("Invalid issuer public key format") if public_key_or_address == compressed_public_key: pass elif public_key_or_address == decompressed_public_key: pass elif public_key_or_address == compressed_address: pass elif public_key_or_address == uncompressed_address: pass else: raise ValueError("Token public key doesn't match the verifying value") token_verifier = TokenVerifier() if not token_verifier.verify(token, public_key_object.to_pem()): raise ValueError("Token was not signed by the issuer public key") return decoded_token
def verify_token(token, public_key_or_address, signing_algorithm="ES256K"): """ A function for validating an individual token. """ decoded_token = decode_token(token) decoded_token_payload = decoded_token["payload"] if "subject" not in decoded_token_payload: raise ValueError("Token doesn't have a subject") if "publicKey" not in decoded_token_payload["subject"]: raise ValueError("Token doesn't have a subject public key") if "issuer" not in decoded_token_payload: raise ValueError("Token doesn't have an issuer") if "publicKey" not in decoded_token_payload["issuer"]: raise ValueError("Token doesn't have an issuer public key") if "claim" not in decoded_token_payload: raise ValueError("Token doesn't have a claim") issuer_public_key = str(decoded_token_payload["issuer"]["publicKey"]) public_key_object = ECPublicKey(issuer_public_key) compressed_public_key = compress(issuer_public_key) decompressed_public_key = decompress(issuer_public_key) if public_key_object._type == PubkeyType.compressed: compressed_address = public_key_object.address() uncompressed_address = bin_hash160_to_address( bin_hash160(decompress(public_key_object.to_bin()))) elif public_key_object._type == PubkeyType.uncompressed: compressed_address = bin_hash160_to_address( bin_hash160(compress(public_key_object.to_bin()))) uncompressed_address = public_key_object.address() else: raise ValueError("Invalid issuer public key format") if public_key_or_address == compressed_public_key: pass elif public_key_or_address == decompressed_public_key: pass elif public_key_or_address == compressed_address: pass elif public_key_or_address == uncompressed_address: pass else: raise ValueError("Token public key doesn't match the verifying value") token_verifier = TokenVerifier() if not token_verifier.verify(token, public_key_object.to_pem()): raise ValueError("Token was not signed by the issuer public key") return decoded_token
def verify_raw_data(raw_data, pubkey, sigb64): """ Verify the signature over a string, given the public key and base64-encode signature. Return True on success. Return False on error. """ data_hash = get_data_hash(raw_data) pubk = ECPublicKey(pubkey).to_hex() if len(pubk) == 66: pubk = secp256k1_compressed_pubkey_to_uncompressed_pubkey( pubkey ) sig_bin = base64.b64decode(sigb64) vk = ecdsa.VerifyingKey.from_string( pubk[2:].decode('hex'), curve=ecdsa.SECP256k1 ) return vk.verify_digest(sig_bin, data_hash.decode('hex'), sigdecode=ecdsa.util.sigdecode_der)
def test_create_pubkey_from_bin_compressed_format(self): public_key_string = '\x02\x06\x8f\xd9\xd4r\x83\xfb1\x0em\xfbf\xb1A\xddx\xfb\xab\xc7m\x07=H\xcd\xdcw\x0f\xfb+\xd2b\xd7' self.assertEqual(self.address_compressed, ECPublicKey(public_key_string).address())
def test_create_pubkey_from_hex_ecdsa_format(self): public_key_string = '068fd9d47283fb310e6dfb66b141dd78fbabc76d073d48cddc770ffb2bd262d7b2832f87f683100b89c2e95314deeeacbc6409af1e36c3ae3fd8c5f2f243cfec' self.assertEqual(self.address_uncompressed, ECPublicKey(public_key_string).address())
def setUp(self): self.ref = _compressed_info_2 self.public_key = ECPublicKey(self.ref['hex_public_key'])
def test_create_pubkey_from_bin_ecdsa_format(self): public_key_string = '\x06\x8f\xd9\xd4r\x83\xfb1\x0em\xfbf\xb1A\xddx\xfb\xab\xc7m\x07=H\xcd\xdcw\x0f\xfb+\xd2b\xd7\xb2\x83/\x87\xf6\x83\x10\x0b\x89\xc2\xe9S\x14\xde\xee\xac\xbcd\t\xaf\x1e6\xc3\xae?\xd8\xc5\xf2\xf2C\xcf\xec' self.assertEqual(self.address_uncompressed, ECPublicKey(public_key_string).address())
def setUp(self): self.public_key = ECPublicKey(self.ref['hex_public_key'])
def test_create_pubkey_from_bin_compressed_format(self): public_key_string = self.ref['bin_public_key_compressed'] self.assertEqual(self.address_compressed, ECPublicKey( public_key_string).address())
def test_create_pubkey_from_hex_ecdsa_format(self): public_key_string = self.ref['hex_public_key_raw_ecdsa'] self.assertEqual(self.address_uncompressed, ECPublicKey( public_key_string).address())
def test_create_pubkey_from_hex_compressed_format(self): public_key_string = '02068fd9d47283fb310e6dfb66b141dd78fbabc76d073d48cddc770ffb2bd262d7' self.assertEqual(self.address_compressed, ECPublicKey(public_key_string).address())