Browse Source

minor fixes and cleanups

The MMGen Project 3 years ago
parent
commit
3510841a12
5 changed files with 28 additions and 27 deletions
  1. 8 14
      mmgen/base_proto/ethereum/misc.py
  2. 13 6
      mmgen/main_msg.py
  3. 6 6
      mmgen/msg.py
  4. 0 1
      mmgen/tool/coin.py
  5. 1 0
      test/test_py_d/ts_ethdev.py

+ 8 - 14
mmgen/base_proto/ethereum/misc.py

@@ -12,7 +12,7 @@
 base_proto.ethereum.misc: miscellaneous utilities for Ethereum base protocol
 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):
 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'] )
 		dklen    = sp['dklen'] )
 
 
 	# Check password by comparing generated MAC to stored MAC
 	# 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()
 	mac_chk = get_keccak()(hashed_pw[16:32] + bytes.fromhex( cdata['ciphertext'] )).digest().hex()
 	if mac_chk != cdata['mac']:
 	if mac_chk != cdata['mac']:
 		die(1,'Incorrect passphrase')
 		die(1,'Incorrect passphrase')
@@ -67,19 +66,19 @@ def extract_key_from_geth_keystore_wallet(wallet_fn,passwd,check_addr=True):
 
 
 	return key
 	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):
 def ec_sign_message_with_privkey(message,key):
 	"""
 	"""
 	Sign an arbitrary string with an Ethereum private key, returning the signature
 	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
 	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
 	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)
 	return '{:064x}{:064x}{:02x}'.format(r,s,v)
 
 
 def ec_recover_pubkey(message,sig):
 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
 	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
 	from py_ecc.secp256k1 import ecdsa_raw_recover
 	r,s,v = ( sig[:64], sig[64:128], sig[128:] )
 	r,s,v = ( sig[:64], sig[64:128], sig[128:] )
 	return '{:064x}{:064x}'.format(
 	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)) )
 	)
 	)

+ 13 - 6
mmgen/main_msg.py

@@ -81,14 +81,15 @@ opts_data = {
 		'usage2': [
 		'usage2': [
 			'[opts] create MESSAGE_TEXT ADDRESS_SPEC [...]',
 			'[opts] create MESSAGE_TEXT ADDRESS_SPEC [...]',
 			'[opts] sign   MESSAGE_FILE [WALLET_FILE ...]',
 			'[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': """
 		'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': """
 	'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’:
 Export data relevant for a third-party verifier to ‘signatures.json’:
 $ mmgen-msg export <signed message file>
 $ 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': {
 	'code': {

+ 6 - 6
mmgen/msg.py

@@ -171,10 +171,10 @@ class coin_msg:
 						yield res
 						yield res
 
 
 			hdr_data = {
 			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':
 			if req_addr or type(self).__name__ == 'exported_sigs':
@@ -332,8 +332,8 @@ class coin_msg:
 					desc   = self.desc )
 					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
 					if self.proto.base_proto == 'Ethereum' else
 				self.data['signatures']
 				self.data['signatures']
 			)}
 			)}

+ 0 - 1
mmgen/tool/coin.py

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

+ 1 - 0
test/test_py_d/ts_ethdev.py

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