Skip to content

Commit 3a04e35

Browse files
author
Lee Miller
committed
Move RIPEMD160 hash to highlevelcrypto and export to_ripe() (closes: #1796)
1 parent 41fd17b commit 3a04e35

6 files changed

+55
-47
lines changed

src/class_addressGenerator.py

+5-9
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"""
22
A thread for creating addresses
33
"""
4-
import hashlib
4+
55
import time
66
from binascii import hexlify
77

@@ -14,7 +14,6 @@
1414
import state
1515
from addresses import decodeAddress, encodeAddress, encodeVarint
1616
from bmconfigparser import config
17-
from fallback import RIPEMD160Hash
1817
from network import StoppableThread
1918
from tr import _translate
2019

@@ -133,9 +132,8 @@ def run(self):
133132
numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix += 1
134133
potentialPrivEncryptionKey, potentialPubEncryptionKey = \
135134
highlevelcrypto.random_keys()
136-
sha = hashlib.new('sha512')
137-
sha.update(pubSigningKey + potentialPubEncryptionKey)
138-
ripe = RIPEMD160Hash(sha.digest()).digest()
135+
ripe = highlevelcrypto.to_ripe(
136+
pubSigningKey, potentialPubEncryptionKey)
139137
if (
140138
ripe[:numberOfNullBytesDemandedOnFrontOfRipeHash]
141139
== b'\x00' * numberOfNullBytesDemandedOnFrontOfRipeHash
@@ -244,10 +242,8 @@ def run(self):
244242

245243
signingKeyNonce += 2
246244
encryptionKeyNonce += 2
247-
sha = hashlib.new('sha512')
248-
sha.update(
249-
potentialPubSigningKey + potentialPubEncryptionKey)
250-
ripe = RIPEMD160Hash(sha.digest()).digest()
245+
ripe = highlevelcrypto.to_ripe(
246+
potentialPubSigningKey, potentialPubEncryptionKey)
251247
if (
252248
ripe[:numberOfNullBytesDemandedOnFrontOfRipeHash]
253249
== b'\x00' * numberOfNullBytesDemandedOnFrontOfRipeHash

src/class_objectProcessor.py

+13-22
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
encodeAddress, encodeVarint, varintDecodeError
2929
)
3030
from bmconfigparser import config
31-
from fallback import RIPEMD160Hash
3231
from helper_sql import (
3332
sql_ready, sql_timeout, SqlBulkExecute, sqlExecute, sqlQuery)
3433
from network import knownnodes
@@ -300,31 +299,28 @@ def processpubkey(self, data):
300299
'(within processpubkey) payloadLength less than 146.'
301300
' Sanity check failed.')
302301
readPosition += 4
303-
publicSigningKey = data[readPosition:readPosition + 64]
302+
pubSigningKey = '\x04' + data[readPosition:readPosition + 64]
304303
# Is it possible for a public key to be invalid such that trying to
305304
# encrypt or sign with it will cause an error? If it is, it would
306305
# be easiest to test them here.
307306
readPosition += 64
308-
publicEncryptionKey = data[readPosition:readPosition + 64]
309-
if len(publicEncryptionKey) < 64:
307+
pubEncryptionKey = '\x04' + data[readPosition:readPosition + 64]
308+
if len(pubEncryptionKey) < 65:
310309
return logger.debug(
311310
'publicEncryptionKey length less than 64. Sanity check'
312311
' failed.')
313312
readPosition += 64
314313
# The data we'll store in the pubkeys table.
315314
dataToStore = data[20:readPosition]
316-
sha = hashlib.new('sha512')
317-
sha.update(
318-
'\x04' + publicSigningKey + '\x04' + publicEncryptionKey)
319-
ripe = RIPEMD160Hash(sha.digest()).digest()
315+
ripe = highlevelcrypto.to_ripe(pubSigningKey, pubEncryptionKey)
320316

321317
if logger.isEnabledFor(logging.DEBUG):
322318
logger.debug(
323319
'within recpubkey, addressVersion: %s, streamNumber: %s'
324320
'\nripe %s\npublicSigningKey in hex: %s'
325321
'\npublicEncryptionKey in hex: %s',
326322
addressVersion, streamNumber, hexlify(ripe),
327-
hexlify(publicSigningKey), hexlify(publicEncryptionKey)
323+
hexlify(pubSigningKey), hexlify(pubEncryptionKey)
328324
)
329325

330326
address = encodeAddress(addressVersion, streamNumber, ripe)
@@ -354,9 +350,9 @@ def processpubkey(self, data):
354350
' Sanity check failed.')
355351
return
356352
readPosition += 4
357-
publicSigningKey = '\x04' + data[readPosition:readPosition + 64]
353+
pubSigningKey = '\x04' + data[readPosition:readPosition + 64]
358354
readPosition += 64
359-
publicEncryptionKey = '\x04' + data[readPosition:readPosition + 64]
355+
pubEncryptionKey = '\x04' + data[readPosition:readPosition + 64]
360356
readPosition += 64
361357
specifiedNonceTrialsPerByteLength = decodeVarint(
362358
data[readPosition:readPosition + 10])[1]
@@ -373,23 +369,21 @@ def processpubkey(self, data):
373369
signature = data[readPosition:readPosition + signatureLength]
374370
if highlevelcrypto.verify(
375371
data[8:endOfSignedDataPosition],
376-
signature, hexlify(publicSigningKey)):
372+
signature, hexlify(pubSigningKey)):
377373
logger.debug('ECDSA verify passed (within processpubkey)')
378374
else:
379375
logger.warning('ECDSA verify failed (within processpubkey)')
380376
return
381377

382-
sha = hashlib.new('sha512')
383-
sha.update(publicSigningKey + publicEncryptionKey)
384-
ripe = RIPEMD160Hash(sha.digest()).digest()
378+
ripe = highlevelcrypto.to_ripe(pubSigningKey, pubEncryptionKey)
385379

386380
if logger.isEnabledFor(logging.DEBUG):
387381
logger.debug(
388382
'within recpubkey, addressVersion: %s, streamNumber: %s'
389383
'\nripe %s\npublicSigningKey in hex: %s'
390384
'\npublicEncryptionKey in hex: %s',
391385
addressVersion, streamNumber, hexlify(ripe),
392-
hexlify(publicSigningKey), hexlify(publicEncryptionKey)
386+
hexlify(pubSigningKey), hexlify(pubEncryptionKey)
393387
)
394388

395389
address = encodeAddress(addressVersion, streamNumber, ripe)
@@ -588,9 +582,7 @@ def processmsg(self, data):
588582
sigHash = highlevelcrypto.double_sha512(signature)[32:]
589583

590584
# calculate the fromRipe.
591-
sha = hashlib.new('sha512')
592-
sha.update(pubSigningKey + pubEncryptionKey)
593-
ripe = RIPEMD160Hash(sha.digest()).digest()
585+
ripe = highlevelcrypto.to_ripe(pubSigningKey, pubEncryptionKey)
594586
fromAddress = encodeAddress(
595587
sendersAddressVersionNumber, sendersStreamNumber, ripe)
596588

@@ -883,9 +875,8 @@ def processbroadcast(self, data):
883875
requiredPayloadLengthExtraBytes)
884876
endOfPubkeyPosition = readPosition
885877

886-
sha = hashlib.new('sha512')
887-
sha.update(sendersPubSigningKey + sendersPubEncryptionKey)
888-
calculatedRipe = RIPEMD160Hash(sha.digest()).digest()
878+
calculatedRipe = highlevelcrypto.to_ripe(
879+
sendersPubSigningKey, sendersPubEncryptionKey)
889880

890881
if broadcastVersion == 4:
891882
if toRipe != calculatedRipe:

src/highlevelcrypto.py

+12-1
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,13 @@
1515
from pyelliptic import OpenSSL
1616
from pyelliptic import arithmetic as a
1717

18+
from fallback import RIPEMD160Hash
1819

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

2526

2627
# WIF (uses arithmetic ):
@@ -64,6 +65,16 @@ def randomBytes(n):
6465

6566
# Hashes
6667

68+
def _bm160(data):
69+
"""RIPEME160(SHA512(data)) -> bytes"""
70+
return RIPEMD160Hash(hashlib.sha512(data).digest()).digest()
71+
72+
73+
def to_ripe(signing_key, encryption_key):
74+
"""Convert two public keys to a ripe hash"""
75+
return _bm160(signing_key + encryption_key)
76+
77+
6778
def double_sha512(data):
6879
"""Binary double SHA512 digest"""
6980
return hashlib.sha512(hashlib.sha512(data).digest()).digest()

src/protocol.py

+5-8
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 network.node import Peer
2625
from version import softwareVersion
@@ -512,9 +511,9 @@ def decryptAndCheckPubkeyPayload(data, address):
512511
readPosition = 0
513512
# bitfieldBehaviors = decryptedData[readPosition:readPosition + 4]
514513
readPosition += 4
515-
publicSigningKey = '\x04' + decryptedData[readPosition:readPosition + 64]
514+
pubSigningKey = '\x04' + decryptedData[readPosition:readPosition + 64]
516515
readPosition += 64
517-
publicEncryptionKey = '\x04' + decryptedData[readPosition:readPosition + 64]
516+
pubEncryptionKey = '\x04' + decryptedData[readPosition:readPosition + 64]
518517
readPosition += 64
519518
specifiedNonceTrialsPerByteLength = decodeVarint(
520519
decryptedData[readPosition:readPosition + 10])[1]
@@ -530,17 +529,15 @@ def decryptAndCheckPubkeyPayload(data, address):
530529
signature = decryptedData[readPosition:readPosition + signatureLength]
531530

532531
if not highlevelcrypto.verify(
533-
signedData, signature, hexlify(publicSigningKey)):
532+
signedData, signature, hexlify(pubSigningKey)):
534533
logger.info(
535534
'ECDSA verify failed (within decryptAndCheckPubkeyPayload)')
536535
return 'failed'
537536

538537
logger.info(
539538
'ECDSA verify passed (within decryptAndCheckPubkeyPayload)')
540539

541-
sha = hashlib.new('sha512')
542-
sha.update(publicSigningKey + publicEncryptionKey)
543-
embeddedRipe = RIPEMD160Hash(sha.digest()).digest()
540+
embeddedRipe = highlevelcrypto.to_ripe(pubSigningKey, pubEncryptionKey)
544541

545542
if embeddedRipe != ripe:
546543
# Although this pubkey object had the tag were were looking for
@@ -558,7 +555,7 @@ def decryptAndCheckPubkeyPayload(data, address):
558555
'addressVersion: %s, streamNumber: %s\nripe %s\n'
559556
'publicSigningKey in hex: %s\npublicEncryptionKey in hex: %s',
560557
addressVersion, streamNumber, hexlify(ripe),
561-
hexlify(publicSigningKey), hexlify(publicEncryptionKey)
558+
hexlify(pubSigningKey), hexlify(pubEncryptionKey)
562559
)
563560

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

src/tests/samples.py

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
'0592a10584ffabf96539f3d780d776828c67da1ab5b169e9e8aed838aaecc9ed36d49ff14'
99
'23c55f019e050c66c6324f53588be88894fef4dcffdb74b98e2b200')
1010

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

1213
# 500 identical peers:
1314
# 1626611891, 1, 1, 127.0.0.1, 8444

src/tests/test_crypto.py

+19-7
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from abc import ABCMeta, abstractmethod
99
from binascii import hexlify
1010

11-
from pybitmessage import highlevelcrypto, fallback
11+
from pybitmessage import highlevelcrypto
1212

1313

1414
try:
@@ -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(fallback.RIPEMD160Hash(
98-
hashlib.sha512(sigkey + enkey).digest()).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)