Skip to content

Commit

Permalink
feat: keccak addresses (#130)
Browse files Browse the repository at this point in the history
  • Loading branch information
alexbarnsley authored Jul 19, 2024
1 parent fa6560a commit 25c6867
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 53 deletions.
89 changes: 43 additions & 46 deletions crypto/identity/address.py
Original file line number Diff line number Diff line change
@@ -1,55 +1,73 @@
import hashlib
from binascii import unhexlify

from base58 import b58decode_check, b58encode_check
from crypto.identity.private_key import PrivateKey

from binary.unsigned_integer.writer import write_bit8
from Cryptodome.Hash import RIPEMD160, keccak
from coincurve import PrivateKey, PublicKey

from crypto.configuration.network import get_network
from crypto.identity.private_key import PrivateKey
def get_checksum_address(address):
"""Get checksum address
Args:
address (str): address to get checksum
Returns:
str: checksum address
"""
address = address.lower()

from Cryptodome.Hash import RIPEMD160
chars = list(address[2:])

def address_from_public_key(public_key, network_version=None):
expanded = bytearray(40)
for i in range(40):
expanded[i] = ord(chars[i])

hashed = keccak.new(data=bytes(expanded), digest_bits=256).digest()

for i in range(0, 40, 2):
if (hashed[i >> 1] >> 4) >= 8:
chars[i] = chars[i].upper()
if (hashed[i >> 1] & 0x0F) >= 8:
chars[i + 1] = chars[i + 1].upper()

return "0x" + ''.join(chars)

def address_from_public_key(public_key):
"""Get an address from a public key
Args:
public_key (str):
network_version (int, optional):
Returns:
bytes:
str: address
"""
if not network_version:
network = get_network()
network_version = network['version']

ripemd160 = RIPEMD160.new(data=unhexlify(public_key.encode()))
seed = write_bit8(network_version) + ripemd160.digest()
return b58encode_check(seed).decode()
public_key = PublicKey(bytes.fromhex(public_key)).format(compressed=False)[1:]

keccak_hash = keccak.new(
data=bytearray.fromhex(public_key.hex()),
digest_bits=256,
)

return get_checksum_address(unhexlify(keccak_hash.hexdigest()[22:]).hex())

def address_from_private_key(private_key, network_version=None):

def address_from_private_key(private_key):
"""Get an address from private key
Args:
private_key (string):
network_version (int, optional):
Returns:
TYPE: Description
"""
if not network_version:
network = get_network()
network_version = network['version']

private_key = PrivateKey.from_hex(private_key)
ripemd160 = RIPEMD160.new(data=unhexlify(private_key.public_key))
seed = write_bit8(network_version) + ripemd160.digest()
return b58encode_check(seed).decode()

return address_from_public_key(private_key.public_key.format(compressed=False).hex())


def address_from_passphrase(passphrase, network_version=None):
def address_from_passphrase(passphrase):
"""Get an address from passphrase
Args:
Expand All @@ -59,27 +77,6 @@ def address_from_passphrase(passphrase, network_version=None):
Returns:
string: address
"""
if not network_version:
network = get_network()
network_version = network['version']

private_key = hashlib.sha256(passphrase.encode()).hexdigest()
address = address_from_private_key(private_key, network_version)
address = address_from_private_key(private_key)
return address


def validate_address(address, network_version=None):
"""Validate a given address
Args:
address (str): address you wish to validate
network_version (None, optional): integer, version of the network
Returns:
bool:
"""
if not network_version:
network = get_network()
network_version = network['version']

return network_version == b58decode_check(address)[0]
3 changes: 1 addition & 2 deletions tests/identity/conftest.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import pytest


@pytest.fixture
def identity():
"""Identity fixture
Expand All @@ -9,7 +8,7 @@ def identity():
'data': {
'private_key': 'd8839c2432bfd0a67ef10a804ba991eabba19f154a3d707917681d45822a5712',
'public_key': '034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192',
'address': 'D61mfSggzbvQgTUe6JhYKH2doHaqJ3Dyib',
'address': '0xb0FF9213f7226bBB72b84dE16af86e56f1f38B01',
'wif': 'SGq4xLgZKCGxs7bjmwnBrWcT4C1ADFEermj846KC97FSv1WFD1dA'
},
'passphrase': 'this is a top secret passphrase'
Expand Down
6 changes: 1 addition & 5 deletions tests/identity/test_address.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import pytest
from crypto.identity.address import (
address_from_passphrase, address_from_private_key, address_from_public_key, validate_address
address_from_passphrase, address_from_private_key, address_from_public_key
)

def test_address_from_public_key(identity):
Expand All @@ -16,7 +16,3 @@ def test_address_from_private_key(identity):
def test_address_from_passphrase(identity):
address = address_from_passphrase(identity['passphrase'])
assert address == identity['data']['address']


def test_validate_address(identity):
assert validate_address(identity['data']['address']) is True

0 comments on commit 25c6867

Please sign in to comment.