def genesis_commitments(wallets, blind): commitments = [] for pkh_b58, amount in wallets.items(): # Public key hash corresponding to this Tezos address. pkh = base58_decode(pkh_b58.encode('utf-8')) # The redemption code is unique to the public key hash and deterministically # constructed using a secret blinding value. secret = secret_code(pkh, blind) # The redemption code is used to blind the pkh blinded_pkh = blake2b(pkh, 20, key=secret).digest() commitment = { 'blinded_pkh': base58_encode(blinded_pkh, prefix=b'btz1').decode(), 'amount': amount } commitments.append(commitment) return commitments
def verify(self, signature: Union[str, bytes], message: Union[str, bytes]) -> None: """Verify signature, raise exception if it is not valid. :param message: sequance of bytes, raw format or hexadecimal notation :param signature: a signature in base58 encoding :raises: ValueError if signature is not valid """ encoded_signature = scrub_input(signature) encoded_message = scrub_input(message) if not self.public_point: raise ValueError("Cannot verify without a public key") if encoded_signature[:3] != b'sig': # not generic if self.curve != encoded_signature[:2]: # "sp", "p2" "ed" raise ValueError("Signature and public key curves mismatch.") decoded_signature = base58_decode(encoded_signature) # Ed25519 if self.curve == b"ed": digest = pysodium.crypto_generichash(encoded_message) try: pysodium.crypto_sign_verify_detached(decoded_signature, digest, self.public_point) except ValueError as exc: raise ValueError('Signature is invalid.') from exc # Secp256k1 elif self.curve == b"sp": pk = secp256k1.PublicKey(self.public_point, raw=True) sig = pk.ecdsa_deserialize_compact(decoded_signature) if not pk.ecdsa_verify(encoded_message, sig, digest=blake2b_32): raise ValueError('Signature is invalid.') # P256 elif self.curve == b"p2": pk = fastecdsa.encoding.sec1.SEC1Encoder.decode_public_key( self.public_point, curve=fastecdsa.curve.P256) r, s = bytes_to_int(decoded_signature[:32]), bytes_to_int( decoded_signature[32:]) if not fastecdsa.ecdsa.verify( sig=(r, s), msg=encoded_message, Q=pk, hashfunc=blake2b_32): raise ValueError('Signature is invalid.') else: raise Exception( f'Unknown elliptic curve {self.curve}') # type: ignore
def from_encoded_key(cls, key, passphrase=''): """ Creates a key object from a base58 encoded key. :param key: a public or secret key in base58 encoding :param passphrase: the passphrase used if the key provided is an encrypted private key """ key = scrub_input(key) curve = key[:2] # "sp", "p2" "ed" if curve not in [b'sp', b'p2', b'ed']: raise ValueError("Invalid prefix for a key encoding.") if not len(key) in [54, 55, 88, 98]: raise ValueError("Invalid length for a key encoding.") encrypted = (key[2:3] == b'e') public_or_secret = key[3:5] if encrypted else key[2:4] if public_or_secret not in [b'pk', b'sk']: raise Exception("Invalid prefix for a key encoding.") key = base58_decode(key) is_secret = (public_or_secret == b'sk') if not is_secret: return cls.from_public_point(key, curve) if encrypted: if not passphrase: raise ValueError( "Encrypted key provided without a passphrase.") if isinstance(passphrase, str): passphrase = passphrase.encode() assert isinstance( passphrase, bytes ), f'expected bytes or str, got {type(passphrase).__name__}' salt, encrypted_sk = key[:8], key[8:] encryption_key = hashlib.pbkdf2_hmac(hash_name="sha512", password=passphrase, salt=salt, iterations=32768, dklen=32) key = pysodium.crypto_secretbox_open(c=encrypted_sk, nonce=b'\000' * 24, k=encryption_key) del passphrase return cls.from_secret_exponent(key, curve)
def from_encoded_key( cls, key: Union[str, bytes], passphrase: PassphraseInput = None, ) -> 'Key': """Creates a key object from a base58 encoded key. :param key: a public or secret key in base58 encoding :param passphrase: the passphrase used if the key provided is an encrypted private key, if not set value from from PYTEZOS_PASSPHRASE env variable will be used or promted dynamically """ encoded_key = scrub_input(key) curve = encoded_key[:2] # "sp", "p2" "ed" if curve not in [b'sp', b'p2', b'ed']: raise ValueError("Invalid prefix for a key encoding.") if not len(encoded_key) in [54, 55, 88, 98]: raise ValueError("Invalid length for a key encoding.") encrypted = encoded_key[2:3] == b'e' public_or_secret = encoded_key[3:5] if encrypted else encoded_key[2:4] if public_or_secret not in [b'pk', b'sk']: raise Exception("Invalid prefix for a key encoding.") encoded_key = base58_decode(encoded_key) is_secret = public_or_secret == b'sk' if not is_secret: return cls.from_public_point(encoded_key, curve) if encrypted: passphrase = get_passphrase(passphrase) salt, encrypted_sk = encoded_key[:8], encoded_key[8:] encryption_key = hashlib.pbkdf2_hmac(hash_name="sha512", password=passphrase, salt=salt, iterations=32768, dklen=32) encoded_key = pysodium.crypto_secretbox_open( c=encrypted_sk, nonce=b'\000' * 24, k=encryption_key, ) del passphrase return cls.from_secret_exponent(encoded_key, curve)
def sign(self) -> 'OperationGroup': """Sign the operation group with the key specified by `using`. :rtype: OperationGroup """ validation_pass = validation_passes[self.contents[0]['kind']] if any(map(lambda x: validation_passes[x['kind']] != validation_pass, self.contents)): raise ValueError('Mixed validation passes') if validation_pass == 0: if self.chain_id is None: raise ValueError('Chain ID is undefined, run .fill first') watermark = b'\x02' + base58_decode(self.chain_id.encode()) else: watermark = b'\x03' message = watermark + bytes.fromhex(self.forge()) signature = self.key.sign(message=message, generic=True) return self._spawn(signature=signature)
def forge_base58(value: str) -> bytes: """ Encode base58 string into bytes. :param value: base58 encoded value (with checksum) """ return base58_decode(value.encode())
def watermark(self): """Chain watermark, hex encoded.""" data = self.chain_id() return hexlify(base58_decode(data.encode())).decode()
def get_originated_address(index: int, opg_hash=None): prefix = base58_decode(opg_hash) if opg_hash else b'\x00' * 32 nonce = prefix + index.to_bytes(4, 'big') nonce_hash = blake2b(data=nonce, digest_size=20).digest() return base58_encode(nonce_hash, b'KT1').decode()
def raw(self) -> bytes: return base58_decode(self.value.encode())
def test_b58_decode_encode(self, string, prefix): data = base58_decode(string) result = base58_encode(data, prefix) self.assertEqual(string, result)