Skip to content

Commit acb8c95

Browse files
author
Lee Miller
committed
Move RIPEMD160 hash to highlevelcrypto and export to_ripe() (closes: Bitmessage#1796)
1 parent 17b5c31 commit acb8c95

File tree

6 files changed

+56
-47
lines changed

6 files changed

+56
-47
lines changed

src/class_addressGenerator.py

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
"""
22
A thread for creating addresses
33
"""
4-
import hashlib
4+
55
import time
66
from binascii import hexlify
77

8+
from six.moves import configparser, queue
9+
810
import defaults
911
import highlevelcrypto
1012
import queues
@@ -13,9 +15,7 @@
1315
import tr
1416
from addresses import decodeAddress, encodeAddress, encodeVarint
1517
from bmconfigparser import config
16-
from fallback import RIPEMD160Hash
1718
from network import StoppableThread
18-
from six.moves import configparser, queue
1919

2020

2121
class AddressGeneratorException(Exception):
@@ -132,9 +132,8 @@ def run(self):
132132
numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix += 1
133133
potentialPrivEncryptionKey, potentialPubEncryptionKey = \
134134
highlevelcrypto.random_keys()
135-
sha = hashlib.new('sha512')
136-
sha.update(pubSigningKey + potentialPubEncryptionKey)
137-
ripe = RIPEMD160Hash(sha.digest()).digest()
135+
ripe = highlevelcrypto.to_ripe(
136+
pubSigningKey, potentialPubEncryptionKey)
138137
if (
139138
ripe[:numberOfNullBytesDemandedOnFrontOfRipeHash]
140139
== b'\x00' * numberOfNullBytesDemandedOnFrontOfRipeHash
@@ -241,10 +240,8 @@ def run(self):
241240

242241
signingKeyNonce += 2
243242
encryptionKeyNonce += 2
244-
sha = hashlib.new('sha512')
245-
sha.update(
246-
potentialPubSigningKey + potentialPubEncryptionKey)
247-
ripe = RIPEMD160Hash(sha.digest()).digest()
243+
ripe = highlevelcrypto.to_ripe(
244+
potentialPubSigningKey, potentialPubEncryptionKey)
248245
if (
249246
ripe[:numberOfNullBytesDemandedOnFrontOfRipeHash]
250247
== b'\x00' * numberOfNullBytesDemandedOnFrontOfRipeHash

src/class_objectProcessor.py

Lines changed: 13 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
encodeAddress, encodeVarint, varintDecodeError
2828
)
2929
from bmconfigparser import config
30-
from fallback import RIPEMD160Hash
3130
from helper_sql import sql_ready, SqlBulkExecute, sqlExecute, sqlQuery
3231
from network import bmproto, knownnodes
3332
from network.node import Peer
@@ -295,31 +294,28 @@ def processpubkey(self, data):
295294
'(within processpubkey) payloadLength less than 146.'
296295
' Sanity check failed.')
297296
readPosition += 4
298-
publicSigningKey = data[readPosition:readPosition + 64]
297+
pubSigningKey = '\x04' + data[readPosition:readPosition + 64]
299298
# Is it possible for a public key to be invalid such that trying to
300299
# encrypt or sign with it will cause an error? If it is, it would
301300
# be easiest to test them here.
302301
readPosition += 64
303-
publicEncryptionKey = data[readPosition:readPosition + 64]
304-
if len(publicEncryptionKey) < 64:
302+
pubEncryptionKey = '\x04' + data[readPosition:readPosition + 64]
303+
if len(pubEncryptionKey) < 65:
305304
return logger.debug(
306305
'publicEncryptionKey length less than 64. Sanity check'
307306
' failed.')
308307
readPosition += 64
309308
# The data we'll store in the pubkeys table.
310309
dataToStore = data[20:readPosition]
311-
sha = hashlib.new('sha512')
312-
sha.update(
313-
'\x04' + publicSigningKey + '\x04' + publicEncryptionKey)
314-
ripe = RIPEMD160Hash(sha.digest()).digest()
310+
ripe = highlevelcrypto.to_ripe(pubSigningKey, pubEncryptionKey)
315311

316312
if logger.isEnabledFor(logging.DEBUG):
317313
logger.debug(
318314
'within recpubkey, addressVersion: %s, streamNumber: %s'
319315
'\nripe %s\npublicSigningKey in hex: %s'
320316
'\npublicEncryptionKey in hex: %s',
321317
addressVersion, streamNumber, hexlify(ripe),
322-
hexlify(publicSigningKey), hexlify(publicEncryptionKey)
318+
hexlify(pubSigningKey), hexlify(pubEncryptionKey)
323319
)
324320

325321
address = encodeAddress(addressVersion, streamNumber, ripe)
@@ -349,9 +345,9 @@ def processpubkey(self, data):
349345
' Sanity check failed.')
350346
return
351347
readPosition += 4
352-
publicSigningKey = '\x04' + data[readPosition:readPosition + 64]
348+
pubSigningKey = '\x04' + data[readPosition:readPosition + 64]
353349
readPosition += 64
354-
publicEncryptionKey = '\x04' + data[readPosition:readPosition + 64]
350+
pubEncryptionKey = '\x04' + data[readPosition:readPosition + 64]
355351
readPosition += 64
356352
specifiedNonceTrialsPerByteLength = decodeVarint(
357353
data[readPosition:readPosition + 10])[1]
@@ -368,23 +364,21 @@ def processpubkey(self, data):
368364
signature = data[readPosition:readPosition + signatureLength]
369365
if highlevelcrypto.verify(
370366
data[8:endOfSignedDataPosition],
371-
signature, hexlify(publicSigningKey)):
367+
signature, hexlify(pubSigningKey)):
372368
logger.debug('ECDSA verify passed (within processpubkey)')
373369
else:
374370
logger.warning('ECDSA verify failed (within processpubkey)')
375371
return
376372

377-
sha = hashlib.new('sha512')
378-
sha.update(publicSigningKey + publicEncryptionKey)
379-
ripe = RIPEMD160Hash(sha.digest()).digest()
373+
ripe = highlevelcrypto.to_ripe(pubSigningKey, pubEncryptionKey)
380374

381375
if logger.isEnabledFor(logging.DEBUG):
382376
logger.debug(
383377
'within recpubkey, addressVersion: %s, streamNumber: %s'
384378
'\nripe %s\npublicSigningKey in hex: %s'
385379
'\npublicEncryptionKey in hex: %s',
386380
addressVersion, streamNumber, hexlify(ripe),
387-
hexlify(publicSigningKey), hexlify(publicEncryptionKey)
381+
hexlify(pubSigningKey), hexlify(pubEncryptionKey)
388382
)
389383

390384
address = encodeAddress(addressVersion, streamNumber, ripe)
@@ -583,9 +577,7 @@ def processmsg(self, data):
583577
sigHash = highlevelcrypto.double_sha512(signature)[32:]
584578

585579
# calculate the fromRipe.
586-
sha = hashlib.new('sha512')
587-
sha.update(pubSigningKey + pubEncryptionKey)
588-
ripe = RIPEMD160Hash(sha.digest()).digest()
580+
ripe = highlevelcrypto.to_ripe(pubSigningKey, pubEncryptionKey)
589581
fromAddress = encodeAddress(
590582
sendersAddressVersionNumber, sendersStreamNumber, ripe)
591583

@@ -873,9 +865,8 @@ def processbroadcast(self, data):
873865
requiredPayloadLengthExtraBytes)
874866
endOfPubkeyPosition = readPosition
875867

876-
sha = hashlib.new('sha512')
877-
sha.update(sendersPubSigningKey + sendersPubEncryptionKey)
878-
calculatedRipe = RIPEMD160Hash(sha.digest()).digest()
868+
calculatedRipe = highlevelcrypto.to_ripe(
869+
sendersPubSigningKey, sendersPubEncryptionKey)
879870

880871
if broadcastVersion == 4:
881872
if toRipe != calculatedRipe:

src/highlevelcrypto.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,27 @@
1414
from pyelliptic import ECC, OpenSSL
1515
from pyelliptic import arithmetic as a
1616

17+
from fallback import RIPEMD160Hash
1718

1819
__all__ = [
1920
'decodeWalletImportFormat', 'deterministic_keys',
2021
'double_sha512', 'calculateInventoryHash', 'encodeWalletImportFormat',
2122
'encrypt', 'makeCryptor', 'pointMult', 'privToPub', 'randomBytes',
22-
'random_keys', 'sign', 'verify']
23+
'random_keys', 'sign', 'to_ripe', 'verify']
2324

2425

2526
# Hashes
2627

28+
def _bm160(data):
29+
"""RIPEME160(SHA512(data)) -> bytes"""
30+
return RIPEMD160Hash(hashlib.sha512(data).digest()).digest()
31+
32+
33+
def to_ripe(signing_key, encryption_key):
34+
"""Convert two public keys to a ripe hash"""
35+
return _bm160(signing_key + encryption_key)
36+
37+
2738
def double_sha512(data):
2839
"""Binary double SHA512 digest"""
2940
return hashlib.sha512(hashlib.sha512(data).digest()).digest()

src/protocol.py

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
encodeVarint, decodeVarint, decodeAddress, varintDecodeError)
2121
from bmconfigparser import config
2222
from debug import logger
23-
from fallback import RIPEMD160Hash
2423
from helper_sql import sqlExecute
2524
from version import softwareVersion
2625

@@ -458,9 +457,9 @@ def decryptAndCheckPubkeyPayload(data, address):
458457
readPosition = 0
459458
# bitfieldBehaviors = decryptedData[readPosition:readPosition + 4]
460459
readPosition += 4
461-
publicSigningKey = '\x04' + decryptedData[readPosition:readPosition + 64]
460+
pubSigningKey = '\x04' + decryptedData[readPosition:readPosition + 64]
462461
readPosition += 64
463-
publicEncryptionKey = '\x04' + decryptedData[readPosition:readPosition + 64]
462+
pubEncryptionKey = '\x04' + decryptedData[readPosition:readPosition + 64]
464463
readPosition += 64
465464
specifiedNonceTrialsPerByteLength = decodeVarint(
466465
decryptedData[readPosition:readPosition + 10])[1]
@@ -476,17 +475,15 @@ def decryptAndCheckPubkeyPayload(data, address):
476475
signature = decryptedData[readPosition:readPosition + signatureLength]
477476

478477
if not highlevelcrypto.verify(
479-
signedData, signature, hexlify(publicSigningKey)):
478+
signedData, signature, hexlify(pubSigningKey)):
480479
logger.info(
481480
'ECDSA verify failed (within decryptAndCheckPubkeyPayload)')
482481
return 'failed'
483482

484483
logger.info(
485484
'ECDSA verify passed (within decryptAndCheckPubkeyPayload)')
486485

487-
sha = hashlib.new('sha512')
488-
sha.update(publicSigningKey + publicEncryptionKey)
489-
embeddedRipe = RIPEMD160Hash(sha.digest()).digest()
486+
embeddedRipe = highlevelcrypto.to_ripe(pubSigningKey, pubEncryptionKey)
490487

491488
if embeddedRipe != ripe:
492489
# Although this pubkey object had the tag were were looking for
@@ -504,7 +501,7 @@ def decryptAndCheckPubkeyPayload(data, address):
504501
'addressVersion: %s, streamNumber: %s\nripe %s\n'
505502
'publicSigningKey in hex: %s\npublicEncryptionKey in hex: %s',
506503
addressVersion, streamNumber, hexlify(ripe),
507-
hexlify(publicSigningKey), hexlify(publicEncryptionKey)
504+
hexlify(pubSigningKey), hexlify(pubEncryptionKey)
508505
)
509506

510507
t = (address, addressVersion, storedData, int(time.time()), 'yes')

src/tests/samples.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
'0592a10584ffabf96539f3d780d776828c67da1ab5b169e9e8aed838aaecc9ed36d49ff14'
99
'23c55f019e050c66c6324f53588be88894fef4dcffdb74b98e2b200')
1010

11+
sample_bm160 = unhexlify('79a324faeebcbf9849f310545ed531556882487e')
1112

1213
magic = 0xE9BEB4D9
1314

src/tests/test_crypto.py

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@
1717
RIPEMD160 = None
1818

1919
from .samples import (
20-
sample_deterministic_ripe, sample_double_sha512, sample_hash_data,
21-
sample_msg, sample_pubsigningkey, sample_pubencryptionkey,
22-
sample_privsigningkey, sample_privencryptionkey, sample_ripe,
23-
sample_seed, sample_sig, sample_sig_sha1
20+
sample_bm160, sample_deterministic_ripe, sample_double_sha512,
21+
sample_hash_data, sample_msg, sample_pubsigningkey,
22+
sample_pubencryptionkey, sample_privsigningkey, sample_privencryptionkey,
23+
sample_ripe, sample_seed, sample_sig, sample_sig_sha1
2424
)
2525

2626

@@ -73,6 +73,19 @@ def test_double_sha512(self):
7373
highlevelcrypto.double_sha512(sample_hash_data),
7474
sample_double_sha512)
7575

76+
def test_bm160(self):
77+
"""Formally check highlevelcrypto._bm160()"""
78+
# pylint: disable=protected-access
79+
self.assertEqual(
80+
highlevelcrypto._bm160(sample_hash_data), sample_bm160)
81+
82+
def test_to_ripe(self):
83+
"""Formally check highlevelcrypto.to_ripe()"""
84+
self.assertEqual(
85+
hexlify(highlevelcrypto.to_ripe(
86+
sample_pubsigningkey, sample_pubencryptionkey)),
87+
sample_ripe)
88+
7689
def test_randomBytes(self):
7790
"""Dummy checks for random bytes"""
7891
for n in (8, 32, 64):
@@ -94,8 +107,7 @@ def test_deterministic_keys(self):
94107
enkey = highlevelcrypto.deterministic_keys(sample_seed, b'+')[1]
95108
self.assertEqual(
96109
sample_deterministic_ripe,
97-
hexlify(TestHashlib._hashdigest(
98-
hashlib.sha512(sigkey + enkey).digest())))
110+
hexlify(highlevelcrypto.to_ripe(sigkey, enkey)))
99111

100112
def test_signatures(self):
101113
"""Verify sample signatures and newly generated ones"""

0 commit comments

Comments
 (0)