Skip to content

Update from pysha3 (deprecated) to pycryptodome for Keccak-256 #69

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Nov 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 = "meherett@zoho.com"
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'