Skip to content

Commit

Permalink
Merge pull request #69 from pjkundert/fix-keccak
Browse files Browse the repository at this point in the history
Update from pysha3 (deprecated) to pycryptodome for Keccak-256
  • Loading branch information
meherett authored Nov 8, 2022
2 parents 86ff8d0 + 918e33f commit 4c9d2c5
Show file tree
Hide file tree
Showing 7 changed files with 111 additions and 14 deletions.
46 changes: 46 additions & 0 deletions GNUmakefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
SHELL = /bin/bash
PY3 ?= $(shell python3 --version >/dev/null 2>&1 && echo python3 || echo python )
VERSION = $(shell $(PY3) -c 'from hdwallet import __version__; print( __version__.strip("v"))')
WHEEL = dist/hdwallet-$(VERSION)-py3-none-any.whl

PY3TEST = $(PY3) -m pytest

.PHONY: all test build build-check wheel install-dev install clean FORCE

all: build

test:
$(PY3TEST)

# Run only tests with a prefix containing the target string, eg test-blah
test-%:
$(PY3TEST) *$*_test.py

unit-%:
$(PY3TEST) -k $*

build: clean wheel

build-check:
@$(PY3) -m build --version \
|| ( \
echo -e "\n\n!!! Missing Python modules; run:"; \
echo -e "\n\n $(PY3) -m pip install --upgrade pip setuptools wheel build\n"; \
false; \
)

wheel: $(WHEEL)

$(WHEEL): build-check FORCE
$(PY3) -m build
@ls -last dist

# Install from wheel, including all optional extra dependencies (except dev)
install-dev: $(WHEEL) FORCE
$(PY3) -m pip install --upgrade $<[tests]

install: $(WHEEL) FORCE
$(PY3) -m pip install --force-reinstall $<[cli,docs]

clean:
@rm -rf build dist *.egg-info $(shell find . -name '__pycache__' )
2 changes: 1 addition & 1 deletion hdwallet/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
)

# HDWallet Information's
__version__: str = "v2.1.1"
__version__: str = "v2.1.2"
__license__: str = "ISCL"
__author__: str = "Meheret Tesfaye Batu"
__email__: str = "[email protected]"
Expand Down
10 changes: 5 additions & 5 deletions hdwallet/hdwallet.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
import hmac
import ecdsa
import struct
import sha3
from Crypto.Hash import keccak
import unicodedata
import hashlib
import base58
Expand Down Expand Up @@ -433,7 +433,7 @@ def from_path(self, path: Union[str, Derivation]) -> "HDWallet":
if isinstance(path, Derivation):
path = str(path)
elif str(path)[0:2] != "m/":
raise ValueError("Bad path, please insert like this type of path \"m/0'/0\"! ")
raise ValueError("Bad path, please insert like this type of path \"m/0'/0\"!, not: %r" % ( path ))

for index in path.lstrip("m/").split("/"):
if "'" in index:
Expand Down Expand Up @@ -1101,17 +1101,17 @@ def p2pkh_address(self) -> str:
"""

if self._cryptocurrency.SYMBOL in ["ETH", "ETHTEST"]:
keccak_256 = sha3.keccak_256()
keccak_256 = keccak.new(digest_bits=256)
keccak_256.update(unhexlify(self.uncompressed()))
address = keccak_256.hexdigest()[24:]
return checksum_encode(address, crypto="eth")
elif self._cryptocurrency.SYMBOL in ["XDC", "XDCTEST"]:
keccak_256 = sha3.keccak_256()
keccak_256 = keccak.new(digest_bits=256)
keccak_256.update(unhexlify(self.uncompressed()))
address = keccak_256.hexdigest()[24:]
return checksum_encode(address, crypto="xdc")
elif self._cryptocurrency.SYMBOL in ["TRX"]:
keccak_256 = sha3.keccak_256()
keccak_256 = keccak.new(digest_bits=256)
keccak_256.update(unhexlify(self.uncompressed()))
address = keccak_256.hexdigest()[24:]
network_hash160_bytes = _unhexlify(self._cryptocurrency.PUBLIC_KEY_ADDRESS) + bytearray.fromhex(address)
Expand Down
8 changes: 4 additions & 4 deletions hdwallet/libs/base58.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from hashlib import sha256

import sha3
from Crypto.Hash import keccak
import six


Expand All @@ -13,10 +13,10 @@

def checksum_encode(address, crypto="eth"):
out = ""
keccak = sha3.keccak_256()
keccak_256 = keccak.new(digest_bits=256)
addr = address.lower().replace("0x", "") if crypto == "eth" else address.lower().replace("xdc", "")
keccak.update(addr.encode("ascii"))
hash_addr = keccak.hexdigest()
keccak_256.update(addr.encode("ascii"))
hash_addr = keccak_256.hexdigest()
for i, c in enumerate(addr):
if int(hash_addr[i], 16) >= 8:
out += c.upper()
Expand Down
4 changes: 2 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
ecdsa>=0.13,<1
mnemonic>=0.19,<1
pysha3>=1.0.2,<2
base58>=2.0.1,<3
pycryptodome>=3.15,<4
base58>=2.0.1,<3
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

setup(
name="hdwallet",
version="v2.1.1",
version="v2.1.2",
description="Python-based library for the implementation of a hierarchical deterministic wallet "
"generator for more than 140+ multiple cryptocurrencies.",
long_description=long_description,
Expand Down
53 changes: 52 additions & 1 deletion tests/test_base58.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import pytest

from hdwallet.libs.base58 import (
check_encode, check_decode, decode, encode, string_to_int
checksum_encode, check_encode, check_decode, decode, encode, string_to_int
)


Expand Down Expand Up @@ -35,3 +35,54 @@ def test_base58():


assert encode(decode("111233QC4")) == "111233QC4"

# Ensure ETH address checksums are correct; these are Keccak hash of the lower-case hex address,
# with hash results mapped onto the upper/lower case bits of the address.
eth = "0xfc2077CA7F403cBECA41B1B0F62D91B5EA631B5E"
eth_lower = eth.lower()
eth_check = checksum_encode( eth_lower )
assert eth_check == eth


def test_keccak():
"""Keccak 256 hash is required by several crypto algorithms. Ensure our hash implementations
are correct.
From: https://cryptobook.nakov.com/cryptographic-hash-functions/hash-functions-examples
"""
import hashlib, binascii

text = 'hello'
data = text.encode("utf8")

sha256hash = hashlib.sha256(data).digest()
print("SHA-256: ", binascii.hexlify(sha256hash))
assert binascii.hexlify(sha256hash) == b'2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824'

sha3_256 = hashlib.sha3_256(data).digest()
print("SHA3-256: ", binascii.hexlify(sha3_256))
assert binascii.hexlify(sha3_256) == b'3338be694f50c5f338814986cdf0686453a888b84f424d792af4b9202398f392'

blake2s = hashlib.new('blake2s', data).digest()
print("BLAKE2s: ", binascii.hexlify(blake2s))
assert binascii.hexlify(blake2s) == b'19213bacc58dee6dbde3ceb9a47cbb330b3d86f8cca8997eb00be456f140ca25'

ripemd160 = hashlib.new('ripemd160', data).digest()
print("RIPEMD-160:", binascii.hexlify(ripemd160))
assert binascii.hexlify(ripemd160) == b'108f07b8382412612c048d07d13f814118445acd'

# # Old pysha3 (deprecated) keccak-256 implementation
# from sha3 import keccak_256
# keccak256 = keccak_256()
# keccak256.update(data)
# keccak256_sha3 = keccak256.digest()
# print("Keccak256:", binascii.hexlify(keccak256_sha3), "(pysha3)")
# assert binascii.hexlify(keccak256_sha3) == b'1c8aff950685c2ed4bc3174f3472287b56d9517b9c948127319a09a7a36deac8'

# New pycryptodome keccak-256 implementation
from Crypto.Hash import keccak
keccak256_pycryptodome = keccak.new(data=data, digest_bits=256).digest()
print("Keccak256:", binascii.hexlify(keccak256_pycryptodome), " (pycryptodome)")
assert binascii.hexlify(keccak256_pycryptodome) == b'1c8aff950685c2ed4bc3174f3472287b56d9517b9c948127319a09a7a36deac8'

0 comments on commit 4c9d2c5

Please sign in to comment.