Added pycrypto fallback for RIPEMD160 hash function
This commit is contained in:
parent
4eec124225
commit
e163137893
|
@ -1,2 +1,3 @@
|
||||||
python_prctl
|
python_prctl
|
||||||
psutil
|
psutil
|
||||||
|
pycrypto
|
||||||
|
|
|
@ -15,6 +15,7 @@ import highlevelcrypto
|
||||||
from bmconfigparser import BMConfigParser
|
from bmconfigparser import BMConfigParser
|
||||||
from debug import logger
|
from debug import logger
|
||||||
from addresses import decodeAddress, encodeAddress, encodeVarint
|
from addresses import decodeAddress, encodeAddress, encodeVarint
|
||||||
|
from fallback import RIPEMD160Hash
|
||||||
from helper_threading import StoppableThread
|
from helper_threading import StoppableThread
|
||||||
|
|
||||||
|
|
||||||
|
@ -133,16 +134,17 @@ class addressGenerator(threading.Thread, StoppableThread):
|
||||||
potentialPrivEncryptionKey = OpenSSL.rand(32)
|
potentialPrivEncryptionKey = OpenSSL.rand(32)
|
||||||
potentialPubEncryptionKey = highlevelcrypto.pointMult(
|
potentialPubEncryptionKey = highlevelcrypto.pointMult(
|
||||||
potentialPrivEncryptionKey)
|
potentialPrivEncryptionKey)
|
||||||
ripe = hashlib.new('ripemd160')
|
|
||||||
sha = hashlib.new('sha512')
|
sha = hashlib.new('sha512')
|
||||||
sha.update(
|
sha.update(
|
||||||
potentialPubSigningKey + potentialPubEncryptionKey)
|
potentialPubSigningKey + potentialPubEncryptionKey)
|
||||||
ripe.update(sha.digest())
|
ripe = RIPEMD160Hash(sha.digest()).digest()
|
||||||
if ripe.digest()[:numberOfNullBytesDemandedOnFrontOfRipeHash] == '\x00' * numberOfNullBytesDemandedOnFrontOfRipeHash:
|
if (
|
||||||
|
ripe[:numberOfNullBytesDemandedOnFrontOfRipeHash] ==
|
||||||
|
'\x00' * numberOfNullBytesDemandedOnFrontOfRipeHash
|
||||||
|
):
|
||||||
break
|
break
|
||||||
logger.info(
|
logger.info(
|
||||||
'Generated address with ripe digest: %s',
|
'Generated address with ripe digest: %s', hexlify(ripe))
|
||||||
hexlify(ripe.digest()))
|
|
||||||
try:
|
try:
|
||||||
logger.info(
|
logger.info(
|
||||||
'Address generator calculated %s addresses at %s'
|
'Address generator calculated %s addresses at %s'
|
||||||
|
@ -156,7 +158,7 @@ class addressGenerator(threading.Thread, StoppableThread):
|
||||||
# time.time() - startTime equaled zero.
|
# time.time() - startTime equaled zero.
|
||||||
pass
|
pass
|
||||||
address = encodeAddress(
|
address = encodeAddress(
|
||||||
addressVersionNumber, streamNumber, ripe.digest())
|
addressVersionNumber, streamNumber, ripe)
|
||||||
|
|
||||||
# An excellent way for us to store our keys
|
# An excellent way for us to store our keys
|
||||||
# is in Wallet Import Format. Let us convert now.
|
# is in Wallet Import Format. Let us convert now.
|
||||||
|
@ -203,7 +205,7 @@ class addressGenerator(threading.Thread, StoppableThread):
|
||||||
shared.reloadMyAddressHashes()
|
shared.reloadMyAddressHashes()
|
||||||
if addressVersionNumber == 3:
|
if addressVersionNumber == 3:
|
||||||
queues.workerQueue.put((
|
queues.workerQueue.put((
|
||||||
'sendOutOrStoreMyV3Pubkey', ripe.digest()))
|
'sendOutOrStoreMyV3Pubkey', ripe))
|
||||||
elif addressVersionNumber == 4:
|
elif addressVersionNumber == 4:
|
||||||
queues.workerQueue.put((
|
queues.workerQueue.put((
|
||||||
'sendOutOrStoreMyV4Pubkey', address))
|
'sendOutOrStoreMyV4Pubkey', address))
|
||||||
|
@ -255,17 +257,18 @@ class addressGenerator(threading.Thread, StoppableThread):
|
||||||
potentialPrivEncryptionKey)
|
potentialPrivEncryptionKey)
|
||||||
signingKeyNonce += 2
|
signingKeyNonce += 2
|
||||||
encryptionKeyNonce += 2
|
encryptionKeyNonce += 2
|
||||||
ripe = hashlib.new('ripemd160')
|
|
||||||
sha = hashlib.new('sha512')
|
sha = hashlib.new('sha512')
|
||||||
sha.update(
|
sha.update(
|
||||||
potentialPubSigningKey + potentialPubEncryptionKey)
|
potentialPubSigningKey + potentialPubEncryptionKey)
|
||||||
ripe.update(sha.digest())
|
ripe = RIPEMD160Hash(sha.digest()).digest()
|
||||||
if ripe.digest()[:numberOfNullBytesDemandedOnFrontOfRipeHash] == '\x00' * numberOfNullBytesDemandedOnFrontOfRipeHash:
|
if (
|
||||||
|
ripe[:numberOfNullBytesDemandedOnFrontOfRipeHash] ==
|
||||||
|
'\x00' * numberOfNullBytesDemandedOnFrontOfRipeHash
|
||||||
|
):
|
||||||
break
|
break
|
||||||
|
|
||||||
logger.info(
|
logger.info(
|
||||||
'Generated address with ripe digest: %s',
|
'Generated address with ripe digest: %s', hexlify(ripe))
|
||||||
hexlify(ripe.digest()))
|
|
||||||
try:
|
try:
|
||||||
logger.info(
|
logger.info(
|
||||||
'Address generator calculated %s addresses'
|
'Address generator calculated %s addresses'
|
||||||
|
@ -280,7 +283,7 @@ class addressGenerator(threading.Thread, StoppableThread):
|
||||||
# time.time() - startTime equaled zero.
|
# time.time() - startTime equaled zero.
|
||||||
pass
|
pass
|
||||||
address = encodeAddress(
|
address = encodeAddress(
|
||||||
addressVersionNumber, streamNumber, ripe.digest())
|
addressVersionNumber, streamNumber, ripe)
|
||||||
|
|
||||||
saveAddressToDisk = True
|
saveAddressToDisk = True
|
||||||
# If we are joining an existing chan, let us check
|
# If we are joining an existing chan, let us check
|
||||||
|
@ -357,13 +360,13 @@ class addressGenerator(threading.Thread, StoppableThread):
|
||||||
))
|
))
|
||||||
listOfNewAddressesToSendOutThroughTheAPI.append(
|
listOfNewAddressesToSendOutThroughTheAPI.append(
|
||||||
address)
|
address)
|
||||||
shared.myECCryptorObjects[ripe.digest()] = \
|
shared.myECCryptorObjects[ripe] = \
|
||||||
highlevelcrypto.makeCryptor(
|
highlevelcrypto.makeCryptor(
|
||||||
hexlify(potentialPrivEncryptionKey))
|
hexlify(potentialPrivEncryptionKey))
|
||||||
shared.myAddressesByHash[ripe.digest()] = address
|
shared.myAddressesByHash[ripe] = address
|
||||||
tag = hashlib.sha512(hashlib.sha512(
|
tag = hashlib.sha512(hashlib.sha512(
|
||||||
encodeVarint(addressVersionNumber) +
|
encodeVarint(addressVersionNumber) +
|
||||||
encodeVarint(streamNumber) + ripe.digest()
|
encodeVarint(streamNumber) + ripe
|
||||||
).digest()).digest()[32:]
|
).digest()).digest()[32:]
|
||||||
shared.myAddressesByTag[tag] = address
|
shared.myAddressesByTag[tag] = address
|
||||||
if addressVersionNumber == 3:
|
if addressVersionNumber == 3:
|
||||||
|
@ -371,7 +374,7 @@ class addressGenerator(threading.Thread, StoppableThread):
|
||||||
# the worker thread won't send out
|
# the worker thread won't send out
|
||||||
# the pubkey over the network.
|
# the pubkey over the network.
|
||||||
queues.workerQueue.put((
|
queues.workerQueue.put((
|
||||||
'sendOutOrStoreMyV3Pubkey', ripe.digest()))
|
'sendOutOrStoreMyV3Pubkey', ripe))
|
||||||
elif addressVersionNumber == 4:
|
elif addressVersionNumber == 4:
|
||||||
queues.workerQueue.put((
|
queues.workerQueue.put((
|
||||||
'sendOutOrStoreMyV4Pubkey', address))
|
'sendOutOrStoreMyV4Pubkey', address))
|
||||||
|
|
|
@ -24,6 +24,7 @@ import queues
|
||||||
import state
|
import state
|
||||||
import tr
|
import tr
|
||||||
from debug import logger
|
from debug import logger
|
||||||
|
from fallback import RIPEMD160Hash
|
||||||
import l10n
|
import l10n
|
||||||
|
|
||||||
|
|
||||||
|
@ -288,9 +289,7 @@ class objectProcessor(threading.Thread):
|
||||||
sha = hashlib.new('sha512')
|
sha = hashlib.new('sha512')
|
||||||
sha.update(
|
sha.update(
|
||||||
'\x04' + publicSigningKey + '\x04' + publicEncryptionKey)
|
'\x04' + publicSigningKey + '\x04' + publicEncryptionKey)
|
||||||
ripeHasher = hashlib.new('ripemd160')
|
ripe = RIPEMD160Hash(sha.digest()).digest()
|
||||||
ripeHasher.update(sha.digest())
|
|
||||||
ripe = ripeHasher.digest()
|
|
||||||
|
|
||||||
logger.debug(
|
logger.debug(
|
||||||
'within recpubkey, addressVersion: %s, streamNumber: %s'
|
'within recpubkey, addressVersion: %s, streamNumber: %s'
|
||||||
|
@ -354,9 +353,7 @@ class objectProcessor(threading.Thread):
|
||||||
|
|
||||||
sha = hashlib.new('sha512')
|
sha = hashlib.new('sha512')
|
||||||
sha.update(publicSigningKey + publicEncryptionKey)
|
sha.update(publicSigningKey + publicEncryptionKey)
|
||||||
ripeHasher = hashlib.new('ripemd160')
|
ripe = RIPEMD160Hash(sha.digest()).digest()
|
||||||
ripeHasher.update(sha.digest())
|
|
||||||
ripe = ripeHasher.digest()
|
|
||||||
|
|
||||||
logger.debug(
|
logger.debug(
|
||||||
'within recpubkey, addressVersion: %s, streamNumber: %s'
|
'within recpubkey, addressVersion: %s, streamNumber: %s'
|
||||||
|
@ -575,10 +572,9 @@ class objectProcessor(threading.Thread):
|
||||||
# calculate the fromRipe.
|
# calculate the fromRipe.
|
||||||
sha = hashlib.new('sha512')
|
sha = hashlib.new('sha512')
|
||||||
sha.update(pubSigningKey + pubEncryptionKey)
|
sha.update(pubSigningKey + pubEncryptionKey)
|
||||||
ripe = hashlib.new('ripemd160')
|
ripe = RIPEMD160Hash(sha.digest()).digest()
|
||||||
ripe.update(sha.digest())
|
|
||||||
fromAddress = encodeAddress(
|
fromAddress = encodeAddress(
|
||||||
sendersAddressVersionNumber, sendersStreamNumber, ripe.digest())
|
sendersAddressVersionNumber, sendersStreamNumber, ripe)
|
||||||
|
|
||||||
# Let's store the public key in case we want to reply to this
|
# Let's store the public key in case we want to reply to this
|
||||||
# person.
|
# person.
|
||||||
|
@ -897,9 +893,7 @@ class objectProcessor(threading.Thread):
|
||||||
|
|
||||||
sha = hashlib.new('sha512')
|
sha = hashlib.new('sha512')
|
||||||
sha.update(sendersPubSigningKey + sendersPubEncryptionKey)
|
sha.update(sendersPubSigningKey + sendersPubEncryptionKey)
|
||||||
ripeHasher = hashlib.new('ripemd160')
|
calculatedRipe = RIPEMD160Hash(sha.digest()).digest()
|
||||||
ripeHasher.update(sha.digest())
|
|
||||||
calculatedRipe = ripeHasher.digest()
|
|
||||||
|
|
||||||
if broadcastVersion == 4:
|
if broadcastVersion == 4:
|
||||||
if toRipe != calculatedRipe:
|
if toRipe != calculatedRipe:
|
||||||
|
|
|
@ -162,37 +162,13 @@ def try_import(module, log_extra=False):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
# We need to check hashlib for RIPEMD-160, as it won't be available
|
def check_ripemd160():
|
||||||
# if OpenSSL is not linked against or the linked OpenSSL has RIPEMD
|
"""Check availability of the RIPEMD160 hash function"""
|
||||||
# disabled.
|
|
||||||
def check_hashlib():
|
|
||||||
"""Do hashlib check.
|
|
||||||
|
|
||||||
The hashlib module check with version as if it included or not
|
|
||||||
in The Python Standard library, it's a module containing an
|
|
||||||
interface to the most popular hashing algorithms. hashlib
|
|
||||||
implements some of the algorithms, however if OpenSSL
|
|
||||||
installed, hashlib is able to use this algorithms as well.
|
|
||||||
"""
|
|
||||||
if sys.hexversion < 0x020500F0:
|
|
||||||
logger.error(
|
|
||||||
'The hashlib module is not included in this version of Python.')
|
|
||||||
return False
|
|
||||||
import hashlib
|
|
||||||
if '_hashlib' not in hashlib.__dict__:
|
|
||||||
logger.error(
|
|
||||||
'The RIPEMD-160 hash algorithm is not available.'
|
|
||||||
' The hashlib module is not linked against OpenSSL.')
|
|
||||||
return False
|
|
||||||
try:
|
try:
|
||||||
hashlib.new('ripemd160')
|
from fallback import RIPEMD160Hash
|
||||||
except ValueError:
|
except ImportError:
|
||||||
logger.error(
|
|
||||||
'The RIPEMD-160 hash algorithm is not available.'
|
|
||||||
' The hashlib module utilizes an OpenSSL library with'
|
|
||||||
' RIPEMD disabled.')
|
|
||||||
return False
|
return False
|
||||||
return True
|
return RIPEMD160Hash is not None
|
||||||
|
|
||||||
|
|
||||||
def check_sqlite():
|
def check_sqlite():
|
||||||
|
@ -446,7 +422,7 @@ def check_dependencies(verbose=False, optional=False):
|
||||||
' or greater is required.')
|
' or greater is required.')
|
||||||
has_all_dependencies = False
|
has_all_dependencies = False
|
||||||
|
|
||||||
check_functions = [check_hashlib, check_sqlite, check_openssl]
|
check_functions = [check_ripemd160, check_sqlite, check_openssl]
|
||||||
if optional:
|
if optional:
|
||||||
check_functions.extend([check_msgpack, check_pyqt, check_curses])
|
check_functions.extend([check_msgpack, check_pyqt, check_curses])
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,26 @@
|
||||||
"""
|
"""
|
||||||
.. todo:: hello world
|
.. todo:: hello world
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import hashlib
|
||||||
|
|
||||||
|
# We need to check hashlib for RIPEMD-160, as it won't be available
|
||||||
|
# if OpenSSL is not linked against or the linked OpenSSL has RIPEMD
|
||||||
|
# disabled.
|
||||||
|
|
||||||
|
try:
|
||||||
|
hashlib.new('ripemd160')
|
||||||
|
except ValueError:
|
||||||
|
try:
|
||||||
|
from Crypto.Hash import RIPEMD
|
||||||
|
except ImportError:
|
||||||
|
RIPEMD160Hash = None
|
||||||
|
else:
|
||||||
|
RIPEMD160Hash = RIPEMD.RIPEMD160Hash
|
||||||
|
else:
|
||||||
|
def RIPEMD160Hash(data=None):
|
||||||
|
"""hashlib based RIPEMD160Hash"""
|
||||||
|
hasher = hashlib.new('ripemd160')
|
||||||
|
if data:
|
||||||
|
hasher.update(data)
|
||||||
|
return hasher
|
||||||
|
|
|
@ -25,6 +25,7 @@ from addresses import (
|
||||||
encodeVarint, decodeVarint, decodeAddress, varintDecodeError)
|
encodeVarint, decodeVarint, decodeAddress, varintDecodeError)
|
||||||
from bmconfigparser import BMConfigParser
|
from bmconfigparser import BMConfigParser
|
||||||
from debug import logger
|
from debug import logger
|
||||||
|
from fallback import RIPEMD160Hash
|
||||||
from helper_sql import sqlExecute
|
from helper_sql import sqlExecute
|
||||||
from version import softwareVersion
|
from version import softwareVersion
|
||||||
|
|
||||||
|
@ -411,9 +412,7 @@ def decryptAndCheckPubkeyPayload(data, address):
|
||||||
|
|
||||||
sha = hashlib.new('sha512')
|
sha = hashlib.new('sha512')
|
||||||
sha.update(publicSigningKey + publicEncryptionKey)
|
sha.update(publicSigningKey + publicEncryptionKey)
|
||||||
ripeHasher = hashlib.new('ripemd160')
|
embeddedRipe = RIPEMD160Hash(sha.digest()).digest()
|
||||||
ripeHasher.update(sha.digest())
|
|
||||||
embeddedRipe = ripeHasher.digest()
|
|
||||||
|
|
||||||
if embeddedRipe != ripe:
|
if embeddedRipe != ripe:
|
||||||
# Although this pubkey object had the tag were were looking for
|
# Although this pubkey object had the tag were were looking for
|
||||||
|
|
60
src/tests/test_crypto.py
Normal file
60
src/tests/test_crypto.py
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
"""
|
||||||
|
Test the alternatives for crypto primitives
|
||||||
|
"""
|
||||||
|
|
||||||
|
import hashlib
|
||||||
|
import unittest
|
||||||
|
from abc import ABCMeta, abstractmethod
|
||||||
|
from binascii import hexlify, unhexlify
|
||||||
|
|
||||||
|
try:
|
||||||
|
from Crypto.Hash import RIPEMD
|
||||||
|
except ImportError:
|
||||||
|
RIPEMD = None
|
||||||
|
|
||||||
|
|
||||||
|
# These keys are from addresses test script
|
||||||
|
sample_pubsigningkey = unhexlify(
|
||||||
|
'044a367f049ec16cb6b6118eb734a9962d10b8db59c890cd08f210c43ff08bdf09d'
|
||||||
|
'16f502ca26cd0713f38988a1237f1fc8fa07b15653c996dc4013af6d15505ce')
|
||||||
|
sample_pubencryptionkey = unhexlify(
|
||||||
|
'044597d59177fc1d89555d38915f581b5ff2286b39d022ca0283d2bdd5c36be5d3c'
|
||||||
|
'e7b9b97792327851a562752e4b79475d1f51f5a71352482b241227f45ed36a9')
|
||||||
|
|
||||||
|
sample_ripe = '003cd097eb7f35c87b5dc8b4538c22cb55312a9f'
|
||||||
|
|
||||||
|
_sha = hashlib.new('sha512')
|
||||||
|
_sha.update(sample_pubsigningkey + sample_pubencryptionkey)
|
||||||
|
|
||||||
|
pubkey_sha = _sha.digest()
|
||||||
|
|
||||||
|
|
||||||
|
class RIPEMD160TestCase(object):
|
||||||
|
"""Base class for RIPEMD160 test case"""
|
||||||
|
__metaclass__ = ABCMeta
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def _hashdigest(self, data):
|
||||||
|
"""RIPEMD160 digest implementation"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def test_hash_string(self):
|
||||||
|
"""Check RIPEMD160 hash function on string"""
|
||||||
|
self.assertEqual(hexlify(self._hashdigest(pubkey_sha)), sample_ripe)
|
||||||
|
|
||||||
|
|
||||||
|
class TestHashlib(RIPEMD160TestCase, unittest.TestCase):
|
||||||
|
"""RIPEMD160 test case for hashlib"""
|
||||||
|
@staticmethod
|
||||||
|
def _hashdigest(data):
|
||||||
|
hasher = hashlib.new('ripemd160')
|
||||||
|
hasher.update(data)
|
||||||
|
return hasher.digest()
|
||||||
|
|
||||||
|
|
||||||
|
@unittest.skipUnless(RIPEMD, 'pycrypto package not found')
|
||||||
|
class TestCrypto(RIPEMD160TestCase, unittest.TestCase):
|
||||||
|
"""RIPEMD160 test case for Crypto"""
|
||||||
|
@staticmethod
|
||||||
|
def _hashdigest(data):
|
||||||
|
return RIPEMD.RIPEMD160Hash(data).digest()
|
Reference in New Issue
Block a user