Moved decodeWalletImportFormat() from shared to highlevelcrypto,

not addresses, where it's supposed to be because it uses
pyelliptic.arithmetic, addresses.decodeBase58() returns int which needs
to be encoded. Defined encodeWalletImportFormat() and replaced all uses.
This commit is contained in:
Dmitri Bogomolov 2021-08-06 15:44:35 +03:00 committed by Lee Miller
parent 17a09a665b
commit c1ca7044d2
Signed by untrusted user: lee.miller
GPG Key ID: 4F97A5EA88F4AB63
4 changed files with 107 additions and 118 deletions

View File

@ -16,7 +16,6 @@ from addresses import decodeAddress, encodeAddress, encodeVarint
from bmconfigparser import config from bmconfigparser import config
from fallback import RIPEMD160Hash from fallback import RIPEMD160Hash
from network import StoppableThread from network import StoppableThread
from pyelliptic import arithmetic
from pyelliptic.openssl import OpenSSL from pyelliptic.openssl import OpenSSL
from tr import _translate from tr import _translate
@ -164,20 +163,10 @@ class addressGenerator(StoppableThread):
address = encodeAddress( address = encodeAddress(
addressVersionNumber, streamNumber, ripe) addressVersionNumber, streamNumber, ripe)
# An excellent way for us to store our keys privSigningKeyWIF = highlevelcrypto.encodeWalletImportFormat(
# is in Wallet Import Format. Let us convert now. potentialPrivSigningKey)
# https://en.bitcoin.it/wiki/Wallet_import_format privEncryptionKeyWIF = highlevelcrypto.encodeWalletImportFormat(
privSigningKey = b'\x80' + potentialPrivSigningKey potentialPrivEncryptionKey)
checksum = hashlib.sha256(hashlib.sha256(
privSigningKey).digest()).digest()[0:4]
privSigningKeyWIF = arithmetic.changebase(
privSigningKey + checksum, 256, 58)
privEncryptionKey = b'\x80' + potentialPrivEncryptionKey
checksum = hashlib.sha256(hashlib.sha256(
privEncryptionKey).digest()).digest()[0:4]
privEncryptionKeyWIF = arithmetic.changebase(
privEncryptionKey + checksum, 256, 58)
config.add_section(address) config.add_section(address)
config.set(address, 'label', label) config.set(address, 'label', label)
@ -303,21 +292,12 @@ class addressGenerator(StoppableThread):
saveAddressToDisk = False saveAddressToDisk = False
if saveAddressToDisk and live: if saveAddressToDisk and live:
# An excellent way for us to store our keys is privSigningKeyWIF = \
# in Wallet Import Format. Let us convert now. highlevelcrypto.encodeWalletImportFormat(
# https://en.bitcoin.it/wiki/Wallet_import_format potentialPrivSigningKey)
privSigningKey = b'\x80' + potentialPrivSigningKey privEncryptionKeyWIF = \
checksum = hashlib.sha256(hashlib.sha256( highlevelcrypto.encodeWalletImportFormat(
privSigningKey).digest()).digest()[0:4] potentialPrivEncryptionKey)
privSigningKeyWIF = arithmetic.changebase(
privSigningKey + checksum, 256, 58)
privEncryptionKey = b'\x80' + \
potentialPrivEncryptionKey
checksum = hashlib.sha256(hashlib.sha256(
privEncryptionKey).digest()).digest()[0:4]
privEncryptionKeyWIF = arithmetic.changebase(
privEncryptionKey + checksum, 256, 58)
try: try:
config.add_section(address) config.add_section(address)

View File

@ -197,15 +197,18 @@ class singleWorker(StoppableThread):
self.logger.info("Quitting...") self.logger.info("Quitting...")
def _getKeysForAddress(self, address): def _getKeysForAddress(self, address):
privSigningKeyBase58 = config.get( try:
address, 'privsigningkey') privSigningKeyBase58 = config.get(address, 'privsigningkey')
privEncryptionKeyBase58 = config.get( privEncryptionKeyBase58 = config.get(address, 'privencryptionkey')
address, 'privencryptionkey') except (configparser.NoSectionError, configparser.NoOptionError):
self.logger.error(
'Could not read or decode privkey for address %s', address)
raise ValueError
privSigningKeyHex = hexlify(shared.decodeWalletImportFormat( privSigningKeyHex = hexlify(
privSigningKeyBase58)) highlevelcrypto.decodeWalletImportFormat(privSigningKeyBase58))
privEncryptionKeyHex = hexlify(shared.decodeWalletImportFormat( privEncryptionKeyHex = hexlify(
privEncryptionKeyBase58)) highlevelcrypto.decodeWalletImportFormat(privEncryptionKeyBase58))
# The \x04 on the beginning of the public keys are not sent. # The \x04 on the beginning of the public keys are not sent.
# This way there is only one acceptable way to encode # This way there is only one acceptable way to encode
@ -256,9 +259,7 @@ class singleWorker(StoppableThread):
message once it is done with the POW""" message once it is done with the POW"""
# Look up my stream number based on my address hash # Look up my stream number based on my address hash
myAddress = shared.myAddressesByHash[adressHash] myAddress = shared.myAddressesByHash[adressHash]
# status addressVersionNumber, streamNumber = decodeAddress(myAddress)[1:3]
_, addressVersionNumber, streamNumber, adressHash = (
decodeAddress(myAddress))
# 28 days from now plus or minus five minutes # 28 days from now plus or minus five minutes
TTL = int(28 * 24 * 60 * 60 + helper_random.randomrandrange(-300, 300)) TTL = int(28 * 24 * 60 * 60 + helper_random.randomrandrange(-300, 300))
@ -271,17 +272,15 @@ class singleWorker(StoppableThread):
payload += protocol.getBitfield(myAddress) payload += protocol.getBitfield(myAddress)
try: try:
# privSigningKeyHex, privEncryptionKeyHex pubSigningKey, pubEncryptionKey = self._getKeysForAddress(
_, _, pubSigningKey, pubEncryptionKey = \ myAddress)[2:]
self._getKeysForAddress(myAddress) except ValueError:
except (configparser.NoSectionError, configparser.NoOptionError) as err: return
self.logger.warning("Section or Option did not found: %s", err) except Exception: # pylint:disable=broad-exception-caught
except Exception as err:
self.logger.error( self.logger.error(
'Error within doPOWForMyV2Pubkey. Could not read' 'Error within doPOWForMyV2Pubkey. Could not read'
' the keys from the keys.dat file for a requested' ' the keys from the keys.dat file for a requested'
' address. %s\n', err ' address. %s\n', exc_info=True)
)
return return
payload += pubSigningKey + pubEncryptionKey payload += pubSigningKey + pubEncryptionKey
@ -320,8 +319,8 @@ class singleWorker(StoppableThread):
try: try:
myAddress = shared.myAddressesByHash[adressHash] myAddress = shared.myAddressesByHash[adressHash]
except KeyError: except KeyError:
# The address has been deleted. self.logger.warning( # The address has been deleted.
self.logger.warning("Can't find %s in myAddressByHash", hexlify(adressHash)) "Can't find %s in myAddressByHash", hexlify(adressHash))
return return
if config.safeGetBoolean(myAddress, 'chan'): if config.safeGetBoolean(myAddress, 'chan'):
self.logger.info('This is a chan address. Not sending pubkey.') self.logger.info('This is a chan address. Not sending pubkey.')
@ -353,14 +352,13 @@ class singleWorker(StoppableThread):
# , privEncryptionKeyHex # , privEncryptionKeyHex
privSigningKeyHex, _, pubSigningKey, pubEncryptionKey = \ privSigningKeyHex, _, pubSigningKey, pubEncryptionKey = \
self._getKeysForAddress(myAddress) self._getKeysForAddress(myAddress)
except (configparser.NoSectionError, configparser.NoOptionError) as err: except ValueError:
self.logger.warning("Section or Option did not found: %s", err) return
except Exception as err: except Exception: # pylint:disable=broad-exception-caught
self.logger.error( self.logger.error(
'Error within sendOutOrStoreMyV3Pubkey. Could not read' 'Error within sendOutOrStoreMyV3Pubkey. Could not read'
' the keys from the keys.dat file for a requested' ' the keys from the keys.dat file for a requested'
' address. %s\n', err ' address. %s\n', exc_info=True)
)
return return
payload += pubSigningKey + pubEncryptionKey payload += pubSigningKey + pubEncryptionKey
@ -428,14 +426,13 @@ class singleWorker(StoppableThread):
# , privEncryptionKeyHex # , privEncryptionKeyHex
privSigningKeyHex, _, pubSigningKey, pubEncryptionKey = \ privSigningKeyHex, _, pubSigningKey, pubEncryptionKey = \
self._getKeysForAddress(myAddress) self._getKeysForAddress(myAddress)
except (configparser.NoSectionError, configparser.NoOptionError) as err: except ValueError:
self.logger.warning("Section or Option did not found: %s", err) return
except Exception as err: except Exception: # pylint:disable=broad-exception-caught
self.logger.error( self.logger.error(
'Error within sendOutOrStoreMyV4Pubkey. Could not read' 'Error within sendOutOrStoreMyV4Pubkey. Could not read'
' the keys from the keys.dat file for a requested' ' the keys from the keys.dat file for a requested'
' address. %s\n', err ' address. %s\n', exc_info=True)
)
return return
dataToEncrypt += pubSigningKey + pubEncryptionKey dataToEncrypt += pubSigningKey + pubEncryptionKey
@ -1118,8 +1115,9 @@ class singleWorker(StoppableThread):
' from the keys.dat file for our own address. %s\n', ' from the keys.dat file for our own address. %s\n',
err) err)
continue continue
privEncryptionKeyHex = hexlify(shared.decodeWalletImportFormat( privEncryptionKeyHex = hexlify(
privEncryptionKeyBase58)) highlevelcrypto.decodeWalletImportFormat(
privEncryptionKeyBase58))
pubEncryptionKeyBase256 = unhexlify(highlevelcrypto.privToPub( pubEncryptionKeyBase256 = unhexlify(highlevelcrypto.privToPub(
privEncryptionKeyHex))[1:] privEncryptionKeyHex))[1:]
requiredAverageProofOfWorkNonceTrialsPerByte = \ requiredAverageProofOfWorkNonceTrialsPerByte = \

View File

@ -7,6 +7,7 @@ High level cryptographic functions based on `.pyelliptic` OpenSSL bindings.
`More discussion. <https://github.com/yann2192/pyelliptic/issues/32>`_ `More discussion. <https://github.com/yann2192/pyelliptic/issues/32>`_
""" """
import hashlib
from binascii import hexlify from binascii import hexlify
import pyelliptic import pyelliptic
@ -14,7 +15,38 @@ from pyelliptic import OpenSSL
from pyelliptic import arithmetic as a from pyelliptic import arithmetic as a
__all__ = ['encrypt', 'makeCryptor', 'pointMult', 'privToPub', 'sign', 'verify'] __all__ = [
'decodeWalletImportFormat', 'encodeWalletImportFormat',
'encrypt', 'makeCryptor', 'pointMult', 'privToPub', 'sign', 'verify']
# WIF (uses arithmetic ):
def decodeWalletImportFormat(WIFstring):
"""
Convert private key from base58 that's used in the config file to
8-bit binary string.
"""
fullString = a.changebase(WIFstring, 58, 256)
privkey = fullString[:-4]
if fullString[-4:] != \
hashlib.sha256(hashlib.sha256(privkey).digest()).digest()[:4]:
raise ValueError('Checksum failed')
elif privkey[0:1] == b'\x80': # checksum passed
return privkey[1:]
raise ValueError('No hex 80 prefix')
# An excellent way for us to store our keys
# is in Wallet Import Format. Let us convert now.
# https://en.bitcoin.it/wiki/Wallet_import_format
def encodeWalletImportFormat(privKey):
"""
Convert private key from binary 8-bit string into base58check WIF string.
"""
privKey = b'\x80' + privKey
checksum = hashlib.sha256(hashlib.sha256(privKey).digest()).digest()[0:4]
return a.changebase(privKey + checksum, 256, 58)
def makeCryptor(privkey, curve='secp256k1'): def makeCryptor(privkey, curve='secp256k1'):

View File

@ -23,8 +23,6 @@ from bmconfigparser import config
from debug import logger from debug import logger
from helper_sql import sqlQuery from helper_sql import sqlQuery
from pyelliptic import arithmetic
myECCryptorObjects = {} myECCryptorObjects = {}
MyECSubscriptionCryptorObjects = {} MyECSubscriptionCryptorObjects = {}
@ -76,35 +74,6 @@ def isAddressInMyAddressBookSubscriptionsListOrWhitelist(address):
return False return False
def decodeWalletImportFormat(WIFstring):
# pylint: disable=inconsistent-return-statements
"""
Convert private key from base58 that's used in the config file to
8-bit binary string
"""
fullString = arithmetic.changebase(WIFstring, 58, 256)
privkey = fullString[:-4]
if fullString[-4:] != \
hashlib.sha256(hashlib.sha256(privkey).digest()).digest()[:4]:
logger.critical(
'Major problem! When trying to decode one of your'
' private keys, the checksum failed. Here are the first'
' 6 characters of the PRIVATE key: %s',
str(WIFstring)[:6]
)
os._exit(0) # pylint: disable=protected-access
# return ""
elif privkey[0] == '\x80': # checksum passed
return privkey[1:]
logger.critical(
'Major problem! When trying to decode one of your private keys,'
' the checksum passed but the key doesn\'t begin with hex 80.'
' Here is the PRIVATE key: %s', WIFstring
)
os._exit(0) # pylint: disable=protected-access
def reloadMyAddressHashes(): def reloadMyAddressHashes():
"""Reload keys for user's addresses from the config file""" """Reload keys for user's addresses from the config file"""
logger.debug('reloading keys from keys.dat file') logger.debug('reloading keys from keys.dat file')
@ -118,29 +87,39 @@ def reloadMyAddressHashes():
hasEnabledKeys = False hasEnabledKeys = False
for addressInKeysFile in config.addresses(): for addressInKeysFile in config.addresses():
isEnabled = config.getboolean(addressInKeysFile, 'enabled') isEnabled = config.getboolean(addressInKeysFile, 'enabled')
if isEnabled: if not isEnabled:
hasEnabledKeys = True continue
# status
addressVersionNumber, streamNumber, hashobj = decodeAddress(addressInKeysFile)[1:] hasEnabledKeys = True
if addressVersionNumber in (2, 3, 4):
# Returns a simple 32 bytes of information encoded addressVersionNumber, streamNumber, hashobj = decodeAddress(
# in 64 Hex characters, or null if there was an error. addressInKeysFile)[1:]
privEncryptionKey = hexlify(decodeWalletImportFormat( if addressVersionNumber not in (2, 3, 4):
config.get(addressInKeysFile, 'privencryptionkey'))) logger.error(
# It is 32 bytes encoded as 64 hex characters 'Error in reloadMyAddressHashes: Can\'t handle'
if len(privEncryptionKey) == 64: ' address versions other than 2, 3, or 4.')
myECCryptorObjects[hashobj] = \ continue
highlevelcrypto.makeCryptor(privEncryptionKey)
myAddressesByHash[hashobj] = addressInKeysFile # Returns a simple 32 bytes of information encoded in 64 Hex characters
tag = hashlib.sha512(hashlib.sha512( try:
encodeVarint(addressVersionNumber) privEncryptionKey = hexlify(
+ encodeVarint(streamNumber) + hashobj).digest()).digest()[32:] highlevelcrypto.decodeWalletImportFormat(
myAddressesByTag[tag] = addressInKeysFile config.get(addressInKeysFile, 'privencryptionkey')
else: ))
logger.error( except ValueError:
'Error in reloadMyAddressHashes: Can\'t handle' logger.error(
' address versions other than 2, 3, or 4.' 'Error in reloadMyAddressHashes: failed to decode'
) ' one of the private keys for address %s', addressInKeysFile)
continue
# It is 32 bytes encoded as 64 hex characters
if len(privEncryptionKey) == 64:
myECCryptorObjects[hashobj] = \
highlevelcrypto.makeCryptor(privEncryptionKey)
myAddressesByHash[hashobj] = addressInKeysFile
tag = hashlib.sha512(hashlib.sha512(
encodeVarint(addressVersionNumber)
+ encodeVarint(streamNumber) + hashobj).digest()).digest()[32:]
myAddressesByTag[tag] = addressInKeysFile
if not keyfileSecure: if not keyfileSecure:
fixSensitiveFilePermissions(os.path.join( fixSensitiveFilePermissions(os.path.join(