Refactor using of crypto functions #1796

Closed
g1itch wants to merge 14 commits from crypto into v0.6
20 changed files with 436 additions and 303 deletions

View File

@ -2,11 +2,16 @@
Operations with addresses
"""
# pylint: disable=inconsistent-return-statements
import hashlib
import logging
from binascii import hexlify, unhexlify
from struct import pack, unpack
try:
from highlevelcrypto import double_sha512
except ImportError:
from .highlevelcrypto import double_sha512
logger = logging.getLogger('default')
@ -134,15 +139,6 @@ def decodeVarint(data):
return (encodedValue, 9)
def calculateInventoryHash(data):
"""Calculate inventory hash from object data"""
sha = hashlib.new('sha512')
sha2 = hashlib.new('sha512')
sha.update(data)
sha2.update(sha.digest())
return sha2.digest()[0:32]
def encodeAddress(version, stream, ripe):
"""Convert ripe to address"""
if version >= 2 and version < 4:
@ -166,12 +162,7 @@ def encodeAddress(version, stream, ripe):
storedBinaryData = encodeVarint(version) + encodeVarint(stream) + ripe
# Generate the checksum
sha = hashlib.new('sha512')
sha.update(storedBinaryData)
currentHash = sha.digest()
sha = hashlib.new('sha512')
sha.update(currentHash)
checksum = sha.digest()[0:4]
checksum = double_sha512(storedBinaryData)[0:4]
# FIXME: encodeBase58 should take binary data, to reduce conversions
# encodeBase58(storedBinaryData + checksum)
@ -207,13 +198,7 @@ def decodeAddress(address):
data = unhexlify(hexdata)
checksum = data[-4:]
sha = hashlib.new('sha512')
sha.update(data[:-4])
currentHash = sha.digest()
sha = hashlib.new('sha512')
sha.update(currentHash)
if checksum != sha.digest()[0:4]:
if checksum != double_sha512(data[:-4])[0:4]:
status = 'checksumfailed'
return status, 0, 0, ''

View File

@ -71,6 +71,8 @@ from binascii import hexlify, unhexlify
from SimpleXMLRPCServer import SimpleXMLRPCRequestHandler, SimpleXMLRPCServer
from struct import pack
from six.moves import queue
import defaults
import helper_inbox
import helper_sent
@ -82,17 +84,17 @@ import shutdown
import state
from addresses import (
addBMIfNotPresent,
calculateInventoryHash,
decodeAddress,
decodeVarint,
varintDecodeError
)
from bmconfigparser import BMConfigParser
from debug import logger
from helper_sql import SqlBulkExecute, sqlExecute, sqlQuery, sqlStoredProcedure, sql_ready
from helper_sql import (
SqlBulkExecute, sqlExecute, sqlQuery, sql_ready, sqlStoredProcedure)
from highlevelcrypto import calculateInventoryHash
from inventory import Inventory
from network.threads import StoppableThread
from six.moves import queue
from version import softwareVersion
try: # TODO: write tests for XML vulnerabilities

View File

@ -15,8 +15,6 @@ from addresses import decodeAddress, encodeAddress, encodeVarint
from bmconfigparser import BMConfigParser
from fallback import RIPEMD160Hash
from network import StoppableThread
from pyelliptic import arithmetic
from pyelliptic.openssl import OpenSSL
from six.moves import configparser, queue
@ -129,17 +127,13 @@ class addressGenerator(StoppableThread):
# the \x00 or \x00\x00 bytes thus making the address shorter.
startTime = time.time()
numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix = 0
potentialPrivSigningKey = OpenSSL.rand(32)
potentialPubSigningKey = highlevelcrypto.pointMult(
potentialPrivSigningKey)
privSigningKey, pubSigningKey = highlevelcrypto.random_keys()
while True:
numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix += 1
potentialPrivEncryptionKey = OpenSSL.rand(32)
potentialPubEncryptionKey = highlevelcrypto.pointMult(
potentialPrivEncryptionKey)
potentialPrivEncryptionKey, potentialPubEncryptionKey = \
highlevelcrypto.random_keys()
sha = hashlib.new('sha512')
sha.update(
potentialPubSigningKey + potentialPubEncryptionKey)
sha.update(pubSigningKey + potentialPubEncryptionKey)
ripe = RIPEMD160Hash(sha.digest()).digest()
if (
ripe[:numberOfNullBytesDemandedOnFrontOfRipeHash]
@ -163,20 +157,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(
privSigningKey)
privEncryptionKeyWIF = highlevelcrypto.encodeWalletImportFormat(
potentialPrivEncryptionKey)
BMConfigParser().add_section(address)
BMConfigParser().set(address, 'label', label)
@ -246,18 +230,15 @@ class addressGenerator(StoppableThread):
numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix = 0
while True:
numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix += 1
potentialPrivSigningKey = hashlib.sha512(
deterministicPassphrase
+ encodeVarint(signingKeyNonce)
).digest()[:32]
potentialPrivEncryptionKey = hashlib.sha512(
deterministicPassphrase
+ encodeVarint(encryptionKeyNonce)
).digest()[:32]
potentialPubSigningKey = highlevelcrypto.pointMult(
potentialPrivSigningKey)
potentialPubEncryptionKey = highlevelcrypto.pointMult(
potentialPrivEncryptionKey)
potentialPrivSigningKey, potentialPubSigningKey = \
highlevelcrypto.deterministic_keys(
deterministicPassphrase,
encodeVarint(signingKeyNonce))
potentialPrivEncryptionKey, potentialPubEncryptionKey = \
highlevelcrypto.deterministic_keys(
deterministicPassphrase,
encodeVarint(encryptionKeyNonce))
signingKeyNonce += 2
encryptionKeyNonce += 2
sha = hashlib.new('sha512')
@ -300,21 +281,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:
BMConfigParser().add_section(address)
@ -367,10 +339,10 @@ class addressGenerator(StoppableThread):
highlevelcrypto.makeCryptor(
hexlify(potentialPrivEncryptionKey))
shared.myAddressesByHash[ripe] = address
tag = hashlib.sha512(hashlib.sha512(
tag = highlevelcrypto.double_sha512(
encodeVarint(addressVersionNumber)
+ encodeVarint(streamNumber) + ripe
).digest()).digest()[32:]
)[32:]
shared.myAddressesByTag[tag] = address
if addressVersionNumber == 3:
# If this is a chan address,

View File

@ -23,7 +23,7 @@ import queues
import shared
import state
from addresses import (
calculateInventoryHash, decodeAddress, decodeVarint,
decodeAddress, decodeVarint,
encodeAddress, encodeVarint, varintDecodeError
)
from bmconfigparser import BMConfigParser
@ -450,7 +450,7 @@ class objectProcessor(threading.Thread):
streamNumberAsClaimedByMsg, streamNumberAsClaimedByMsgLength = \
decodeVarint(data[readPosition:readPosition + 9])
readPosition += streamNumberAsClaimedByMsgLength
inventoryHash = calculateInventoryHash(data)
inventoryHash = highlevelcrypto.calculateInventoryHash(data)
initialDecryptionSuccessful = False
# This is not an acknowledgement bound for me. See if it is a message
@ -580,8 +580,7 @@ class objectProcessor(threading.Thread):
helper_bitcoin.calculateTestnetAddressFromPubkey(pubSigningKey)
)
# Used to detect and ignore duplicate messages in our inbox
sigHash = hashlib.sha512(
hashlib.sha512(signature).digest()).digest()[32:]
sigHash = highlevelcrypto.double_sha512(signature)[32:]
# calculate the fromRipe.
sha = hashlib.new('sha512')
@ -751,7 +750,7 @@ class objectProcessor(threading.Thread):
state.numberOfBroadcastsProcessed += 1
queues.UISignalQueue.put((
'updateNumberOfBroadcastsProcessed', 'no data'))
inventoryHash = calculateInventoryHash(data)
inventoryHash = highlevelcrypto.calculateInventoryHash(data)
readPosition = 20 # bypass the nonce, time, and object type
broadcastVersion, broadcastVersionLength = decodeVarint(
data[readPosition:readPosition + 9])
@ -885,10 +884,10 @@ class objectProcessor(threading.Thread):
' itself. Ignoring message.'
)
elif broadcastVersion == 5:
calculatedTag = hashlib.sha512(hashlib.sha512(
calculatedTag = highlevelcrypto.double_sha512(
encodeVarint(sendersAddressVersion)
+ encodeVarint(sendersStream) + calculatedRipe
).digest()).digest()[32:]
)[32:]
if calculatedTag != embeddedTag:
return logger.debug(
'The tag and encryption key used to encrypt this'
@ -918,8 +917,7 @@ class objectProcessor(threading.Thread):
return
logger.debug('ECDSA verify passed')
# Used to detect and ignore duplicate messages in our inbox
sigHash = hashlib.sha512(
hashlib.sha512(signature).digest()).digest()[32:]
sigHash = highlevelcrypto.double_sha512(signature)[32:]
fromAddress = encodeAddress(
sendersAddressVersion, sendersStream, calculatedRipe)
@ -993,10 +991,10 @@ class objectProcessor(threading.Thread):
# Let us create the tag from the address and see if we were waiting
# for it.
elif addressVersion >= 4:
tag = hashlib.sha512(hashlib.sha512(
tag = highlevelcrypto.double_sha512(
encodeVarint(addressVersion) + encodeVarint(streamNumber)
+ ripe
).digest()).digest()[32:]
)[32:]
if tag in state.neededPubkeys:
del state.neededPubkeys[tag]
self.sendMessages(address)

View File

@ -25,9 +25,7 @@ import queues
import shared
import state
import tr
from addresses import (
calculateInventoryHash, decodeAddress, decodeVarint, encodeVarint
)
from addresses import decodeAddress, decodeVarint, encodeVarint
from bmconfigparser import BMConfigParser
from helper_sql import sqlExecute, sqlQuery
from inventory import Inventory
@ -50,6 +48,8 @@ class singleWorker(StoppableThread):
def __init__(self):
super(singleWorker, self).__init__(name="singleWorker")
self.digestAlg = BMConfigParser().safeGet(
'bitmessagesettings', 'digestalg', 'sha256')
proofofwork.init()
def stopThread(self):
@ -73,18 +73,16 @@ class singleWorker(StoppableThread):
queryreturn = sqlQuery(
'''SELECT DISTINCT toaddress FROM sent'''
''' WHERE (status='awaitingpubkey' AND folder='sent')''')
for row in queryreturn:
toAddress, = row
# toStatus
_, toAddressVersionNumber, toStreamNumber, toRipe = \
decodeAddress(toAddress)
for toAddress, in queryreturn:
toAddressVersionNumber, toStreamNumber, toRipe = \
decodeAddress(toAddress)[1:]
if toAddressVersionNumber <= 3:
state.neededPubkeys[toAddress] = 0
elif toAddressVersionNumber >= 4:
doubleHashOfAddressData = hashlib.sha512(hashlib.sha512(
doubleHashOfAddressData = highlevelcrypto.double_sha512(
encodeVarint(toAddressVersionNumber)
+ encodeVarint(toStreamNumber) + toRipe
).digest()).digest()
)
# Note that this is the first half of the sha512 hash.
privEncryptionKey = doubleHashOfAddressData[:32]
tag = doubleHashOfAddressData[32:]
@ -195,15 +193,20 @@ class singleWorker(StoppableThread):
self.logger.info("Quitting...")
def _getKeysForAddress(self, address):
try:
privSigningKeyBase58 = BMConfigParser().get(
address, 'privsigningkey')
privEncryptionKeyBase58 = BMConfigParser().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
@ -254,9 +257,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))
@ -269,18 +270,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:
self.logger.error(
pubSigningKey, pubEncryptionKey = self._getKeysForAddress(
myAddress)[2:]
except ValueError:
return
except Exception:
return self.logger.error(
'Error within doPOWForMyV2Pubkey. Could not read'
' the keys from the keys.dat file for a requested'
' address. %s\n', err
)
return
' address. %s\n', exc_info=True)
payload += pubSigningKey + pubEncryptionKey
@ -288,7 +286,7 @@ class singleWorker(StoppableThread):
payload = self._doPOWDefaults(
payload, TTL, log_prefix='(For pubkey message)')
inventoryHash = calculateInventoryHash(payload)
inventoryHash = highlevelcrypto.calculateInventoryHash(payload)
objectType = 1
Inventory()[inventoryHash] = (
objectType, streamNumber, payload, embeddedTime, '')
@ -318,9 +316,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))
return
return self.logger.warning( # The address has been deleted.
"Can't find %s in myAddressByHash", hexlify(adressHash))
if BMConfigParser().safeGetBoolean(myAddress, 'chan'):
self.logger.info('This is a chan address. Not sending pubkey.')
return
@ -351,15 +348,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:
self.logger.error(
except ValueError:
return
except Exception:
return self.logger.error(
'Error within sendOutOrStoreMyV3Pubkey. Could not read'
' the keys from the keys.dat file for a requested'
' address. %s\n', err
)
return
' address. %s\n', exc_info=True)
payload += pubSigningKey + pubEncryptionKey
@ -368,7 +363,8 @@ class singleWorker(StoppableThread):
payload += encodeVarint(BMConfigParser().getint(
myAddress, 'payloadlengthextrabytes'))
signature = highlevelcrypto.sign(payload, privSigningKeyHex)
signature = highlevelcrypto.sign(
payload, privSigningKeyHex, self.digestAlg)
payload += encodeVarint(len(signature))
payload += signature
@ -376,7 +372,7 @@ class singleWorker(StoppableThread):
payload = self._doPOWDefaults(
payload, TTL, log_prefix='(For pubkey message)')
inventoryHash = calculateInventoryHash(payload)
inventoryHash = highlevelcrypto.calculateInventoryHash(payload)
objectType = 1
Inventory()[inventoryHash] = (
objectType, streamNumber, payload, embeddedTime, '')
@ -425,15 +421,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:
self.logger.error(
except ValueError:
return
except Exception:
return self.logger.error(
'Error within sendOutOrStoreMyV4Pubkey. Could not read'
' the keys from the keys.dat file for a requested'
' address. %s\n', err
)
return
' address. %s\n', exc_info=True)
dataToEncrypt += pubSigningKey + pubEncryptionKey
@ -449,14 +443,13 @@ class singleWorker(StoppableThread):
# unencrypted, the pubkey with part of the hash so that nodes
# know which pubkey object to try to decrypt
# when they want to send a message.
doubleHashOfAddressData = hashlib.sha512(hashlib.sha512(
doubleHashOfAddressData = highlevelcrypto.double_sha512(
encodeVarint(addressVersionNumber)
+ encodeVarint(streamNumber) + addressHash
).digest()).digest()
)
payload += doubleHashOfAddressData[32:] # the tag
signature = highlevelcrypto.sign(
payload + dataToEncrypt, privSigningKeyHex
)
payload + dataToEncrypt, privSigningKeyHex, self.digestAlg)
dataToEncrypt += encodeVarint(len(signature))
dataToEncrypt += signature
@ -469,7 +462,7 @@ class singleWorker(StoppableThread):
payload = self._doPOWDefaults(
payload, TTL, log_prefix='(For pubkey message)')
inventoryHash = calculateInventoryHash(payload)
inventoryHash = highlevelcrypto.calculateInventoryHash(payload)
objectType = 1
Inventory()[inventoryHash] = (
objectType, streamNumber, payload, embeddedTime,
@ -505,7 +498,7 @@ class singleWorker(StoppableThread):
objectType = protocol.OBJECT_ONIONPEER
# FIXME: ideally the objectPayload should be signed
objectPayload = encodeVarint(peer.port) + protocol.encodeHost(peer.host)
tag = calculateInventoryHash(objectPayload)
tag = highlevelcrypto.calculateInventoryHash(objectPayload)
if Inventory().by_type_and_tag(objectType, tag):
return # not expired
@ -519,7 +512,7 @@ class singleWorker(StoppableThread):
payload = self._doPOWDefaults(
payload, TTL, log_prefix='(For onionpeer object)')
inventoryHash = calculateInventoryHash(payload)
inventoryHash = highlevelcrypto.calculateInventoryHash(payload)
Inventory()[inventoryHash] = (
objectType, streamNumber, buffer(payload),
embeddedTime, buffer(tag)
@ -613,10 +606,10 @@ class singleWorker(StoppableThread):
payload += encodeVarint(streamNumber)
if addressVersionNumber >= 4:
doubleHashOfAddressData = hashlib.sha512(hashlib.sha512(
doubleHashOfAddressData = highlevelcrypto.double_sha512(
encodeVarint(addressVersionNumber)
+ encodeVarint(streamNumber) + ripe
).digest()).digest()
)
tag = doubleHashOfAddressData[32:]
payload += tag
else:
@ -641,7 +634,7 @@ class singleWorker(StoppableThread):
dataToSign = payload + dataToEncrypt
signature = highlevelcrypto.sign(
dataToSign, privSigningKeyHex)
dataToSign, privSigningKeyHex, self.digestAlg)
dataToEncrypt += encodeVarint(len(signature))
dataToEncrypt += signature
@ -686,7 +679,7 @@ class singleWorker(StoppableThread):
)
continue
inventoryHash = calculateInventoryHash(payload)
inventoryHash = highlevelcrypto.calculateInventoryHash(payload)
objectType = 3
Inventory()[inventoryHash] = (
objectType, streamNumber, payload, embeddedTime, tag)
@ -795,10 +788,10 @@ class singleWorker(StoppableThread):
if toAddressVersionNumber <= 3:
toTag = ''
else:
toTag = hashlib.sha512(hashlib.sha512(
toTag = highlevelcrypto.double_sha512(
encodeVarint(toAddressVersionNumber)
+ encodeVarint(toStreamNumber) + toRipe
).digest()).digest()[32:]
)[32:]
if toaddress in state.neededPubkeys or \
toTag in state.neededPubkeys:
# We already sent a request for the pubkey
@ -832,11 +825,11 @@ class singleWorker(StoppableThread):
# already contains the toAddress and cryptor
# object associated with the tag for this toAddress.
if toAddressVersionNumber >= 4:
doubleHashOfToAddressData = hashlib.sha512(
hashlib.sha512(
encodeVarint(toAddressVersionNumber) + encodeVarint(toStreamNumber) + toRipe
).digest()
).digest()
doubleHashOfToAddressData = \
highlevelcrypto.double_sha512(
encodeVarint(toAddressVersionNumber)
+ encodeVarint(toStreamNumber) + toRipe
)
# The first half of the sha512 hash.
privEncryptionKey = doubleHashOfToAddressData[:32]
# The second half of the sha512 hash.
@ -1116,7 +1109,8 @@ class singleWorker(StoppableThread):
' from the keys.dat file for our own address. %s\n',
err)
continue
privEncryptionKeyHex = hexlify(shared.decodeWalletImportFormat(
privEncryptionKeyHex = hexlify(
highlevelcrypto.decodeWalletImportFormat(
privEncryptionKeyBase58))
pubEncryptionKeyBase256 = unhexlify(highlevelcrypto.privToPub(
privEncryptionKeyHex))[1:]
@ -1223,7 +1217,8 @@ class singleWorker(StoppableThread):
payload += fullAckPayload
dataToSign = pack('>Q', embeddedTime) + '\x00\x00\x00\x02' + \
encodeVarint(1) + encodeVarint(toStreamNumber) + payload
signature = highlevelcrypto.sign(dataToSign, privSigningKeyHex)
signature = highlevelcrypto.sign(
dataToSign, privSigningKeyHex, self.digestAlg)
payload += encodeVarint(len(signature))
payload += signature
@ -1301,7 +1296,7 @@ class singleWorker(StoppableThread):
)
continue
inventoryHash = calculateInventoryHash(encryptedPayload)
inventoryHash = highlevelcrypto.calculateInventoryHash(encryptedPayload)
objectType = 2
Inventory()[inventoryHash] = (
objectType, toStreamNumber, encryptedPayload, embeddedTime, '')
@ -1351,8 +1346,7 @@ class singleWorker(StoppableThread):
# the message in our own inbox.
if BMConfigParser().has_section(toaddress):
# Used to detect and ignore duplicate messages in our inbox
sigHash = hashlib.sha512(hashlib.sha512(
signature).digest()).digest()[32:]
sigHash = highlevelcrypto.double_sha512(signature)[32:]
t = (inventoryHash, toaddress, fromaddress, subject, int(
time.time()), message, 'inbox', encoding, 0, sigHash)
helper_inbox.insert(t)
@ -1407,16 +1401,13 @@ class singleWorker(StoppableThread):
# neededPubkeys dictionary. But if we are recovering
# from a restart of the client then we have to put it in now.
# Note that this is the first half of the sha512 hash.
privEncryptionKey = hashlib.sha512(hashlib.sha512(
doubleHashOfAddressData = highlevelcrypto.double_sha512(
encodeVarint(addressVersionNumber)
+ encodeVarint(streamNumber) + ripe
).digest()).digest()[:32]
)
privEncryptionKey = doubleHashOfAddressData[:32]
# Note that this is the second half of the sha512 hash.
tag = hashlib.sha512(hashlib.sha512(
encodeVarint(addressVersionNumber)
+ encodeVarint(streamNumber) + ripe
).digest()).digest()[32:]
tag = doubleHashOfAddressData[32:]
if tag not in state.neededPubkeys:
# We'll need this for when we receive a pubkey reply:
# it will be encrypted and we'll need to decrypt it.
@ -1459,7 +1450,7 @@ class singleWorker(StoppableThread):
payload = self._doPOWDefaults(payload, TTL)
inventoryHash = calculateInventoryHash(payload)
inventoryHash = highlevelcrypto.calculateInventoryHash(payload)
objectType = 1
Inventory()[inventoryHash] = (
objectType, streamNumber, payload, embeddedTime, '')

View File

@ -25,10 +25,10 @@ def genAckPayload(streamNumber=1, stealthLevel=0):
if stealthLevel == 2: # Generate privacy-enhanced payload
# Generate a dummy privkey and derive the pubkey
dummyPubKeyHex = highlevelcrypto.privToPub(
hexlify(helper_random.randomBytes(32)))
hexlify(highlevelcrypto.randomBytes(32)))
# Generate a dummy message of random length
# (the smallest possible standard-formatted message is 234 bytes)
dummyMessage = helper_random.randomBytes(
dummyMessage = highlevelcrypto.randomBytes(
helper_random.randomrandrange(234, 801))
# Encrypt the message using standard BM encryption (ECIES)
ackdata = highlevelcrypto.encrypt(dummyMessage, dummyPubKeyHex)
@ -36,12 +36,12 @@ def genAckPayload(streamNumber=1, stealthLevel=0):
version = 1
elif stealthLevel == 1: # Basic privacy payload (random getpubkey)
ackdata = helper_random.randomBytes(32)
ackdata = highlevelcrypto.randomBytes(32)
acktype = 0 # getpubkey
version = 4
else: # Minimum viable payload (non stealth)
ackdata = helper_random.randomBytes(32)
ackdata = highlevelcrypto.randomBytes(32)
acktype = 2 # message
version = 1

View File

@ -1,12 +1,7 @@
"""Convenience functions for random operations. Not suitable for security / cryptography operations."""
import os
import random
try:
from pyelliptic.openssl import OpenSSL
except ImportError:
from .pyelliptic.openssl import OpenSSL
NoneType = type(None)
@ -16,14 +11,6 @@ def seed():
random.seed()
def randomBytes(n):
"""Method randomBytes."""
try:
return os.urandom(n)
except NotImplementedError:
return OpenSSL.rand(n)
def randomshuffle(population):
"""Method randomShuffle.

View File

@ -7,17 +7,85 @@ High level cryptographic functions based on `.pyelliptic` OpenSSL bindings.
`More discussion. <https://github.com/yann2192/pyelliptic/issues/32>`_
"""
import hashlib
import os
from binascii import hexlify
import pyelliptic
from pyelliptic import OpenSSL
from pyelliptic import arithmetic as a
from bmconfigparser import BMConfigParser
__all__ = ['encrypt', 'makeCryptor', 'pointMult', 'privToPub', 'sign', 'verify']
# Hashes
def double_sha512(data):
"""Binary double SHA512 digest"""
return hashlib.sha512(hashlib.sha512(data).digest()).digest()
def calculateInventoryHash(data):
"""Calculate inventory hash from object data"""
return double_sha512(data)[:32]
# 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)
# Random
def randomBytes(n):
"""Get n random bytes"""
try:
return os.urandom(n)
except NotImplementedError:
return OpenSSL.rand(n)
# Keys
def random_keys():
"""Return a pair of keys, private and public"""
priv = randomBytes(32)
pub = pointMult(priv)
return priv, pub
def deterministic_keys(passphrase, nonce):
"""Generate keys from *passphrase* and *nonce* (encoded as varint)"""
priv = hashlib.sha512(passphrase + nonce).digest()[:32]
pub = pointMult(priv)
return priv, pub
g1itch commented 2021-12-10 18:02:14 +01:00 (Migrated from github.com)
Review

I'm not sure if these functions should return the pair or only the private key.

I'm not sure if these functions should return the pair or only the private key.
def makeCryptor(privkey):
"""Return a private `.pyelliptic.ECC` instance"""
private_key = a.changebase(privkey, 16, 256, minlen=32)
@ -67,22 +135,17 @@ def decryptFast(msg, cryptor):
return cryptor.decrypt(msg)
def sign(msg, hexPrivkey):
def sign(msg, hexPrivkey, digestAlg="sha256"):
"""
Signs with hex private key using SHA1 or SHA256 depending on
"digestalg" setting
*digestAlg* keyword.
"""
digestAlg = BMConfigParser().safeGet(
'bitmessagesettings', 'digestalg', 'sha256')
if digestAlg == "sha1":
if digestAlg not in ("sha1", "sha256"):
raise ValueError("Unknown digest algorithm %s" % digestAlg)
# SHA1, this will eventually be deprecated
return makeCryptor(hexPrivkey).sign(
msg, digest_alg=OpenSSL.digest_ecdsa_sha1)
elif digestAlg == "sha256":
# SHA256. Eventually this will become the default
return makeCryptor(hexPrivkey).sign(msg, digest_alg=OpenSSL.EVP_sha256)
else:
raise ValueError("Unknown digest algorithm %s" % digestAlg)
msg, digest_alg=OpenSSL.digest_ecdsa_sha1
if digestAlg == "sha1" else OpenSSL.EVP_sha256)
def verify(msg, sig, hexPubkey):

View File

@ -6,7 +6,7 @@ import time
import protocol
import state
from addresses import calculateInventoryHash
from highlevelcrypto import calculateInventoryHash
from inventory import Inventory
from network.dandelion import Dandelion

View File

@ -17,7 +17,7 @@ import knownnodes
import protocol
import state
from bmconfigparser import BMConfigParser
from helper_random import randomBytes
from highlevelcrypto import randomBytes
from inventory import Inventory
from network.advanceddispatcher import AdvancedDispatcher
from network.assemble import assemble_addr

View File

@ -4,7 +4,6 @@ Proof of work calculation
"""
import ctypes
import hashlib
import os
import sys
import tempfile
@ -12,6 +11,7 @@ import time
from struct import pack, unpack
from subprocess import call
import highlevelcrypto
import openclpow
import paths
import queues
@ -87,13 +87,20 @@ def _set_idle():
pass
def trial_value(nonce, initialHash):
"""Calculate PoW trial value"""
trialValue, = unpack(
'>Q', highlevelcrypto.double_sha512(
pack('>Q', nonce) + initialHash)[0:8])
return trialValue
def _pool_worker(nonce, initialHash, target, pool_size):
_set_idle()
trialValue = float('inf')
while trialValue > target:
nonce += pool_size
trialValue, = unpack('>Q', hashlib.sha512(hashlib.sha512(
pack('>Q', nonce) + initialHash).digest()).digest()[0:8])
trialValue = trial_value(nonce, initialHash)
return [trialValue, nonce]
@ -103,10 +110,9 @@ def _doSafePoW(target, initialHash):
trialValue = float('inf')
while trialValue > target and state.shutdown == 0:
nonce += 1
trialValue, = unpack('>Q', hashlib.sha512(hashlib.sha512(
pack('>Q', nonce) + initialHash).digest()).digest()[0:8])
trialValue = trial_value(nonce, initialHash)
if state.shutdown != 0:
raise StopIteration("Interrupted") # pylint: misplaced-bare-raise
raise StopIteration("Interrupted")
logger.debug("Safe PoW done")
return [trialValue, nonce]
@ -163,7 +169,7 @@ def _doCPoW(target, initialHash):
logger.debug("C PoW start")
nonce = bmpow(out_h, out_m)
trialValue, = unpack('>Q', hashlib.sha512(hashlib.sha512(pack('>Q', nonce) + initialHash).digest()).digest()[0:8])
trialValue = trial_value(nonce, initialHash)
if state.shutdown != 0:
raise StopIteration("Interrupted")
logger.debug("C PoW done")
@ -173,7 +179,7 @@ def _doCPoW(target, initialHash):
def _doGPUPoW(target, initialHash):
logger.debug("GPU PoW start")
nonce = openclpow.do_opencl_pow(initialHash.encode("hex"), target)
trialValue, = unpack('>Q', hashlib.sha512(hashlib.sha512(pack('>Q', nonce) + initialHash).digest()).digest()[0:8])
trialValue = trial_value(nonce, initialHash)
if trialValue > target:
deviceNames = ", ".join(gpu.name for gpu in openclpow.enabledGpus)
queues.UISignalQueue.put((

View File

@ -269,12 +269,11 @@ def isProofOfWorkSufficient(
if payloadLengthExtraBytes < defaults.networkDefaultPayloadLengthExtraBytes:
payloadLengthExtraBytes = defaults.networkDefaultPayloadLengthExtraBytes
endOfLifeTime, = unpack('>Q', data[8:16])
TTL = endOfLifeTime - (int(recvTime) if recvTime else int(time.time()))
TTL = endOfLifeTime - int(recvTime if recvTime else time.time())
if TTL < 300:
TTL = 300
POW, = unpack('>Q', hashlib.sha512(hashlib.sha512(
data[:8] + hashlib.sha512(data[8:]).digest()
).digest()).digest()[0:8])
POW, = unpack('>Q', highlevelcrypto.double_sha512(
data[:8] + hashlib.sha512(data[8:]).digest())[0:8])
return POW <= 2 ** 64 / (
nonceTrialsPerByte * (
len(data) + payloadLengthExtraBytes

View File

@ -23,6 +23,12 @@ sample_privsigningkey = \
sample_privencryptionkey = \
b'4b0b73a54e19b059dc274ab69df095fe699f43b17397bca26fdf40f4d7400a3a'
# [chan] bitmessage
sample_wif_privsigningkey = \
b'a2e8b841a531c1c558ee0680c396789c7a2ea3ac4795ae3f000caf9fe367d144'
sample_wif_privencryptionkey = \
b'114ec0e2dca24a826a0eed064b0405b0ac148abc3b1d52729697f4d7b873fdc6'
sample_factor = \
66858749573256452658262553961707680376751171096153613379801854825275240965733
# G * sample_factor
@ -40,6 +46,38 @@ class TestArithmetic(unittest.TestCase):
sample_point,
arithmetic.base10_multiply(arithmetic.G, sample_factor))
def test_base58(self):
"""Test encoding/decoding base58 using arithmetic functions"""
self.assertEqual(
arithmetic.decode(arithmetic.changebase(
b'2cWzSnwjJ7yRP3nLEWUV5LisTZyREWSzUK', 58, 256), 256),
25152821841976547050350277460563089811513157529113201589004)
self.assertEqual(
arithmetic.decode(arithmetic.changebase(
b'2DBPTgeSawWYZceFD69AbDT5q4iUWtj1ZN', 58, 256), 256),
18875720106589866286514488037355423395410802084648916523381)
self.assertEqual(
arithmetic.changebase(arithmetic.encode(
25152821841976547050350277460563089811513157529113201589004,
256), 256, 58), b'2cWzSnwjJ7yRP3nLEWUV5LisTZyREWSzUK')
self.assertEqual(
arithmetic.changebase(arithmetic.encode(
18875720106589866286514488037355423395410802084648916523381,
256), 256, 58), b'2DBPTgeSawWYZceFD69AbDT5q4iUWtj1ZN')
def test_wif(self):
"""Decode WIFs of [chan] bitmessage and check the keys"""
self.assertEqual(
sample_wif_privsigningkey,
arithmetic.changebase(arithmetic.changebase(
b'5K42shDERM5g7Kbi3JT5vsAWpXMqRhWZpX835M2pdSoqQQpJMYm', 58, 256
)[1:-4], 256, 16))
self.assertEqual(
sample_wif_privencryptionkey,
arithmetic.changebase(arithmetic.changebase(
b'5HwugVWm31gnxtoYcvcK7oywH2ezYTh6Y4tzRxsndAeMi6NHqpA', 58, 256
)[1:-4], 256, 16))
def test_decode(self):
"""Decode sample privsigningkey from hex to int and compare to factor"""
self.assertEqual(

View File

@ -4,9 +4,10 @@ Test if OpenSSL is working correctly
import unittest
try:
from pyelliptic.ecc import ECC
from pyelliptic.openssl import OpenSSL
except ImportError:
from pybitmessage.pyelliptic import OpenSSL
from pybitmessage.pyelliptic import ECC, OpenSSL
try:
OpenSSL.BN_bn2binpad
@ -55,3 +56,10 @@ class TestOpenSSL(unittest.TestCase):
if b.raw != c.raw.rjust(OpenSSL.BN_num_bytes(n), b'\x00'):
bad += 1
self.assertEqual(bad, 0)
def test_random_keys(self):
"""A dummy test for random keys in ECC object"""
eccobj = ECC(curve='secp256k1')
self.assertEqual(len(eccobj.privkey), 32)
pubkey = eccobj.get_pubkey()
self.assertEqual(pubkey[:4], b'\x02\xca\x00\x20')

View File

@ -23,8 +23,6 @@ from bmconfigparser import BMConfigParser
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 BMConfigParser().addresses():
isEnabled = BMConfigParser().getboolean(addressInKeysFile, 'enabled')
if isEnabled:
if not isEnabled:
continue
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(
BMConfigParser().get(addressInKeysFile, 'privencryptionkey')))
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(
BMConfigParser().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(
tag = highlevelcrypto.double_sha512(
encodeVarint(addressVersionNumber)
+ encodeVarint(streamNumber) + hashobj).digest()).digest()[32:]
+ encodeVarint(streamNumber) + hashobj)[32:]
myAddressesByTag[tag] = addressInKeysFile
else:
logger.error(
'Error in reloadMyAddressHashes: Can\'t handle'
' address versions other than 2, 3, or 4.'
)
if not keyfileSecure:
fixSensitiveFilePermissions(os.path.join(
@ -174,10 +153,10 @@ def reloadBroadcastSendersForWhichImWatching():
MyECSubscriptionCryptorObjects[hashobj] = \
highlevelcrypto.makeCryptor(hexlify(privEncryptionKey))
else:
doubleHashOfAddressData = hashlib.sha512(hashlib.sha512(
doubleHashOfAddressData = highlevelcrypto.double_sha512(
encodeVarint(addressVersionNumber)
+ encodeVarint(streamNumber) + hashobj
).digest()).digest()
)
tag = doubleHashOfAddressData[32:]
privEncryptionKey = doubleHashOfAddressData[:32]
MyECSubscriptionCryptorObjects[tag] = \

View File

@ -2,6 +2,11 @@
from binascii import unhexlify
# hello, page 1 of the Specification
sample_double_sha512 = unhexlify(
'0592a10584ffabf96539f3d780d776828c67da1ab5b169e9e8aed838aaecc9ed36d49ff14'
'23c55f019e050c66c6324f53588be88894fef4dcffdb74b98e2b200')
magic = 0xE9BEB4D9
@ -28,17 +33,39 @@ sample_point = (
94730058721143827257669456336351159718085716196507891067256111928318063085006
)
sample_seed = 'TIGER, tiger, burning bright. In the forests of the night'
# Deterministic addresses with stream 1 and versions 3, 4
sample_seed = b'TIGER, tiger, burning bright. In the forests of the night'
# RIPE hash on step 22 with signing key nonce 42
sample_deterministic_ripe = b'00cfb69416ae76f68a81c459de4e13460c7d17eb'
# Deterministic addresses with stream 1 and versions 3, 4
sample_deterministic_addr3 = 'BM-2DBPTgeSawWYZceFD69AbDT5q4iUWtj1ZN'
sample_deterministic_addr4 = 'BM-2cWzSnwjJ7yRP3nLEWUV5LisTZyREWSzUK'
sample_daddr3_512 = 18875720106589866286514488037355423395410802084648916523381
sample_daddr4_512 = 25152821841976547050350277460563089811513157529113201589004
sample_statusbar_msg = "new status bar message"
sample_inbox_msg_ids = ['27e644765a3e4b2e973ee7ccf958ea20', '51fc5531-3989-4d69-bbb5-68d64b756f5b',
sample_statusbar_msg = 'new status bar message'
sample_inbox_msg_ids = [
'27e644765a3e4b2e973ee7ccf958ea20', '51fc5531-3989-4d69-bbb5-68d64b756f5b',
'2c975c515f8b414db5eea60ba57ba455', 'bc1f2d8a-681c-4cc0-9a12-6067c7e1ac24']
# second address in sample_test_subscription_address is for the announcement broadcast
sample_test_subscription_address = ['BM-2cWQLCBGorT9pUGkYSuGGVr9LzE4mRnQaq', 'BM-GtovgYdgs7qXPkoYaRgrLFuFKz1SFpsw']
# second address in sample_subscription_addresses
# is for the announcement broadcast
sample_subscription_addresses = [
'BM-2cWQLCBGorT9pUGkYSuGGVr9LzE4mRnQaq',
'BM-GtovgYdgs7qXPkoYaRgrLFuFKz1SFpsw']
sample_subscription_name = 'test sub'
sample_msg = unhexlify(
'0592a10584ffabf96539f3d780d776828c67da1ab5b169e9e8aed838aaecc9ed36d49ff'
'1423c55f019e050c66c6324f53588be88894fef4dcffdb74b98e2b200')
sample_sig = unhexlify(
'304402202302475351db6b822de15d922e29397541f10d8a19780ba2ca4a920b1035f075'
'02205e5bba40d5f07a24c23a89ba5f01a3828371dfbb685dd5375fa1c29095fd232b')
sample_sig_sha1 = unhexlify(
'304502203b50123af78b4e40f5f819ae5b8786f48826e56d0f3e65744708a493f5b65de1'
'0221009ddce2981ea143c0ac70404a535327e774adce8eebbae2d35104f1d326255f9a')
# [chan] bitmessage
sample_wif_privsigningkey = unhexlify(
b'a2e8b841a531c1c558ee0680c396789c7a2ea3ac4795ae3f000caf9fe367d144')
sample_wif_privencryptionkey = unhexlify(
b'114ec0e2dca24a826a0eed064b0405b0ac148abc3b1d52729697f4d7b873fdc6')

View File

@ -2,12 +2,13 @@
import unittest
from binascii import unhexlify
from pybitmessage import addresses
from pybitmessage import addresses, highlevelcrypto
from .samples import (
sample_address, sample_daddr3_512, sample_daddr4_512,
sample_deterministic_addr4, sample_deterministic_addr3,
sample_deterministic_ripe, sample_ripe)
sample_deterministic_ripe, sample_ripe,
sample_wif_privsigningkey, sample_wif_privencryptionkey)
sample_addr3 = sample_deterministic_addr3.split('-')[1]
sample_addr4 = sample_deterministic_addr4.split('-')[1]
@ -59,3 +60,26 @@ class TestAddresses(unittest.TestCase):
sample_addr4, addresses.encodeBase58(sample_daddr4_512))
PeterSurda commented 2021-11-15 08:23:35 +01:00 (Migrated from github.com)
Review

these binary data should also be a variable in samples.

these binary data should also be a variable in samples.
self.assertEqual(
sample_addr3, addresses.encodeBase58(sample_daddr3_512))
def test_wif(self):
"""Decode WIFs of [chan] bitmessage and check the keys"""
self.assertEqual(
sample_wif_privsigningkey,
highlevelcrypto.decodeWalletImportFormat(
b'5K42shDERM5g7Kbi3JT5vsAWpXMqRhWZpX835M2pdSoqQQpJMYm'))
self.assertEqual(
sample_wif_privencryptionkey,
highlevelcrypto.decodeWalletImportFormat(
b'5HwugVWm31gnxtoYcvcK7oywH2ezYTh6Y4tzRxsndAeMi6NHqpA'))
self.assertEqual(
b'5K42shDERM5g7Kbi3JT5vsAWpXMqRhWZpX835M2pdSoqQQpJMYm',
highlevelcrypto.encodeWalletImportFormat(
sample_wif_privsigningkey))
self.assertEqual(
b'5HwugVWm31gnxtoYcvcK7oywH2ezYTh6Y4tzRxsndAeMi6NHqpA',
highlevelcrypto.encodeWalletImportFormat(
sample_wif_privencryptionkey))
with self.assertRaises(ValueError):
highlevelcrypto.decodeWalletImportFormat(
b'5HwugVWm31gnxtoYcvcK7oywH2ezYTh6Y4tzRxsndAeMi6NHq')

View File

@ -12,8 +12,10 @@ from six.moves import xmlrpc_client # nosec
import psutil
from .samples import (
sample_seed, sample_deterministic_addr3, sample_deterministic_addr4, sample_statusbar_msg,
sample_inbox_msg_ids, sample_test_subscription_address, sample_subscription_name)
sample_seed, sample_deterministic_addr3, sample_deterministic_addr4,
sample_statusbar_msg, sample_inbox_msg_ids, sample_subscription_addresses,
sample_subscription_name
)
from .test_process import TestProcessProto
@ -263,9 +265,10 @@ class TestAPI(TestAPIProto):
def test_subscriptions(self):
"""Testing the API commands related to subscriptions"""
self.assertEqual(
self.api.addSubscription(sample_test_subscription_address[0], sample_subscription_name.encode('base64')),
self.api.addSubscription(
sample_subscription_addresses[0],
sample_subscription_name.encode('base64')),
'Added subscription.'
)
@ -273,18 +276,19 @@ class TestAPI(TestAPIProto):
# check_address
for sub in json.loads(self.api.listSubscriptions())['subscriptions']:
# special address, added when sqlThread starts
if sub['address'] == sample_test_subscription_address[0]:
if sub['address'] == sample_subscription_addresses[0]:
added_subscription = sub
break
self.assertEqual(
base64.decodestring(added_subscription['label']) if added_subscription['label'] else None,
base64.decodestring(added_subscription['label'])
if added_subscription['label'] else None,
sample_subscription_name)
self.assertTrue(added_subscription['enabled'])
for s in json.loads(self.api.listSubscriptions())['subscriptions']:
# special address, added when sqlThread starts
if s['address'] == sample_test_subscription_address[1]:
if s['address'] == sample_subscription_addresses[1]:
self.assertEqual(
base64.decodestring(s['label']),
'Bitmessage new releases/announcements')
@ -295,10 +299,10 @@ class TestAPI(TestAPIProto):
'Could not find Bitmessage new releases/announcements'
' in subscriptions')
self.assertEqual(
self.api.deleteSubscription(sample_test_subscription_address[0]),
self.api.deleteSubscription(sample_subscription_addresses[0]),
'Deleted subscription if it existed.')
self.assertEqual(
self.api.deleteSubscription(sample_test_subscription_address[1]),
self.api.deleteSubscription(sample_subscription_addresses[1]),
'Deleted subscription if it existed.')
self.assertEqual(
json.loads(self.api.listSubscriptions())['subscriptions'], [])

View File

@ -16,8 +16,10 @@ except ImportError:
RIPEMD = None
from .samples import (
sample_pubsigningkey, sample_pubencryptionkey,
sample_privsigningkey, sample_privencryptionkey, sample_ripe
sample_deterministic_ripe, sample_double_sha512,
sample_msg, sample_pubsigningkey, sample_pubencryptionkey,
sample_privsigningkey, sample_privencryptionkey, sample_ripe,
sample_seed, sample_sig, sample_sig_sha1
)
@ -62,6 +64,56 @@ class TestCrypto(RIPEMD160TestCase, unittest.TestCase):
class TestHighlevelcrypto(unittest.TestCase):
"""Test highlevelcrypto public functions"""
# def test_sign(self):
# """Check the signature of the sample_msg created with sample key"""
# self.assertEqual(
# highlevelcrypto.sign(sample_msg, sample_privsigningkey), sample_sig)
def test_double_sha512(self):
"""Reproduce the example on page 1 of the Specification"""
self.assertEqual(
highlevelcrypto.double_sha512(b'hello'), sample_double_sha512)
def test_randomBytes(self):
"""Dummy checks for random bytes"""
for n in (8, 32, 64):
data = highlevelcrypto.randomBytes(n)
self.assertEqual(len(data), n)
self.assertNotEqual(len(set(data)), 1)
self.assertNotEqual(data, highlevelcrypto.randomBytes(n))
def test_random_keys(self):
"""Dummy checks for random keys"""
priv, pub = highlevelcrypto.random_keys()
self.assertEqual(len(priv), 32)
PeterSurda commented 2021-11-15 08:24:01 +01:00 (Migrated from github.com)
Review

ideally b'hello' should also be a variable in samples

ideally `b'hello'` should also be a variable in samples
g1itch commented 2021-11-15 13:10:44 +01:00 (Migrated from github.com)
Review
It's from here: https://pybitmessage-test.readthedocs.io/en/doc/protocol.html#hashes
self.assertEqual(highlevelcrypto.pointMult(priv), pub)
def test_deterministic_keys(self):
"""Generate deterministic keys, make ripe and compare it to sample"""
# encodeVarint(42) = b'*'
sigkey = highlevelcrypto.deterministic_keys(sample_seed, b'*')[1]
enkey = highlevelcrypto.deterministic_keys(sample_seed, b'+')[1]
self.assertEqual(
sample_deterministic_ripe,
hexlify(TestHashlib._hashdigest(
hashlib.sha512(sigkey + enkey).digest())))
def test_verify(self):
"""Verify sample signatures and newly generated ones"""
pubkey_hex = hexlify(sample_pubsigningkey)
# pregenerated signatures
self.assertTrue(
highlevelcrypto.verify(sample_msg, sample_sig, pubkey_hex))
self.assertTrue(
highlevelcrypto.verify(sample_msg, sample_sig_sha1, pubkey_hex))
# new signatures
sig256 = highlevelcrypto.sign(sample_msg, sample_privsigningkey)
sig1 = highlevelcrypto.sign(sample_msg, sample_privsigningkey, "sha1")
self.assertTrue(
highlevelcrypto.verify(sample_msg, sig256, pubkey_hex))
self.assertTrue(
highlevelcrypto.verify(sample_msg, sig1, pubkey_hex))
def test_privtopub(self):
"""Generate public keys and check the result"""
self.assertEqual(

View File

@ -1,10 +1,10 @@
"""
Tests for openclpow module
"""
import hashlib
import unittest
from struct import pack, unpack
from pybitmessage import openclpow
from pybitmessage import openclpow, proofofwork
class TestOpenClPow(unittest.TestCase):
@ -25,7 +25,5 @@ class TestOpenClPow(unittest.TestCase):
"b93f3ffeba0ef2fd08a8dc2f87b68ae5a0dc819ab57f22ad2c4c9c8618a43b3"
).decode("hex")
nonce = openclpow.do_opencl_pow(initialHash.encode("hex"), target_)
trialValue, = unpack(
'>Q', hashlib.sha512(hashlib.sha512(
pack('>Q', nonce) + initialHash).digest()).digest()[0:8])
self.assertLess((nonce - trialValue), target_)
self.assertLess(
nonce - proofofwork.trial_value(nonce, initialHash), target_)