1
0
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:
Tomas Susanka 2018-06-26 14:45:43 +02:00 committed by Jan Pochyla
parent 51d810b6da
commit b5c2ae49dd
8 changed files with 124 additions and 9 deletions

View File

@ -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

View 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)

View 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)

View 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)

View 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))

View File

@ -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()

View File

@ -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")

View 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()