Skip to content
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

feat: keccak addresses #130

Merged
merged 1 commit into from
Jul 19, 2024
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
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
Loading