making review changes #2

Open
idaapayo wants to merge 7 commits from Ida/pbkdf2 into master
9 changed files with 117 additions and 45 deletions

5
CHANGELOG Normal file
View File

@ -0,0 +1,5 @@
* 0.5.3
- Upgrade RLP to 3.0.0 (eliminates really annoying cytoolz warning on stdout)
---
changelog before 0.5.3 will be written later, sorry

View File

@ -28,7 +28,7 @@ hash_keywords = [
'pbkdf2' 'pbkdf2'
] ]
default_kdfparams = { default_scrypt_kdfparams = {
'dklen': 32, 'dklen': 32,
'n': 1 << 18, 'n': 1 << 18,
'p': 1, 'p': 1,
@ -36,7 +36,7 @@ default_kdfparams = {
'salt': os.urandom(32).hex(), 'salt': os.urandom(32).hex(),
} }
pbkdf2_kdfparams = { default_pbkdf2_kdfparams = {
'c': 100000, 'c': 100000,
'dklen': 32, 'dklen': 32,
'prf': 'sha256', 'prf': 'sha256',
@ -53,7 +53,7 @@ def to_mac(mac_key, ciphertext_bytes):
class Hashes: class Hashes:
@staticmethod @staticmethod
def from_scrypt(kdfparams=default_kdfparams, passphrase=''): def from_scrypt(kdfparams=default_scrypt_kdfparams, passphrase=''):
dklen = int(kdfparams['dklen']) dklen = int(kdfparams['dklen'])
n = int(kdfparams['n']) n = int(kdfparams['n'])
p = int(kdfparams['p']) p = int(kdfparams['p'])
@ -64,21 +64,17 @@ class Hashes:
dklen=dklen) dklen=dklen)
@staticmethod @staticmethod
def from_pbkdf2(kdfparams=pbkdf2_kdfparams, passphrase=''): def from_pbkdf2(kdfparams=default_pbkdf2_kdfparams, passphrase=''):
hashname = kdfparams['prf'] if kdfparams['prf'] == 'hmac-sha256':
pwd = passphrase.encode('utf-8') kdfparams['prf'].replace('hmac-sha256','sha256')
salt = bytes.fromhex(kdfparams['salt'])
itr = int(kdfparams['c'])
dklen = int(kdfparams['dklen'])
derived_key = hashlib.pbkdf2_hmac( derived_key = hashlib.pbkdf2_hmac(
hash_name=hashname, hash_name='sha256',
password=pwd, password=passphrase.encode('utf-8'),
salt=salt, salt=bytes.fromhex(kdfparams['salt']),
iterations=itr, iterations=int(kdfparams['c']),
dklen=dklen dklen=int(kdfparams['dklen'])
) )
return derived_key return derived_key
@ -101,12 +97,12 @@ class Ciphers:
return ciphertext return ciphertext
def to_dict(private_key_bytes, kdf :str, passphrase=''): def to_dict(private_key_bytes, kdf='scrypt', passphrase=''):
private_key = coincurve.PrivateKey(secret=private_key_bytes) private_key = coincurve.PrivateKey(secret=private_key_bytes)
if kdf == 'scrypt': if kdf == 'scrypt':
encryption_key = Hashes.from_scrypt(passphrase=passphrase) encryption_key = Hashes.from_scrypt(passphrase=passphrase)
kdfparams = default_kdfparams kdfparams = default_scrypt_kdfparams
elif kdf == 'pbkdf2': elif kdf == 'pbkdf2':
encryption_key = Hashes.from_pbkdf2(passphrase=passphrase) encryption_key = Hashes.from_pbkdf2(passphrase=passphrase)

View File

@ -16,10 +16,8 @@ from funga.eth.keystore.keyfile import (
from_file, from_file,
to_dict, to_dict,
) )
# from testkeyfile import (
# from_file,
# to_dict
# )
from funga.eth.encoding import ( from funga.eth.encoding import (
private_key_to_address, private_key_to_address,
private_key_from_bytes, private_key_from_bytes,
@ -81,7 +79,7 @@ def main():
else: else:
pk_bytes = os.urandom(32) pk_bytes = os.urandom(32)
pk = coincurve.PrivateKey(secret=pk_bytes) pk = coincurve.PrivateKey(secret=pk_bytes)
o = to_dict(pk_bytes, 'pbkdf2', passphrase) o = to_dict(pk_bytes, passphrase)
r = json.dumps(o) r = json.dumps(o)
print(r) print(r)

View File

@ -1,6 +1,7 @@
cryptography==3.2.1 cryptography==3.2.1
pysha3==1.0.2 pysha3==1.0.2
rlp==2.0.1 #rlp==2.0.1
rlp==3.0.0
json-rpc==1.13.0 json-rpc==1.13.0
confini~=0.5.1 confini~=0.5.1
coincurve==15.0.0 coincurve==15.0.0

View File

@ -33,7 +33,7 @@ f.close()
setup( setup(
name="funga-eth", name="funga-eth",
version="0.5.2", version="0.5.3",
description="Ethereum implementation of the funga keystore and signer", description="Ethereum implementation of the funga keystore and signer",
author="Louis Holbrook", author="Louis Holbrook",
author_email="dev@holbrook.no", author_email="dev@holbrook.no",

View File

@ -5,10 +5,18 @@ import os
# external imports # external imports
from hexathon import strip_0x from hexathon import strip_0x
from pathlib import Path
import sys
path_root = Path('/home/vincent/ida/grassroots/funga-eth/funga/eth/keystore')
sys.path.append(str(path_root))
print(sys.path)
# local imports # local imports
from funga.eth.signer import EIP155Signer from funga.eth.signer import EIP155Signer
from funga.eth.keystore.dict import DictKeystore from funga.eth.keystore.dict import DictKeystore
from funga.eth.cli.handle import SignRequestHandler from funga.eth.cli.handle import SignRequestHandler
from funga.eth.transaction import EIP155Transaction from funga.eth.transaction import EIP155Transaction
@ -18,30 +26,30 @@ logg = logging.getLogger()
script_dir = os.path.dirname(os.path.realpath(__file__)) script_dir = os.path.dirname(os.path.realpath(__file__))
data_dir = os.path.join(script_dir, 'testdata') data_dir = os.path.join(script_dir, 'testdata')
class TestCli(unittest.TestCase): class TestCli(unittest.TestCase):
def setUp(self): def setUp(self):
#pk = bytes.fromhex('5087503f0a9cc35b38665955eb830c63f778453dd11b8fa5bd04bc41fd2cc6d6') # pk = bytes.fromhex('5087503f0a9cc35b38665955eb830c63f778453dd11b8fa5bd04bc41fd2cc6d6')
#pk_getter = pkGetter(pk) # pk_getter = pkGetter(pk)
self.keystore = DictKeystore() self.keystore = DictKeystore()
SignRequestHandler.keystore = self.keystore SignRequestHandler.keystore = self.keystore
self.signer = EIP155Signer(self.keystore) self.signer = EIP155Signer(self.keystore)
SignRequestHandler.signer = self.signer SignRequestHandler.signer = self.signer
self.handler = SignRequestHandler() self.handler = SignRequestHandler()
def test_new_account(self): def test_new_account(self):
q = { q = {
'id': 0, 'id': 0,
'method': 'personal_newAccount', 'method': 'personal_newAccount',
'params': [''], 'params': [''],
} }
(rpc_id, result) = self.handler.process_input(q) (rpc_id, result) = self.handler.process_input(q)
self.assertTrue(self.keystore.get(result)) self.assertTrue(self.keystore.get(result))
def test_sign_tx(self): def test_sign_tx(self):
keystore_file = os.path.join(data_dir, 'UTC--2021-01-08T18-37-01.187235289Z--00a329c0648769a73afac7f9381e08fb43dbea72') keystore_file = os.path.join(data_dir,
'UTC--2021-01-08T18-37-01.187235289Z--00a329c0648769a73afac7f9381e08fb43dbea72')
sender = self.keystore.import_keystore_file(keystore_file) sender = self.keystore.import_keystore_file(keystore_file)
tx_hexs = { tx_hexs = {
'nonce': '0x', 'nonce': '0x',
@ -62,26 +70,31 @@ class TestCli(unittest.TestCase):
# eth_signTransaction wraps personal_signTransaction, so here we test both already # eth_signTransaction wraps personal_signTransaction, so here we test both already
q = { q = {
'id': 0, 'id': 0,
'method': 'eth_signTransaction', 'method': 'eth_signTransaction',
'params': [tx_s], 'params': [tx_s],
} }
(rpc_id, result) = self.handler.process_input(q) (rpc_id, result) = self.handler.process_input(q)
logg.debug('result {}'.format(result)) logg.debug('result {}'.format(result))
self.assertEqual(strip_0x(result), 'f86c2a8504a817c8008252089435353535353535353535353535353535353535358203e884deadbeef82466aa0b7c1bbf52f736ada30fe253c7484176f44d6fd097a9720dc85ae5bbc7f060e54a07afee2563b0cf6d00333df51cc62b0d13c63108b2bce54ce2ad24e26ce7b4f25') self.assertEqual(strip_0x(result),
'f86c2a8504a817c8008252089435353535353535353535353535353535353535358203e884deadbeef82466aa0b7c1bbf52f736ada30fe253c7484176f44d6fd097a9720dc85ae5bbc7f060e54a07afee2563b0cf6d00333df51cc62b0d13c63108b2bce54ce2ad24e26ce7b4f25')
def test_sign_msg(self): def test_sign_msg(self):
keystore_file = os.path.join(data_dir, 'UTC--2021-01-08T18-37-01.187235289Z--00a329c0648769a73afac7f9381e08fb43dbea72') keystore_file = os.path.join(data_dir,
'UTC--2021-01-08T18-37-01.187235289Z--00a329c0648769a73afac7f9381e08fb43dbea72')
sender = self.keystore.import_keystore_file(keystore_file) sender = self.keystore.import_keystore_file(keystore_file)
q = { q = {
'id': 0, 'id': 0,
'method': 'eth_sign', 'method': 'eth_sign',
'params': [sender, '0xdeadbeef'], 'params': [sender, '0xdeadbeef'],
} }
(rpc_id, result) = self.handler.process_input(q) (rpc_id, result) = self.handler.process_input(q)
logg.debug('result msg {}'.format(result)) logg.debug('result msg {}'.format(result))
self.assertEqual(strip_0x(result), '50320dda75190a121b7b5979de66edadafd02bdfbe4f6d49552e79c01410d2464aae35e385c0e5b61663ff7b44ef65fa0ac7ad8a57472cf405db399b9dba3e1600') self.assertEqual(strip_0x(result),
'50320dda75190a121b7b5979de66edadafd02bdfbe4f6d49552e79c01410d2464aae35e385c0e5b61663ff7b44ef65fa0ac7ad8a57472cf405db399b9dba3e1600')
if __name__ == '__main__': if __name__ == '__main__':

59
tests/test_pbkdf2.py Normal file
View File

@ -0,0 +1,59 @@
#!/usr/bin/python
# standard imports
import unittest
import logging
import base64
import os
# external imports
from hexathon import (
strip_0x,
add_0x,
)
# local imports
from funga.error import UnknownAccountError
from funga.eth.keystore.dict import DictKeystore
from funga.eth.signer import EIP155Signer
logging.basicConfig(level=logging.DEBUG)
logg = logging.getLogger()
script_dir = os.path.realpath(os.path.dirname(__file__))
class TestDict(unittest.TestCase):
address_hex = None
db = None
def setUp(self):
self.db = DictKeystore()
keystore_filepath = os.path.join(script_dir, 'testdata',
'UTC--2022-01-24T10-34-04Z--cc47ad90-71a0-7fbe-0224-63326e27263a')
address_hex = self.db.import_keystore_file(keystore_filepath, 'test')
self.address_hex = add_0x(address_hex)
def tearDown(self):
pass
def test_get_key(self):
logg.debug('getting {}'.format(strip_0x(self.address_hex)))
pk = self.db.get(strip_0x(self.address_hex), '')
self.assertEqual(self.address_hex.lower(), '0xb8df77e1b4fa142e83bf9706f66fd76ad2a564f8')
bogus_account = os.urandom(20).hex()
with self.assertRaises(UnknownAccountError):
self.db.get(bogus_account, '')
def test_sign_message(self):
s = EIP155Signer(self.db)
z = s.sign_ethereum_message(strip_0x(self.address_hex), b'foo')
logg.debug('zzz {}'.format(str(z)))
if __name__ == '__main__':
unittest.main()

View File

@ -0,0 +1 @@
{"id":"cc47ad90-71a0-7fbe-0224-63326e27263a","version":3,"crypto":{"cipher":"aes-128-ctr","cipherparams":{"iv":"7bff67c888a9878a88e8548a4598322d"},"ciphertext":"0cb0e3c69d224d0a645f2784b64f507e5aecdc7bb8a7ea31963d25e6b8020ccf","kdf":"pbkdf2","kdfparams":{"c":10240,"dklen":32,"prf":"hmac-sha256","salt":"02f8b51b07a66a357c2d812952e6bee70fccc2e6a55e7cbd5c22d97d32fa8873"},"mac":"bb45aaabdb9fbbbde89631444ac39f8d76107381f16591799664274fd5d8c5bb"},"address":"b8df77e1b4fa142e83bf9706f66fd76ad2a564f8","name":"","meta":"{}"}

View File

@ -1 +0,0 @@
{"address": "a1De08A738F0bD3B261dC41d7E2102599bf648CA", "version": 3, "crypto": {"cipher": "aes-128-ctr", "ciphertext": "2240149943557906e6ee9bcb864d6148dce0c0d8245d1da8d466dcb39edcde6a", "cipherparams": {"iv": "a0c366fdfe86f21a4168b4f12059e7fa"}, "kdf": "pbkdf2", "kdfparams": {"c": 100000, "dklen": 32, "prf": "sha256", "salt": "73cb66c8cf0e60e36f7ec835a057638a17ed315cebb3b691574c32cfed827b6f"}, "mac": "6760ad0841da7976a41f134e021be450baa453efdec8fe5ba7790cfa79d0c14b"}, "id": "22e597ea-777e-11ec-be42-a8a7956d3851"}