Test WIF decoding and encoding in highlevelcrypto #2208

Merged
PeterSurda merged 2 commits from gitea-83 into v0.6 2024-04-12 06:30:36 +02:00
4 changed files with 107 additions and 118 deletions
Showing only changes of commit c1ca7044d2 - Show all commits

View File

@ -16,7 +16,6 @@ from addresses import decodeAddress, encodeAddress, encodeVarint
from bmconfigparser import config
from fallback import RIPEMD160Hash
from network import StoppableThread
from pyelliptic import arithmetic
from pyelliptic.openssl import OpenSSL
from tr import _translate
@ -164,20 +163,10 @@ class addressGenerator(StoppableThread):
address = encodeAddress(
addressVersionNumber, streamNumber, ripe)
# 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
privSigningKey = b'\x80' + potentialPrivSigningKey
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)
privSigningKeyWIF = highlevelcrypto.encodeWalletImportFormat(
potentialPrivSigningKey)
privEncryptionKeyWIF = highlevelcrypto.encodeWalletImportFormat(
potentialPrivEncryptionKey)
config.add_section(address)
config.set(address, 'label', label)
@ -303,21 +292,12 @@ class addressGenerator(StoppableThread):
saveAddressToDisk = False
if saveAddressToDisk and live:
# 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
privSigningKey = b'\x80' + potentialPrivSigningKey
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)
privSigningKeyWIF = \
highlevelcrypto.encodeWalletImportFormat(
potentialPrivSigningKey)
privEncryptionKeyWIF = \
highlevelcrypto.encodeWalletImportFormat(
potentialPrivEncryptionKey)
try:
config.add_section(address)

View File

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

View File

@ -23,8 +23,6 @@ from bmconfigparser import config
from debug import logger
from helper_sql import sqlQuery
from pyelliptic import arithmetic
myECCryptorObjects = {}
MyECSubscriptionCryptorObjects = {}
@ -76,35 +74,6 @@ def isAddressInMyAddressBookSubscriptionsListOrWhitelist(address):
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():
"""Reload keys for user's addresses from the config file"""
logger.debug('reloading keys from keys.dat file')
@ -118,29 +87,39 @@ def reloadMyAddressHashes():
hasEnabledKeys = False
for addressInKeysFile in config.addresses():
isEnabled = config.getboolean(addressInKeysFile, 'enabled')
if isEnabled:
hasEnabledKeys = True
# status
addressVersionNumber, streamNumber, hashobj = decodeAddress(addressInKeysFile)[1:]
if addressVersionNumber in (2, 3, 4):
# Returns a simple 32 bytes of information encoded
# in 64 Hex characters, or null if there was an error.
privEncryptionKey = hexlify(decodeWalletImportFormat(
config.get(addressInKeysFile, 'privencryptionkey')))
# 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
else:
logger.error(
'Error in reloadMyAddressHashes: Can\'t handle'
' address versions other than 2, 3, or 4.'
)
if not isEnabled:
continue
hasEnabledKeys = True
addressVersionNumber, streamNumber, hashobj = decodeAddress(
addressInKeysFile)[1:]
if addressVersionNumber not in (2, 3, 4):
logger.error(
'Error in reloadMyAddressHashes: Can\'t handle'
' 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
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:
fixSensitiveFilePermissions(os.path.join(