mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-24 07:18:09 +00:00
ripple: get address
This commit is contained in:
parent
51d810b6da
commit
b5c2ae49dd
@ -32,4 +32,4 @@ known_standard_library = micropython,ubinascii,ustruct,uctypes,utime,utimeq,trez
|
||||
[tool:pytest]
|
||||
addopts = --pyargs trezorlib.tests.device_tests
|
||||
xfail_strict = true
|
||||
run_xfail =
|
||||
run_xfail = ripple
|
||||
|
13
src/apps/ripple/__init__.py
Normal file
13
src/apps/ripple/__init__.py
Normal file
@ -0,0 +1,13 @@
|
||||
from trezor.wire import register, protobuf_workflow
|
||||
from trezor.messages.wire_types import RippleGetAddress
|
||||
from .get_address import get_address
|
||||
from .serializer import *
|
||||
|
||||
|
||||
def dispatch_RippleGetAddress(*args, **kwargs):
|
||||
from .get_address import get_address
|
||||
return get_address(*args, **kwargs)
|
||||
|
||||
|
||||
def boot():
|
||||
register(RippleGetAddress, protobuf_workflow, dispatch_RippleGetAddress)
|
33
src/apps/ripple/base58_ripple.py
Normal file
33
src/apps/ripple/base58_ripple.py
Normal file
@ -0,0 +1,33 @@
|
||||
from trezor.crypto import base58
|
||||
|
||||
# Ripple uses different 58 character alphabet than traditional base58
|
||||
_ripple_alphabet = "rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz"
|
||||
|
||||
|
||||
def encode(data: bytes) -> str:
|
||||
"""
|
||||
Convert bytes to base58 encoded string.
|
||||
"""
|
||||
return base58.encode(data, alphabet=_ripple_alphabet)
|
||||
|
||||
|
||||
def decode(string: str) -> bytes:
|
||||
"""
|
||||
Convert base58 encoded string to bytes.
|
||||
"""
|
||||
return base58.decode(string, alphabet=_ripple_alphabet)
|
||||
|
||||
|
||||
def encode_check(data: bytes, digestfunc=base58.sha256d_32) -> str:
|
||||
"""
|
||||
Convert bytes to base58 encoded string, append checksum.
|
||||
"""
|
||||
return encode(data + digestfunc(data))
|
||||
|
||||
|
||||
def decode_check(string: str, digestfunc=base58.sha256d_32) -> bytes:
|
||||
"""
|
||||
Convert base58 encoded string to bytes and verify checksum.
|
||||
"""
|
||||
data = decode(string)
|
||||
return base58.verify_checksum(data, digestfunc)
|
20
src/apps/ripple/get_address.py
Normal file
20
src/apps/ripple/get_address.py
Normal file
@ -0,0 +1,20 @@
|
||||
from apps.common import seed
|
||||
from apps.common.display_address import show_address, show_qr
|
||||
from trezor.messages.RippleAddress import RippleAddress
|
||||
from trezor.messages.RippleGetAddress import RippleGetAddress
|
||||
from . import helpers
|
||||
|
||||
|
||||
async def get_address(ctx, msg: RippleGetAddress):
|
||||
node = await seed.derive_node(ctx, msg.address_n)
|
||||
pubkey = node.public_key()
|
||||
address = helpers.address_from_public_key(pubkey)
|
||||
|
||||
if msg.show_display:
|
||||
while True:
|
||||
if await show_address(ctx, address):
|
||||
break
|
||||
if await show_qr(ctx, address.upper()):
|
||||
break
|
||||
|
||||
return RippleAddress(address=address)
|
25
src/apps/ripple/helpers.py
Normal file
25
src/apps/ripple/helpers.py
Normal file
@ -0,0 +1,25 @@
|
||||
from trezor.crypto.hashlib import ripemd160, sha256
|
||||
|
||||
from . import base58_ripple
|
||||
|
||||
|
||||
def address_from_public_key(pubkey: bytes):
|
||||
"""Extracts public key from an address
|
||||
|
||||
Ripple address is in format:
|
||||
<1-byte ripple flag> <20-bytes account id> <4-bytes dSHA-256 checksum>
|
||||
|
||||
- 1-byte flag is 0x00 which is 'r' (Ripple uses its own base58 alphabet)
|
||||
- 20-bytes account id is a ripemd160(sha256(pubkey))
|
||||
- checksum is first 4 bytes of double sha256(data)
|
||||
|
||||
see https://developers.ripple.com/accounts.html#address-encoding
|
||||
"""
|
||||
"""Returns the Ripple address created using base58"""
|
||||
h = sha256(pubkey).digest()
|
||||
h = ripemd160(h).digest()
|
||||
|
||||
address = bytearray()
|
||||
address.append(0x00) # 'r'
|
||||
address.extend(h)
|
||||
return base58_ripple.encode_check(bytes(address))
|
@ -16,9 +16,9 @@ import apps.ethereum
|
||||
import apps.lisk
|
||||
import apps.nem
|
||||
import apps.stellar
|
||||
import apps.ripple
|
||||
import apps.cardano
|
||||
|
||||
|
||||
if __debug__:
|
||||
import apps.debug
|
||||
else:
|
||||
@ -32,6 +32,7 @@ apps.ethereum.boot()
|
||||
apps.lisk.boot()
|
||||
apps.nem.boot()
|
||||
apps.stellar.boot()
|
||||
apps.ripple.boot()
|
||||
apps.cardano.boot()
|
||||
if __debug__:
|
||||
apps.debug.boot()
|
||||
|
@ -17,7 +17,7 @@
|
||||
_alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
|
||||
|
||||
|
||||
def encode(data: bytes) -> str:
|
||||
def encode(data: bytes, alphabet=_alphabet) -> str:
|
||||
"""
|
||||
Convert bytes to base58 encoded string.
|
||||
"""
|
||||
@ -33,22 +33,22 @@ def encode(data: bytes) -> str:
|
||||
result = ""
|
||||
while acc > 0:
|
||||
acc, mod = divmod(acc, 58)
|
||||
result += _alphabet[mod]
|
||||
result += alphabet[mod]
|
||||
|
||||
return "".join((c for c in reversed(result + _alphabet[0] * (origlen - newlen))))
|
||||
return "".join((c for c in reversed(result + alphabet[0] * (origlen - newlen))))
|
||||
|
||||
|
||||
def decode(string: str) -> bytes:
|
||||
def decode(string: str, alphabet=_alphabet) -> bytes:
|
||||
"""
|
||||
Convert base58 encoded string to bytes.
|
||||
"""
|
||||
origlen = len(string)
|
||||
string = string.lstrip(_alphabet[0])
|
||||
string = string.lstrip(alphabet[0])
|
||||
newlen = len(string)
|
||||
|
||||
p, acc = 1, 0
|
||||
for c in reversed(string):
|
||||
acc += p * _alphabet.index(c)
|
||||
acc += p * alphabet.index(c)
|
||||
p *= 58
|
||||
|
||||
result = []
|
||||
@ -83,8 +83,12 @@ def decode_check(string: str, digestfunc=sha256d_32) -> bytes:
|
||||
Convert base58 encoded string to bytes and verify checksum.
|
||||
"""
|
||||
result = decode(string)
|
||||
return verify_checksum(result, digestfunc)
|
||||
|
||||
|
||||
def verify_checksum(data: bytes, digestfunc) -> bytes:
|
||||
digestlen = len(digestfunc(b""))
|
||||
result, check = result[:-digestlen], result[-digestlen:]
|
||||
result, check = data[:-digestlen], data[-digestlen:]
|
||||
|
||||
if check != digestfunc(result):
|
||||
raise ValueError("Invalid checksum")
|
||||
|
19
tests/test_apps.ripple.pubkey_to_address.py
Normal file
19
tests/test_apps.ripple.pubkey_to_address.py
Normal file
@ -0,0 +1,19 @@
|
||||
from common import *
|
||||
from apps.ripple.helpers import address_from_public_key
|
||||
|
||||
|
||||
class TestStellarPubkeyToAddress(unittest.TestCase):
|
||||
|
||||
def test_pubkey_to_address(self):
|
||||
addr = address_from_public_key(unhexlify('ed9434799226374926eda3b54b1b461b4abf7237962eae18528fea67595397fa32'))
|
||||
self.assertEqual(addr, 'rDTXLQ7ZKZVKz33zJbHjgVShjsBnqMBhmN')
|
||||
|
||||
addr = address_from_public_key(unhexlify('03e2b079e9b09ae8916da8f5ee40cbda9578dbe7c820553fe4d5f872eec7b1fdd4'))
|
||||
self.assertEqual(addr, 'rhq549rEtUrJowuxQC2WsHNGLjAjBQdAe8')
|
||||
|
||||
addr = address_from_public_key(unhexlify('0282ee731039929e97db6aec242002e9aa62cd62b989136df231f4bb9b8b7c7eb2'))
|
||||
self.assertEqual(addr, 'rKzE5DTyF9G6z7k7j27T2xEas2eMo85kmw')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
Loading…
Reference in New Issue
Block a user