Move RIPEMD160 hash to highlevelcrypto and export to_ripe() (closes: #1796)

This commit is contained in:
Lee Miller 2022-05-31 00:57:55 +03:00
parent 41fd17b637
commit 3a04e351cc
Signed by untrusted user: lee.miller
GPG Key ID: 4F97A5EA88F4AB63
6 changed files with 55 additions and 47 deletions

View File

@ -1,7 +1,7 @@
"""
A thread for creating addresses
"""
import hashlib
import time
from binascii import hexlify
@ -14,7 +14,6 @@ import shared
import state
from addresses import decodeAddress, encodeAddress, encodeVarint
from bmconfigparser import config
from fallback import RIPEMD160Hash
from network import StoppableThread
from tr import _translate
@ -133,9 +132,8 @@ class addressGenerator(StoppableThread):
numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix += 1
potentialPrivEncryptionKey, potentialPubEncryptionKey = \
highlevelcrypto.random_keys()
sha = hashlib.new('sha512')
sha.update(pubSigningKey + potentialPubEncryptionKey)
ripe = RIPEMD160Hash(sha.digest()).digest()
ripe = highlevelcrypto.to_ripe(
pubSigningKey, potentialPubEncryptionKey)
if (
ripe[:numberOfNullBytesDemandedOnFrontOfRipeHash]
== b'\x00' * numberOfNullBytesDemandedOnFrontOfRipeHash
@ -244,10 +242,8 @@ class addressGenerator(StoppableThread):
signingKeyNonce += 2
encryptionKeyNonce += 2
sha = hashlib.new('sha512')
sha.update(
potentialPubSigningKey + potentialPubEncryptionKey)
ripe = RIPEMD160Hash(sha.digest()).digest()
ripe = highlevelcrypto.to_ripe(
potentialPubSigningKey, potentialPubEncryptionKey)
if (
ripe[:numberOfNullBytesDemandedOnFrontOfRipeHash]
== b'\x00' * numberOfNullBytesDemandedOnFrontOfRipeHash

View File

@ -28,7 +28,6 @@ from addresses import (
encodeAddress, encodeVarint, varintDecodeError
)
from bmconfigparser import config
from fallback import RIPEMD160Hash
from helper_sql import (
sql_ready, sql_timeout, SqlBulkExecute, sqlExecute, sqlQuery)
from network import knownnodes
@ -300,23 +299,20 @@ class objectProcessor(threading.Thread):
'(within processpubkey) payloadLength less than 146.'
' Sanity check failed.')
readPosition += 4
publicSigningKey = data[readPosition:readPosition + 64]
pubSigningKey = '\x04' + data[readPosition:readPosition + 64]
# Is it possible for a public key to be invalid such that trying to
# encrypt or sign with it will cause an error? If it is, it would
# be easiest to test them here.
readPosition += 64
publicEncryptionKey = data[readPosition:readPosition + 64]
if len(publicEncryptionKey) < 64:
pubEncryptionKey = '\x04' + data[readPosition:readPosition + 64]
if len(pubEncryptionKey) < 65:
return logger.debug(
'publicEncryptionKey length less than 64. Sanity check'
' failed.')
readPosition += 64
# The data we'll store in the pubkeys table.
dataToStore = data[20:readPosition]
sha = hashlib.new('sha512')
sha.update(
'\x04' + publicSigningKey + '\x04' + publicEncryptionKey)
ripe = RIPEMD160Hash(sha.digest()).digest()
ripe = highlevelcrypto.to_ripe(pubSigningKey, pubEncryptionKey)
if logger.isEnabledFor(logging.DEBUG):
logger.debug(
@ -324,7 +320,7 @@ class objectProcessor(threading.Thread):
'\nripe %s\npublicSigningKey in hex: %s'
'\npublicEncryptionKey in hex: %s',
addressVersion, streamNumber, hexlify(ripe),
hexlify(publicSigningKey), hexlify(publicEncryptionKey)
hexlify(pubSigningKey), hexlify(pubEncryptionKey)
)
address = encodeAddress(addressVersion, streamNumber, ripe)
@ -354,9 +350,9 @@ class objectProcessor(threading.Thread):
' Sanity check failed.')
return
readPosition += 4
publicSigningKey = '\x04' + data[readPosition:readPosition + 64]
pubSigningKey = '\x04' + data[readPosition:readPosition + 64]
readPosition += 64
publicEncryptionKey = '\x04' + data[readPosition:readPosition + 64]
pubEncryptionKey = '\x04' + data[readPosition:readPosition + 64]
readPosition += 64
specifiedNonceTrialsPerByteLength = decodeVarint(
data[readPosition:readPosition + 10])[1]
@ -373,15 +369,13 @@ class objectProcessor(threading.Thread):
signature = data[readPosition:readPosition + signatureLength]
if highlevelcrypto.verify(
data[8:endOfSignedDataPosition],
signature, hexlify(publicSigningKey)):
signature, hexlify(pubSigningKey)):
logger.debug('ECDSA verify passed (within processpubkey)')
else:
logger.warning('ECDSA verify failed (within processpubkey)')
return
sha = hashlib.new('sha512')
sha.update(publicSigningKey + publicEncryptionKey)
ripe = RIPEMD160Hash(sha.digest()).digest()
ripe = highlevelcrypto.to_ripe(pubSigningKey, pubEncryptionKey)
if logger.isEnabledFor(logging.DEBUG):
logger.debug(
@ -389,7 +383,7 @@ class objectProcessor(threading.Thread):
'\nripe %s\npublicSigningKey in hex: %s'
'\npublicEncryptionKey in hex: %s',
addressVersion, streamNumber, hexlify(ripe),
hexlify(publicSigningKey), hexlify(publicEncryptionKey)
hexlify(pubSigningKey), hexlify(pubEncryptionKey)
)
address = encodeAddress(addressVersion, streamNumber, ripe)
@ -588,9 +582,7 @@ class objectProcessor(threading.Thread):
sigHash = highlevelcrypto.double_sha512(signature)[32:]
# calculate the fromRipe.
sha = hashlib.new('sha512')
sha.update(pubSigningKey + pubEncryptionKey)
ripe = RIPEMD160Hash(sha.digest()).digest()
ripe = highlevelcrypto.to_ripe(pubSigningKey, pubEncryptionKey)
fromAddress = encodeAddress(
sendersAddressVersionNumber, sendersStreamNumber, ripe)
@ -883,9 +875,8 @@ class objectProcessor(threading.Thread):
requiredPayloadLengthExtraBytes)
endOfPubkeyPosition = readPosition
sha = hashlib.new('sha512')
sha.update(sendersPubSigningKey + sendersPubEncryptionKey)
calculatedRipe = RIPEMD160Hash(sha.digest()).digest()
calculatedRipe = highlevelcrypto.to_ripe(
sendersPubSigningKey, sendersPubEncryptionKey)
if broadcastVersion == 4:
if toRipe != calculatedRipe:

View File

@ -15,12 +15,13 @@ import pyelliptic
from pyelliptic import OpenSSL
from pyelliptic import arithmetic as a
from fallback import RIPEMD160Hash
__all__ = [
'decodeWalletImportFormat', 'deterministic_keys',
'double_sha512', 'calculateInventoryHash', 'encodeWalletImportFormat',
'encrypt', 'makeCryptor', 'pointMult', 'privToPub', 'randomBytes',
'random_keys', 'sign', 'verify']
'random_keys', 'sign', 'to_ripe', 'verify']
# WIF (uses arithmetic ):
@ -64,6 +65,16 @@ def randomBytes(n):
# Hashes
def _bm160(data):
"""RIPEME160(SHA512(data)) -> bytes"""
return RIPEMD160Hash(hashlib.sha512(data).digest()).digest()
def to_ripe(signing_key, encryption_key):
"""Convert two public keys to a ripe hash"""
return _bm160(signing_key + encryption_key)
def double_sha512(data):
"""Binary double SHA512 digest"""
return hashlib.sha512(hashlib.sha512(data).digest()).digest()

View File

@ -20,7 +20,6 @@ from addresses import (
encodeVarint, decodeVarint, decodeAddress, varintDecodeError)
from bmconfigparser import config
from debug import logger
from fallback import RIPEMD160Hash
from helper_sql import sqlExecute
from network.node import Peer
from version import softwareVersion
@ -512,9 +511,9 @@ def decryptAndCheckPubkeyPayload(data, address):
readPosition = 0
# bitfieldBehaviors = decryptedData[readPosition:readPosition + 4]
readPosition += 4
publicSigningKey = '\x04' + decryptedData[readPosition:readPosition + 64]
pubSigningKey = '\x04' + decryptedData[readPosition:readPosition + 64]
readPosition += 64
publicEncryptionKey = '\x04' + decryptedData[readPosition:readPosition + 64]
pubEncryptionKey = '\x04' + decryptedData[readPosition:readPosition + 64]
readPosition += 64
specifiedNonceTrialsPerByteLength = decodeVarint(
decryptedData[readPosition:readPosition + 10])[1]
@ -530,7 +529,7 @@ def decryptAndCheckPubkeyPayload(data, address):
signature = decryptedData[readPosition:readPosition + signatureLength]
if not highlevelcrypto.verify(
signedData, signature, hexlify(publicSigningKey)):
signedData, signature, hexlify(pubSigningKey)):
logger.info(
'ECDSA verify failed (within decryptAndCheckPubkeyPayload)')
return 'failed'
@ -538,9 +537,7 @@ def decryptAndCheckPubkeyPayload(data, address):
logger.info(
'ECDSA verify passed (within decryptAndCheckPubkeyPayload)')
sha = hashlib.new('sha512')
sha.update(publicSigningKey + publicEncryptionKey)
embeddedRipe = RIPEMD160Hash(sha.digest()).digest()
embeddedRipe = highlevelcrypto.to_ripe(pubSigningKey, pubEncryptionKey)
if embeddedRipe != ripe:
# Although this pubkey object had the tag were were looking for
@ -558,7 +555,7 @@ def decryptAndCheckPubkeyPayload(data, address):
'addressVersion: %s, streamNumber: %s\nripe %s\n'
'publicSigningKey in hex: %s\npublicEncryptionKey in hex: %s',
addressVersion, streamNumber, hexlify(ripe),
hexlify(publicSigningKey), hexlify(publicEncryptionKey)
hexlify(pubSigningKey), hexlify(pubEncryptionKey)
)
t = (address, addressVersion, storedData, int(time.time()), 'yes')

View File

@ -8,6 +8,7 @@ sample_double_sha512 = unhexlify(
'0592a10584ffabf96539f3d780d776828c67da1ab5b169e9e8aed838aaecc9ed36d49ff14'
'23c55f019e050c66c6324f53588be88894fef4dcffdb74b98e2b200')
sample_bm160 = unhexlify('79a324faeebcbf9849f310545ed531556882487e')
# 500 identical peers:
# 1626611891, 1, 1, 127.0.0.1, 8444

View File

@ -8,7 +8,7 @@ import unittest
from abc import ABCMeta, abstractmethod
from binascii import hexlify
from pybitmessage import highlevelcrypto, fallback
from pybitmessage import highlevelcrypto
try:
@ -17,10 +17,10 @@ except ImportError:
RIPEMD160 = None
from .samples import (
sample_deterministic_ripe, sample_double_sha512, sample_hash_data,
sample_msg, sample_pubsigningkey, sample_pubencryptionkey,
sample_privsigningkey, sample_privencryptionkey, sample_ripe,
sample_seed, sample_sig, sample_sig_sha1
sample_bm160, sample_deterministic_ripe, sample_double_sha512,
sample_hash_data, sample_msg, sample_pubsigningkey,
sample_pubencryptionkey, sample_privsigningkey, sample_privencryptionkey,
sample_ripe, sample_seed, sample_sig, sample_sig_sha1
)
@ -73,6 +73,19 @@ class TestHighlevelcrypto(unittest.TestCase):
highlevelcrypto.double_sha512(sample_hash_data),
sample_double_sha512)
def test_bm160(self):
"""Formally check highlevelcrypto._bm160()"""
# pylint: disable=protected-access
self.assertEqual(
highlevelcrypto._bm160(sample_hash_data), sample_bm160)
def test_to_ripe(self):
"""Formally check highlevelcrypto.to_ripe()"""
self.assertEqual(
hexlify(highlevelcrypto.to_ripe(
sample_pubsigningkey, sample_pubencryptionkey)),
sample_ripe)
def test_randomBytes(self):
"""Dummy checks for random bytes"""
for n in (8, 32, 64):
@ -94,8 +107,7 @@ class TestHighlevelcrypto(unittest.TestCase):
enkey = highlevelcrypto.deterministic_keys(sample_seed, b'+')[1]
self.assertEqual(
sample_deterministic_ripe,
hexlify(fallback.RIPEMD160Hash(
hashlib.sha512(sigkey + enkey).digest()).digest()))
hexlify(highlevelcrypto.to_ripe(sigkey, enkey)))
def test_signatures(self):
"""Verify sample signatures and newly generated ones"""