Test WIF decoding and encoding in highlevelcrypto #2208
|
@ -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)
|
||||||
|
|
|
@ -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,7 +1115,8 @@ 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(
|
||||||
|
highlevelcrypto.decodeWalletImportFormat(
|
||||||
privEncryptionKeyBase58))
|
privEncryptionKeyBase58))
|
||||||
pubEncryptionKeyBase256 = unhexlify(highlevelcrypto.privToPub(
|
pubEncryptionKeyBase256 = unhexlify(highlevelcrypto.privToPub(
|
||||||
privEncryptionKeyHex))[1:]
|
privEncryptionKeyHex))[1:]
|
||||||
|
|
|
@ -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'):
|
||||||
|
|
|
@ -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,15 +87,30 @@ 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:
|
||||||
|
continue
|
||||||
|
|
||||||
hasEnabledKeys = True
|
hasEnabledKeys = True
|
||||||
# status
|
|
||||||
addressVersionNumber, streamNumber, hashobj = decodeAddress(addressInKeysFile)[1:]
|
addressVersionNumber, streamNumber, hashobj = decodeAddress(
|
||||||
if addressVersionNumber in (2, 3, 4):
|
addressInKeysFile)[1:]
|
||||||
# Returns a simple 32 bytes of information encoded
|
if addressVersionNumber not in (2, 3, 4):
|
||||||
# in 64 Hex characters, or null if there was an error.
|
logger.error(
|
||||||
privEncryptionKey = hexlify(decodeWalletImportFormat(
|
'Error in reloadMyAddressHashes: Can\'t handle'
|
||||||
config.get(addressInKeysFile, 'privencryptionkey')))
|
' address versions other than 2, 3, or 4.')
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Returns a simple 32 bytes of information encoded in 64 Hex characters
|
||||||
|
try:
|
||||||
|
privEncryptionKey = hexlify(
|
||||||
|
highlevelcrypto.decodeWalletImportFormat(
|
||||||
|
config.get(addressInKeysFile, 'privencryptionkey')
|
||||||
|
))
|
||||||
|
except ValueError:
|
||||||
|
logger.error(
|
||||||
|
'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
|
# It is 32 bytes encoded as 64 hex characters
|
||||||
if len(privEncryptionKey) == 64:
|
if len(privEncryptionKey) == 64:
|
||||||
myECCryptorObjects[hashobj] = \
|
myECCryptorObjects[hashobj] = \
|
||||||
|
@ -136,11 +120,6 @@ def reloadMyAddressHashes():
|
||||||
encodeVarint(addressVersionNumber)
|
encodeVarint(addressVersionNumber)
|
||||||
+ encodeVarint(streamNumber) + hashobj).digest()).digest()[32:]
|
+ encodeVarint(streamNumber) + hashobj).digest()).digest()[32:]
|
||||||
myAddressesByTag[tag] = addressInKeysFile
|
myAddressesByTag[tag] = addressInKeysFile
|
||||||
else:
|
|
||||||
logger.error(
|
|
||||||
'Error in reloadMyAddressHashes: Can\'t handle'
|
|
||||||
' address versions other than 2, 3, or 4.'
|
|
||||||
)
|
|
||||||
|
|
||||||
if not keyfileSecure:
|
if not keyfileSecure:
|
||||||
fixSensitiveFilePermissions(os.path.join(
|
fixSensitiveFilePermissions(os.path.join(
|
||||||
|
|
Reference in New Issue
Block a user