Ejemplo n.º 1
0
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,
    }
Ejemplo n.º 2
0
 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)
Ejemplo n.º 3
0
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
Ejemplo n.º 4
0
 def verify_msg(
     self,
     message: bytes,
     signature: 'Signature',
 ) -> bool:
     message_hash = keccak(message)
     return self.verify_msg_hash(message_hash, signature)
Ejemplo n.º 5
0
    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')
Ejemplo n.º 6
0
    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
            }))
Ejemplo n.º 7
0
 def recover_public_key_from_msg(self, message: bytes) -> PublicKey:
     message_hash = keccak(message)
     return self.recover_public_key_from_msg_hash(message_hash)
Ejemplo n.º 8
0
 def verify_msg(self,
                message: bytes,
                public_key: PublicKey) -> bool:
     message_hash = keccak(message)
     return self.verify_msg_hash(message_hash, public_key)
Ejemplo n.º 9
0
 def __hash__(self) -> int:
     return big_endian_to_int(keccak(self.to_bytes()))
Ejemplo n.º 10
0
 def sign_msg_non_recoverable(self, message: bytes) -> 'NonRecoverableSignature':
     message_hash = keccak(message)
     return self.sign_msg_hash_non_recoverable(message_hash)
Ejemplo n.º 11
0
 def sign_msg(self, message: bytes) -> 'Signature':
     message_hash = keccak(message)
     return self.sign_msg_hash(message_hash)
Ejemplo n.º 12
0
    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,
        })
Ejemplo n.º 13
0
def public_key_bytes_to_address(public_key_bytes: bytes) -> bytes:
    return keccak(public_key_bytes)[-20:]