def _create_v3_keyfile_json(hrp,private_key, password, kdf, work_factor=None, salt_size=16): salt = Random.get_random_bytes(salt_size) if work_factor is None: work_factor = get_default_work_factor_for_kdf(kdf) if kdf == 'pbkdf2': derived_key = _pbkdf2_hash( password, hash_name='sha256', salt=salt, iterations=work_factor, dklen=DKLEN, ) kdfparams = { 'c': work_factor, 'dklen': DKLEN, 'prf': 'hmac-sha256', 'salt': encode_hex_no_prefix(salt), } elif kdf == 'scrypt': derived_key = _scrypt_hash( password, salt=salt, buflen=DKLEN, r=SCRYPT_R, p=SCRYPT_P, n=work_factor, ) kdfparams = { 'dklen': DKLEN, 'n': work_factor, 'r': SCRYPT_R, 'p': SCRYPT_P, 'salt': encode_hex_no_prefix(salt), } else: raise NotImplementedError("KDF not implemented: {0}".format(kdf)) iv = big_endian_to_int(Random.get_random_bytes(16)) encrypt_key = derived_key[:16] ciphertext = encrypt_aes_ctr(private_key, encrypt_key, iv) mac = keccak(derived_key[16:32] + ciphertext) pub = keys.PrivateKey(private_key).public_key return { 'address': pub.to_bech32_address(hrp), 'crypto': { 'cipher': 'aes-128-ctr', 'cipherparams': { 'iv': encode_hex_no_prefix(int_to_big_endian(iv)), }, 'ciphertext': encode_hex_no_prefix(ciphertext), 'kdf': kdf, 'kdfparams': kdfparams, 'mac': encode_hex_no_prefix(mac), }, 'id': str(uuid.uuid4()), 'version': 3, }
def recover_from_msg(cls, message: bytes, signature: 'Signature', backend: 'BaseECCBackend' = None, ) -> 'PublicKey': message_hash = keccak(message) return cls.recover_from_msg_hash(message_hash, signature, backend)
def _decode_keyfile_json_v3(keyfile_json, password): crypto = keyfile_json['crypto'] kdf = crypto['kdf'] # Derive the encryption key from the password using the key derivation # function. if kdf == 'pbkdf2': derived_key = _derive_pbkdf_key(crypto, password) elif kdf == 'scrypt': derived_key = _derive_scrypt_key(crypto, password) else: raise TypeError("Unsupported key derivation function: {0}".format(kdf)) # Validate that the derived key matchs the provided MAC ciphertext = decode_hex(crypto['ciphertext']) mac = keccak(derived_key[16:32] + ciphertext) expected_mac = decode_hex(crypto['mac']) if not hmac.compare_digest(mac, expected_mac): raise ValueError("MAC mismatch") # Decrypt the ciphertext using the derived encryption key to get the # private key. encrypt_key = derived_key[:16] cipherparams = crypto['cipherparams'] iv = big_endian_to_int(decode_hex(cipherparams['iv'])) private_key = decrypt_aes_ctr(ciphertext, encrypt_key, iv) return private_key
def verify_msg( self, message: bytes, signature: 'Signature', ) -> bool: message_hash = keccak(message) return self.verify_msg_hash(message_hash, signature)
def create(self, extra_entropy='', net_type=MIANNETHRP, mode='ECDSA'): ''' Creates a new private key, and returns it as a :class:`~platon_account.local.LocalAccount`. :param extra_entropy: Add extra randomness to whatever randomness your OS can provide :type extra_entropy: str or bytes or int :returns: an object with private key and convenience methods .. code-block:: python >>> from client_sdk_python.packages.platon_account import Account >>> acct = Account.create('KEYSMASH FJAFJKLDSKF7JKFDJ 1530') >>> acct.address '0x5ce9454909639D2D17A3F753ce7d93fa0b9aB12E' >>> acct.privateKey b"\\xb2\\}\\xb3\\x1f\\xee\\xd9\\x12''\\xbf\\t9\\xdcv\\x9a\\x96VK-\\xe4\\xc4rm\\x03[6\\xec\\xf1\\xe5\\xb3d" # These methods are also available: signHash(), signTransaction(), encrypt() # They correspond to the same-named methods in Account.* # but without the private key argument ''' if mode == 'ECDSA': extra_key_bytes = text_if_str(to_bytes, extra_entropy) key_bytes = keccak(os.urandom(32) + extra_key_bytes) return self.privateKeyToAccount(key_bytes, net_type) elif mode == 'SM': key_bytes = func.random_hex( 64) #sm3.sm3_hash(func.bytes_to_list(os.urandom(32))) return self.privateKeyToAccount(key_bytes, net_type, 'SM')
def sha3(primitive=None, text=None, hexstr=None): if isinstance(primitive, (bytes, int, type(None))): input_bytes = to_bytes(primitive, hexstr=hexstr, text=text) return keccak(input_bytes) raise TypeError( "You called sha3 with first arg %r and keywords %r. You must call it with one of " "these approaches: sha3(text='txt'), sha3(hexstr='0x747874'), " "sha3(b'\\x74\\x78\\x74'), or sha3(0x747874)." % (primitive, { 'text': text, 'hexstr': hexstr }))
def recover_public_key_from_msg(self, message: bytes) -> PublicKey: message_hash = keccak(message) return self.recover_public_key_from_msg_hash(message_hash)
def verify_msg(self, message: bytes, public_key: PublicKey) -> bool: message_hash = keccak(message) return self.verify_msg_hash(message_hash, public_key)
def __hash__(self) -> int: return big_endian_to_int(keccak(self.to_bytes()))
def sign_msg_non_recoverable(self, message: bytes) -> 'NonRecoverableSignature': message_hash = keccak(message) return self.sign_msg_hash_non_recoverable(message_hash)
def sign_msg(self, message: bytes) -> 'Signature': message_hash = keccak(message) return self.sign_msg_hash(message_hash)
def signTransaction(self, transaction_dict, private_key, net_type=DEFAULTHRP): ''' Sign a transaction using a local private key. Produces signature details and the hex-encoded transaction suitable for broadcast using :meth:`w3.eth.sendRawTransaction() <web3.eth.Eth.sendRawTransaction>`. Create the transaction dict for a contract method with `my_contract.functions.my_function().buildTransaction() <http://web3py.readthedocs.io/en/latest/contracts.html#methods>`_ :param dict transaction_dict: the transaction with keys: nonce, chainId, to, data, value, gas, and gasPrice. :param private_key: the private key to sign the data with :type private_key: hex str, bytes, int or :class:`platon_keys.datatypes.PrivateKey` :returns: Various details about the signature - most importantly the fields: v, r, and s :rtype: AttributeDict .. code-block:: python >>> transaction = { # Note that the address must be in checksum format: 'to': '0xF0109fC8DF283027b6285cc889F5aA624EaC1F55', 'value': 1000000000, 'gas': 2000000, 'gasPrice': 234567897654321, 'nonce': 0, 'chainId': 1 } >>> key = '0x4c0883a69102937d6231471b5dbb6204fe5129617082792ae468d01a3f362318' >>> signed = Account.signTransaction(transaction, key) {'hash': HexBytes('0x6893a6ee8df79b0f5d64a180cd1ef35d030f3e296a5361cf04d02ce720d32ec5'), 'r': 4487286261793418179817841024889747115779324305375823110249149479905075174044, 'rawTransaction': HexBytes('0xf86a8086d55698372431831e848094f0109fc8df283027b6285cc889f5aa624eac1f55843b9aca008025a009ebb6ca057a0535d6186462bc0b465b561c94a295bdb0621fc19208ab149a9ca0440ffd775ce91a833ab410777204d5341a6f9fa91216a6f3ee2c051fea6a0428'), # noqa: E501 's': 30785525769477805655994251009256770582792548537338581640010273753578382951464, 'v': 37} >>> w3.eth.sendRawTransaction(signed.rawTransaction) ''' if not isinstance(transaction_dict, Mapping): raise TypeError("transaction_dict must be dict-like, got %r" % transaction_dict) account = self.privateKeyToAccount(private_key, net_type) # allow from field, *only* if it matches the private key if 'from' in transaction_dict: if transaction_dict['from'] == account.address: sanitized_transaction = dissoc(transaction_dict, 'from') else: raise TypeError( "from field must match key's %s, but it was %s" % ( account.address, transaction_dict['from'], )) else: sanitized_transaction = transaction_dict # sign transaction ( v, r, s, rlp_encoded, ) = sign_transaction_dict(account._key_obj, sanitized_transaction) transaction_hash = keccak(rlp_encoded) return AttributeDict({ 'rawTransaction': HexBytes(rlp_encoded), 'hash': HexBytes(transaction_hash), 'r': r, 's': s, 'v': v, })
def public_key_bytes_to_address(public_key_bytes: bytes) -> bytes: return keccak(public_key_bytes)[-20:]