minor fixes and cleanups

This commit is contained in:
The MMGen Project 2022-04-29 16:53:51 +00:00
commit 3510841a12
Signed by: mmgen
GPG key ID: 3F8B1861E32B7DA2
5 changed files with 28 additions and 27 deletions

View file

@ -12,7 +12,7 @@
base_proto.ethereum.misc: miscellaneous utilities for Ethereum base protocol
"""
from ...util import die
from ...util import die,get_keccak
def extract_key_from_geth_keystore_wallet(wallet_fn,passwd,check_addr=True):
"""
@ -41,7 +41,6 @@ def extract_key_from_geth_keystore_wallet(wallet_fn,passwd,check_addr=True):
dklen = sp['dklen'] )
# Check password by comparing generated MAC to stored MAC
from ...util import get_keccak
mac_chk = get_keccak()(hashed_pw[16:32] + bytes.fromhex( cdata['ciphertext'] )).digest().hex()
if mac_chk != cdata['mac']:
die(1,'Incorrect passphrase')
@ -67,19 +66,19 @@ def extract_key_from_geth_keystore_wallet(wallet_fn,passwd,check_addr=True):
return key
def hash_message(message):
return get_keccak()(
'\x19Ethereum Signed Message:\n{}{}'.format( len(message), message ).encode()
).digest()
def ec_sign_message_with_privkey(message,key):
"""
Sign an arbitrary string with an Ethereum private key, returning the signature
Conforms to the standard defined by the Geth `eth_sign` JSON-RPC call
"""
from ...util import get_keccak
msghash = get_keccak()(
'\x19Ethereum Signed Message:\n{}{}'.format( len(message), message ).encode()
).digest()
from py_ecc.secp256k1 import ecdsa_raw_sign
v,r,s = ecdsa_raw_sign( msghash, key )
v,r,s = ecdsa_raw_sign( hash_message(message), key )
return '{:064x}{:064x}{:02x}'.format(r,s,v)
def ec_recover_pubkey(message,sig):
@ -89,13 +88,8 @@ def ec_recover_pubkey(message,sig):
Conforms to the standard defined by the Geth `eth_sign` JSON-RPC call
"""
from ...util import get_keccak
msghash = get_keccak()(
'\x19Ethereum Signed Message:\n{}{}'.format( len(message), message ).encode()
).digest()
from py_ecc.secp256k1 import ecdsa_raw_recover
r,s,v = ( sig[:64], sig[64:128], sig[128:] )
return '{:064x}{:064x}'.format(
*ecdsa_raw_recover( msghash, tuple(int(hexstr,16) for hexstr in (v,r,s)) )
*ecdsa_raw_recover( hash_message(message), tuple(int(hexstr,16) for hexstr in (v,r,s)) )
)

View file

@ -81,14 +81,15 @@ opts_data = {
'usage2': [
'[opts] create MESSAGE_TEXT ADDRESS_SPEC [...]',
'[opts] sign MESSAGE_FILE [WALLET_FILE ...]',
'[opts] verify MESSAGE_FILE or exported JSON dump',
'[opts] export MESSAGE_FILE',
'[opts] verify MESSAGE_FILE [MMGen ID]',
'[opts] verify <exported JSON dump file> [address]',
'[opts] export MESSAGE_FILE [MMGen ID]',
],
'options': """
-h, --help Print this help message
--, --longhelp Print help message for long options (common options)
-d, --outdir=d Output file to directory 'd' instead of working dir
-q, --quiet Produce quieter output
-h, --help Print this help message
--, --longhelp Print help message for long options (common options)
-d, --outdir=d Output file to directory 'd' instead of working dir
-q, --quiet Produce quieter output
""",
'notes': """
@ -168,6 +169,12 @@ $ mmgen-msg verify <signed message file> DEADBEEF:B:98
Export data relevant for a third-party verifier to signatures.json:
$ mmgen-msg export <signed message file>
Same as above, but export only one signature:
$ mmgen-msg export <signed message file> DEADBEEF:B:98
Verify and display the exported JSON signature data:
$ mmgen-msg verify signatures.json
"""
},
'code': {

View file

@ -171,10 +171,10 @@ class coin_msg:
yield res
hdr_data = {
'message': ('Message:', lambda v: grnbg(v) ),
'network': ('Network:', lambda v: v.replace('_',' ').upper() ),
'addrlists': ('Address Ranges:', lambda v: fmt_list(v,fmt='bare') ),
'failed_sids': ('Failed Seed IDs:', lambda v: red(fmt_list(v,fmt='bare')) ),
'message': ('Message:', lambda v: grnbg(v) ),
'network': ('Network:', lambda v: v.replace('_',' ').upper() ),
'addrlists': ('Address Ranges:', lambda v: fmt_list(v,fmt='bare') ),
'failed_sids': ('Failed Seed IDs:', lambda v: red(fmt_list(v,fmt='bare')) ),
}
if req_addr or type(self).__name__ == 'exported_sigs':
@ -332,8 +332,8 @@ class coin_msg:
desc = self.desc )
)
self.sigs = {sig['addr']:sig for sig in (
[{k:v[2:] for k,v in e.items()} for e in self.data['signatures']]
self.sigs = {sig_data['addr']:sig_data for sig_data in (
[{k:v[2:] for k,v in e.items()} for e in self.data['signatures']] # remove '0x' prefix
if self.proto.base_proto == 'Ethereum' else
self.data['signatures']
)}

View file

@ -168,7 +168,6 @@ class tool_cmd(tool_cmd_base):
def addr2pubhash(self,addr:'sstr'):
"convert coin address to public key hash"
from ..opts import opt
ap = self.proto.parse_addr(addr)
assert ap, f'coin address {addr!r} could not be parsed'
if ap.fmt not in MMGenAddrType.pkh_fmts:

View file

@ -691,6 +691,7 @@ class TestSuiteEthdev(TestSuiteBase,TestSuiteShared):
imsg(f'Message: {self.message}')
imsg(f'Signature: {sig}')
cmp_or_die(sig,sig_chk,'message signatures')
imsg('Geth and MMGen signatures match')
return 'ok'