def test_script(self): genesis_block = self.genesis_blocks[0] # random keys to be used random_priv = 'MIGEAgEAMBAGByqGSM49AgEGBSuBBAAKBG0wawIBAQQgMnAHVIyj7Hym2yI' \ 'w+JcKEfdCHByIp+FHfPoIkcnjqGyhRANCAATX76SGshGeoacUcZDhXEzERt' \ 'AHbd30CVpUg8RRnAIhaFcuMY3G+YFr/mReAPRuiLKCnolWz3kCltTtNj36rJyd' private_key_random = get_private_key_from_bytes( base64.b64decode(random_priv)) # create input data with incorrect private key _input = TxInput(genesis_block.hash, 0, b'') value = genesis_block.outputs[0].value address = get_address_from_public_key(self.genesis_public_key) script = P2PKH.create_output_script(address) output = TxOutput(value, script) tx = Transaction(inputs=[_input], outputs=[output], storage=self.tx_storage, timestamp=self.last_block.timestamp + 1) data_to_sign = tx.get_sighash_all() public_bytes, signature = self.wallet.get_input_aux_data( data_to_sign, private_key_random) data_wrong = P2PKH.create_input_data(public_bytes, signature) _input.data = data_wrong with self.assertRaises(InvalidInputData): tx.verify_inputs()
def main(): from hathor.cli.util import create_parser from hathor.crypto.util import get_private_key_from_bytes parser = create_parser() parser.add_argument('data', nargs='+', help='Encode data in oracle format.') parser.add_argument( '--keyfile', help='Path to a private key file, used to sign the data') args = parser.parse_args() binary_data = b'' for d in args.data: [t, _data] = d.split(':') if t == 'int': b = encode_int(_data) elif t == 'str': b = encode_str(_data) else: print('wrong data type {}'.format(d)) return 1 binary_data += (bytes([len(b)]) + b) print('data (base64):', base64.b64encode(binary_data).decode('utf-8')) with open(args.keyfile, 'r') as key_file: private_key_bytes = base64.b64decode(key_file.read()) private_key = get_private_key_from_bytes(private_key_bytes) signature = private_key.sign(binary_data, ec.ECDSA(hashes.SHA256())) print('signature (base64):', base64.b64encode(signature).decode('utf-8'))
def main(): from hathor.cli.util import create_parser from hathor.crypto.util import get_hash160, get_private_key_from_bytes, get_public_key_bytes_compressed parser = create_parser() parser.add_argument('filepath', help='Get public key hash given the private key file') args = parser.parse_args() with open(args.filepath, 'r') as key_file: private_key_bytes = base64.b64decode(key_file.read()) private_key = get_private_key_from_bytes(private_key_bytes) public_key_bytes = get_public_key_bytes_compressed( private_key.public_key()) print('base64:', base64.b64encode(public_key_bytes).decode('utf-8')) print('hash base64:', base64.b64encode(get_hash160(public_key_bytes)).decode('utf-8'))
def get_private_key(self, password: bytes) -> _EllipticCurvePrivateKey: """ :param password: password to decode private key :type password: bytes :return: Private key object. :rtype: :py:class:`cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKey` :raises WalletLocked: wallet password was not provided :raises IncorrectPassword: password provided cannot decrypt keys """ if not password: raise WalletLocked if self._cache_priv_key_unlock is None: try: assert self.private_key_bytes is not None self._cache_priv_key_unlock = get_private_key_from_bytes(self.private_key_bytes, password=password) except ValueError: raise IncorrectPassword return self._cache_priv_key_unlock
def generate_signature(tx: Transaction, private_key_bytes: bytes, password: Optional[bytes] = None) -> bytes: """ Create a signature for the tx :param tx: transaction with the data to be signed :type tx: :py:class:`hathor.transaction.transaction.Transaction` :param private_key_bytes: private key to generate the signature :type private_key_bytes: bytes :param password: password to decrypt the private key :type password: bytes :return: signature of the tx :rtype: bytes """ private_key = get_private_key_from_bytes(private_key_bytes, password=password) data_to_sign = tx.get_sighash_all() hashed_data = hashlib.sha256(data_to_sign).digest() signature = private_key.sign(hashed_data, ec.ECDSA(hashes.SHA256())) return signature
def test_spend_multisig(self): # Adding funds to the wallet blocks = add_new_blocks(self.manager, 2, advance_clock=15) add_blocks_unlock_reward(self.manager) self.assertEqual( self.manager.wallet.balance[settings.HATHOR_TOKEN_UID], WalletBalance(0, sum(blk.outputs[0].value for blk in blocks))) first_block_amount = blocks[0].outputs[0].value # First we send tokens to a multisig address outputs = [ WalletOutputInfo(address=self.multisig_address, value=first_block_amount, timelock=int(self.clock.seconds()) + 15) ] tx1 = self.manager.wallet.prepare_transaction_compute_inputs( Transaction, outputs) tx1.weight = 10 tx1.parents = self.manager.get_new_tx_parents() tx1.timestamp = int(self.clock.seconds()) tx1.resolve() self.manager.propagate_tx(tx1) self.clock.advance(10) self.assertEqual( self.manager.wallet.balance[settings.HATHOR_TOKEN_UID], WalletBalance(0, first_block_amount)) # Then we create a new tx that spends this tokens from multisig wallet tx = Transaction.create_from_struct(tx1.get_struct()) tx.weight = 10 tx.parents = self.manager.get_new_tx_parents() tx.timestamp = int(self.clock.seconds()) multisig_script = create_output_script(self.multisig_address) multisig_output = TxOutput(200, multisig_script) wallet_output = TxOutput(300, create_output_script(self.address)) outside_output = TxOutput(first_block_amount - 200 - 300, create_output_script(self.outside_address)) tx.outputs = [multisig_output, wallet_output, outside_output] tx_input = TxInput(tx1.hash, 0, b'') tx.inputs = [tx_input] signatures = [] for private_key_hex in self.private_keys: signature = generate_signature(tx, bytes.fromhex(private_key_hex), password=b'1234') signatures.append(signature) input_data = MultiSig.create_input_data(self.redeem_script, signatures) tx.inputs[0].data = input_data tx.resolve() # Transaction is still locked self.assertFalse(self.manager.propagate_tx(tx)) self.clock.advance(6) tx.timestamp = int(self.clock.seconds()) tx.resolve() # First we try to propagate with a P2PKH input private_key_obj = get_private_key_from_bytes(bytes.fromhex( self.private_keys[0]), password=b'1234') pubkey_obj = private_key_obj.public_key() public_key_compressed = get_public_key_bytes_compressed(pubkey_obj) p2pkh_input_data = P2PKH.create_input_data(public_key_compressed, signatures[0]) tx2 = Transaction.create_from_struct(tx.get_struct()) tx2.inputs[0].data = p2pkh_input_data tx2.resolve() self.assertFalse(self.manager.propagate_tx(tx2)) # Now we propagate the correct self.assertTrue(self.manager.propagate_tx(tx)) self.assertEqual( self.manager.wallet.balance[settings.HATHOR_TOKEN_UID], WalletBalance(0, first_block_amount + 300)) # Testing the MultiSig class methods cls_script = parse_address_script(multisig_script) self.assertTrue(isinstance(cls_script, MultiSig)) self.assertEqual(cls_script.address, self.multisig_address_b58) expected_dict = { 'type': 'MultiSig', 'address': self.multisig_address_b58, 'timelock': None } self.assertEqual(cls_script.to_human_readable(), expected_dict) script_eval(tx, tx_input, tx1) # Script error with self.assertRaises(ScriptError): create_output_script( base58.b58decode('55d14K5jMqsN2uwUEFqiPG5SoD7Vr1BfnH'))
def get_genesis_key(): private_key_bytes = base64.b64decode( 'MIGEAgEAMBAGByqGSM49AgEGBSuBBAAKBG0wawIBAQQgOCgCddzDZsfKgiMJLOt97eov9RLwHeePyBIK2WPF8MChRA' 'NCAAQ/XSOK+qniIY0F3X+lDrb55VQx5jWeBLhhzZnH6IzGVTtlAj9Ki73DVBm5+VXK400Idd6ddzS7FahBYYC7IaTl' ) return get_private_key_from_bytes(private_key_bytes)
def test_privkey_serialization(self): private_key_bytes = get_private_key_bytes(self.private_key) self.assertEqual( self.private_key.private_numbers(), get_private_key_from_bytes(private_key_bytes).private_numbers())