diff --git a/examples/base.py b/examples/base.py index 477d5a46..d193dd4b 100755 --- a/examples/base.py +++ b/examples/base.py @@ -1,14 +1,43 @@ import struct + def parse_bip32_path(path): - if len(path) == 0: - return "" - result = "" - elements = path.split('/') - for pathElement in elements: - element = pathElement.split('\'') - if len(element) == 1: - result = result + struct.pack(">I", int(element[0])).hex() - else: - result = result + struct.pack(">I", 0x80000000 | int(element[0])).hex() - return result \ No newline at end of file + if len(path) == 0: + return "" + result = "" + elements = path.split('/') + for pathElement in elements: + element = pathElement.split('\'') + if len(element) == 1: + result = result + struct.pack(">I", int(element[0])).hex() + else: + result = result + struct.pack(">I", + 0x80000000 | int(element[0])).hex() + return result + + +def parse_bip32_path_to_bytes(path): + if len(path) == 0: + return b"" + result = b"" + elements = path.split('/') + for pathElement in elements: + element = pathElement.split('\'') + if len(element) == 1: + result = result + struct.pack(">I", int(element[0])) + else: + result = result + struct.pack(">I", 0x80000000 | int(element[0])) + return result + + +def apduMessage(INS, P1, P2, PATH, MESSAGE): + hexString = "" + if PATH: + hexString = "E0{:02x}{:02x}{:02x}{:02x}{:02x}{}".format( + INS, P1, P2, (len(PATH) + len(MESSAGE)) // 2 + 1, + len(PATH) // 4 // 2, PATH + MESSAGE) + else: + hexString = "E0{:02x}{:02x}{:02x}{:02x}{}".format( + INS, P1, P2, + len(MESSAGE) // 2, MESSAGE) + return bytearray.fromhex(hexString) diff --git a/examples/ecdh_eke.py.py b/examples/ecdh_eke.py.py index 8d88d725..764b7edd 100755 --- a/examples/ecdh_eke.py.py +++ b/examples/ecdh_eke.py.py @@ -7,9 +7,13 @@ from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes from secrets import token_bytes + class DiffieHellman: + def __init__(self): - self.diffieHellman = ec.derive_private_key(0xb5a4cea271ff424d7c31dc12a3e43e401df7a40d7412a15750f3f0b6b5449a28,ec.SECP256K1(), default_backend()) + self.diffieHellman = ec.derive_private_key( + 0xb5a4cea271ff424d7c31dc12a3e43e401df7a40d7412a15750f3f0b6b5449a28, + ec.SECP256K1(), default_backend()) self.public_key = self.diffieHellman.public_key() self.IV = token_bytes(16) @@ -17,15 +21,15 @@ def encrypt(self, public_key, secret): shared_key = self.diffieHellman.exchange(ec.ECDH(), public_key) print("Shared") print(shared_key.hex()) - derived_key = HKDF( - algorithm=hashes.SHA256(), - length=32, - salt=None, - info=None, - backend=default_backend() - ).derive(shared_key) - - aes = Cipher(algorithms.AES(derived_key), modes.CBC(self.IV), backend=default_backend()) + derived_key = HKDF(algorithm=hashes.SHA256(), + length=32, + salt=None, + info=None, + backend=default_backend()).derive(shared_key) + + aes = Cipher(algorithms.AES(derived_key), + modes.CBC(self.IV), + backend=default_backend()) encryptor = aes.encryptor() padder = padding.PKCS7(128).padder() @@ -34,15 +38,15 @@ def encrypt(self, public_key, secret): def decrypt(self, public_key, secret, iv): shared_key = self.diffieHellman.exchange(ec.ECDH(), public_key) - derived_key = HKDF( - algorithm=hashes.SHA256(), - length=32, - salt=None, - info=None, - backend=default_backend() - ).derive(shared_key) - - aes = Cipher(algorithms.AES(derived_key), modes.CBC(iv), backend=default_backend()) + derived_key = HKDF(algorithm=hashes.SHA256(), + length=32, + salt=None, + info=None, + backend=default_backend()).derive(shared_key) + + aes = Cipher(algorithms.AES(derived_key), + modes.CBC(iv), + backend=default_backend()) decryptor = aes.decryptor() decrypted_data = decryptor.update(secret) + decryptor.finalize() @@ -59,4 +63,4 @@ def decrypt(self, public_key, secret, iv): print(encrypted_message) decrypted_message = alice.decrypt(bob.public_key, encrypted_message, bob.IV) -print(decrypted_message) \ No newline at end of file +print(decrypted_message) diff --git a/examples/getPublicKey.py b/examples/getPublicKey.py index 02a62df5..caf9c005 100755 --- a/examples/getPublicKey.py +++ b/examples/getPublicKey.py @@ -5,11 +5,12 @@ from base import parse_bip32_path parser = argparse.ArgumentParser() -parser.add_argument('--path', help="BIP32 path to retrieve. e.g. \"44'/195'/0'/0/0\".") +parser.add_argument('--path', + help="BIP32 path to retrieve. e.g. \"44'/195'/0'/0/0\".") args = parser.parse_args() if args.path == None: - args.path = "44'/195'/0'/0/0" + args.path = "44'/195'/0'/0/0" donglePath = parse_bip32_path(args.path) @@ -21,7 +22,9 @@ # Ask for confirmation # txt = "E0020100" + '{:02x}'.format(len(donglePath) + 1) + '{:02x}'.format( int(len(donglePath) / 4 / 2)) + donglePath # No confirmation -apduMessage = "E0020000" + '{:02x}'.format(int(len(donglePath)/2) ) + '{:02x}'.format(int(len(donglePath) / 4 / 2)) + donglePath +apduMessage = "E0020000" + '{:02x}'.format(int( + len(donglePath) / 2)) + '{:02x}'.format(int( + len(donglePath) / 4 / 2)) + donglePath apdu = bytearray.fromhex(apduMessage) print("-= Tron Ledger =-") @@ -29,16 +32,16 @@ dongle = getDongle(True) result = dongle.exchange(apdu) -size=result[0] -if size == 65 : - print("Public Key: " + result[1:1+size].hex()) +size = result[0] +if size == 65: + print("Public Key: " + result[1:1 + size].hex()) else: - print("Error... Public Key Size: {:d}".format(size)) + print("Error... Public Key Size: {:d}".format(size)) -size=result[size+1] -if size == 34 : - print("Address: " + result[67:67+size].decode()) - if (result[67:67+size].decode()=="TUEZSdKsoDHQMeZwihtdoBiN46zxhGWYdH"): - print("Address match with test case!") +size = result[size + 1] +if size == 34: + print("Address: " + result[67:67 + size].decode()) + if (result[67:67 + size].decode() == "TUEZSdKsoDHQMeZwihtdoBiN46zxhGWYdH"): + print("Address match with test case!") else: - print("Error... Address Size: {:d}".format(size)) + print("Error... Address Size: {:d}".format(size)) diff --git a/examples/getVersion.py b/examples/getVersion.py index 841d8266..fc589e21 100755 --- a/examples/getVersion.py +++ b/examples/getVersion.py @@ -15,4 +15,4 @@ dongle = getDongle(True) result = dongle.exchange(bytearray.fromhex(apduMessage)) -print('Version={:d}.{:d}.{:d}'.format(result[1],result[2],result[3])) +print('Version={:d}.{:d}.{:d}'.format(result[1], result[2], result[3])) diff --git a/examples/multisignTransfer.py b/examples/multisignTransfer.py index 24e89bae..80aad767 100644 --- a/examples/multisignTransfer.py +++ b/examples/multisignTransfer.py @@ -1,6 +1,7 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- import sys + sys.path.append("./examples/proto") from pprint import pprint @@ -15,7 +16,8 @@ import binascii import base58 -logging.basicConfig(level=logging.DEBUG, format="%(asctime)s - %(levelname)s - %(message)s") +logging.basicConfig(level=logging.DEBUG, + format="%(asctime)s - %(levelname)s - %(message)s") logger = logging.getLogger() # Start Ledger @@ -27,50 +29,67 @@ def chunks(l, n): for i in range(0, len(l), n): yield l[i:i + n] + def apduMessage(INS, P1, P2, PATH, MESSAGE): hexString = "" if PATH: - hexString = "E0{:02x}{:02x}{:02x}{:02x}{:02x}{}".format(INS,P1,P2,(len(PATH)+len(MESSAGE))//2+1,len(PATH)//4//2,PATH+MESSAGE) + hexString = "E0{:02x}{:02x}{:02x}{:02x}{:02x}{}".format( + INS, P1, P2, (len(PATH) + len(MESSAGE)) // 2 + 1, + len(PATH) // 4 // 2, PATH + MESSAGE) else: - hexString = "E0{:02x}{:02x}{:02x}{:02x}{}".format(INS,P1,P2,len(MESSAGE)//2,MESSAGE) + hexString = "E0{:02x}{:02x}{:02x}{:02x}{}".format( + INS, P1, P2, + len(MESSAGE) // 2, MESSAGE) print(hexString) return bytearray.fromhex(hexString) + def ledgerSign(PATH, tx, tokenSignature=[]): raw_tx = tx.raw_data.SerializeToString().hex() # Sign in chunks - chunkList = list(chunks(raw_tx,420)) - if len(tokenSignature)>0: + chunkList = list(chunks(raw_tx, 420)) + if len(tokenSignature) > 0: chunkList.extend(tokenSignature) # P1 = P1_FIRST = 0x00 - if len(chunkList)>1: - result = dongle.exchange(apduMessage(0x04,0x00,0x00, PATH, chunkList[0])) + if len(chunkList) > 1: + result = dongle.exchange( + apduMessage(0x04, 0x00, 0x00, PATH, chunkList[0])) else: - result = dongle.exchange(apduMessage(0x04,0x10,0x00, PATH, chunkList[0])) + result = dongle.exchange( + apduMessage(0x04, 0x10, 0x00, PATH, chunkList[0])) - for i in range(1,len(chunkList)-1-len(tokenSignature)): + for i in range(1, len(chunkList) - 1 - len(tokenSignature)): # P1 = P1_MODE = 0x80 - result = dongle.exchange(apduMessage(0x04,0x80,0x00, None, chunkList[i])) - - for i in range(0,len(tokenSignature)-1): - result = dongle.exchange(apduMessage(0x04,0xA0 | (0x00+i), 0x00, None, tokenSignature[i])) - + result = dongle.exchange( + apduMessage(0x04, 0x80, 0x00, None, chunkList[i])) + + for i in range(0, len(tokenSignature) - 1): + result = dongle.exchange( + apduMessage(0x04, 0xA0 | (0x00 + i), 0x00, None, + tokenSignature[i])) + # P1 = P1_LAST = 0x90 - if len(chunkList)>1: - if len(tokenSignature)>0: - result = dongle.exchange(apduMessage(0x04,0xA0 | 0x08 | (0x00+len(tokenSignature)-1),0x00, None, chunkList[len(chunkList)-1])) + if len(chunkList) > 1: + if len(tokenSignature) > 0: + result = dongle.exchange( + apduMessage(0x04, + 0xA0 | 0x08 | (0x00 + len(tokenSignature) - 1), + 0x00, None, chunkList[len(chunkList) - 1])) else: - result = dongle.exchange(apduMessage(0x04,0x90,0x00, None, chunkList[len(chunkList)-1])) + result = dongle.exchange( + apduMessage(0x04, 0x90, 0x00, None, + chunkList[len(chunkList) - 1])) return raw_tx, result + def address_hex(address): return base58.b58decode_check(address).hex().upper() + # Get Addresses logger.debug('-= Tron Ledger =-') - ''' Tron Protobuf ''' @@ -90,19 +109,17 @@ def address_hex(address): ''') tx = stub.CreateTransaction2( - contract.TransferContract( - owner_address=bytes.fromhex(address_hex("TUEZSdKsoDHQMeZwihtdoBiN46zxhGWYdH")), - to_address=bytes.fromhex(address_hex("TPnYqC2ukKyhEDAjqRRobSVygMAb8nAcXM")), - amount=100000 - ) - ) + contract.TransferContract( + owner_address=bytes.fromhex( + address_hex("TUEZSdKsoDHQMeZwihtdoBiN46zxhGWYdH")), + to_address=bytes.fromhex( + address_hex("TPnYqC2ukKyhEDAjqRRobSVygMAb8nAcXM")), + amount=100000)) # use permission 2 -tx.transaction.raw_data.contract[0].Permission_id=2 - - +tx.transaction.raw_data.contract[0].Permission_id = 2 -raw_tx, sign1 = ledgerSign(parse_bip32_path("44'/195'/0'/0/0"),tx.transaction) -raw_tx, sign2 = ledgerSign(parse_bip32_path("44'/195'/1'/0/0"),tx.transaction) +raw_tx, sign1 = ledgerSign(parse_bip32_path("44'/195'/0'/0/0"), tx.transaction) +raw_tx, sign2 = ledgerSign(parse_bip32_path("44'/195'/1'/0/0"), tx.transaction) tx.transaction.signature.extend([bytes(sign1[0:65])]) tx.transaction.signature.extend([bytes(sign2[0:65])]) @@ -110,6 +127,6 @@ def address_hex(address): r = stub.BroadcastTransaction(tx.transaction) if r.result == True: - print("Success") + print("Success") else: - print("Fail") + print("Fail") diff --git a/examples/runTest.py b/examples/runTest.py index c6f28eec..b14e3c90 100755 --- a/examples/runTest.py +++ b/examples/runTest.py @@ -1,6 +1,7 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- import sys + sys.path.append("./examples/proto") from pprint import pprint @@ -15,7 +16,8 @@ import binascii import base58 -logging.basicConfig(level=logging.DEBUG, format="%(asctime)s - %(levelname)s - %(message)s") +logging.basicConfig(level=logging.DEBUG, + format="%(asctime)s - %(levelname)s - %(message)s") logger = logging.getLogger() @@ -24,79 +26,94 @@ def chunks(l, n): for i in range(0, len(l), n): yield l[i:i + n] + def apduMessage(INS, P1, P2, PATH, MESSAGE): hexString = "" if PATH: - hexString = "E0{:02x}{:02x}{:02x}{:02x}{:02x}{}".format(INS,P1,P2,(len(PATH)+len(MESSAGE))//2+1,len(PATH)//4//2,PATH+MESSAGE) + hexString = "E0{:02x}{:02x}{:02x}{:02x}{:02x}{}".format( + INS, P1, P2, (len(PATH) + len(MESSAGE)) // 2 + 1, + len(PATH) // 4 // 2, PATH + MESSAGE) else: - hexString = "E0{:02x}{:02x}{:02x}{:02x}{}".format(INS,P1,P2,len(MESSAGE)//2,MESSAGE) + hexString = "E0{:02x}{:02x}{:02x}{:02x}{}".format( + INS, P1, P2, + len(MESSAGE) // 2, MESSAGE) print(hexString) return bytearray.fromhex(hexString) + def ledgerSign(PATH, tx, tokenSignature=[]): raw_tx = tx.raw_data.SerializeToString().hex() # Sign in chunks - chunkList = list(chunks(raw_tx,410)) - if len(tokenSignature)>0: + chunkList = list(chunks(raw_tx, 410)) + if len(tokenSignature) > 0: chunkList.extend(tokenSignature) # P1 = P1_FIRST = 0x00 - if len(chunkList)>1: - result = dongle.exchange(apduMessage(0x04,0x00,0x00, PATH, chunkList[0])) + if len(chunkList) > 1: + result = dongle.exchange( + apduMessage(0x04, 0x00, 0x00, PATH, chunkList[0])) else: - result = dongle.exchange(apduMessage(0x04,0x10,0x00, PATH, chunkList[0])) + result = dongle.exchange( + apduMessage(0x04, 0x10, 0x00, PATH, chunkList[0])) - for i in range(1,len(chunkList)-1-len(tokenSignature)): + for i in range(1, len(chunkList) - 1 - len(tokenSignature)): # P1 = P1_MODE = 0x80 - result = dongle.exchange(apduMessage(0x04,0x80,0x00, None, chunkList[i])) - - for i in range(0,len(tokenSignature)-1): - result = dongle.exchange(apduMessage(0x04,0xA0 | (0x00+i), 0x00, None, tokenSignature[i])) - + result = dongle.exchange( + apduMessage(0x04, 0x80, 0x00, None, chunkList[i])) + + for i in range(0, len(tokenSignature) - 1): + result = dongle.exchange( + apduMessage(0x04, 0xA0 | (0x00 + i), 0x00, None, + tokenSignature[i])) + # P1 = P1_LAST = 0x90 - if len(chunkList)>1: - if len(tokenSignature)>0: - result = dongle.exchange(apduMessage(0x04,0xA0 | 0x08 | (0x00+len(tokenSignature)-1),0x00, None, chunkList[len(chunkList)-1])) + if len(chunkList) > 1: + if len(tokenSignature) > 0: + result = dongle.exchange( + apduMessage(0x04, + 0xA0 | 0x08 | (0x00 + len(tokenSignature) - 1), + 0x00, None, chunkList[len(chunkList) - 1])) else: - result = dongle.exchange(apduMessage(0x04,0x90,0x00, None, chunkList[len(chunkList)-1])) + result = dongle.exchange( + apduMessage(0x04, 0x90, 0x00, None, + chunkList[len(chunkList) - 1])) return raw_tx, result + def address_hex(address): return base58.b58decode_check(address).hex().upper() + accounts = [{ - "path": parse_bip32_path("44'/195'/0'/0/0"), - }, - { - "path": parse_bip32_path("44'/195'/1'/0/0"), - }] + "path": parse_bip32_path("44'/195'/0'/0/0"), +}, { + "path": parse_bip32_path("44'/195'/1'/0/0"), +}] # Get Addresses logger.debug('-= Tron Ledger =-') logger.debug('Requesting Public Keys...') dongle = getDongle(True) for i in range(2): - result = dongle.exchange(apduMessage(0x02,0x00,0x00,accounts[i]['path'], "")) - size=result[0] - if size == 65 : - accounts[i]['publicKey'] = result[1:1+size].hex() - size=result[size+1] - if size == 34 : - accounts[i]['address'] = result[67:67+size].decode() + result = dongle.exchange( + apduMessage(0x02, 0x00, 0x00, accounts[i]['path'], "")) + size = result[0] + if size == 65: + accounts[i]['publicKey'] = result[1:1 + size].hex() + size = result[size + 1] + if size == 34: + accounts[i]['address'] = result[67:67 + size].decode() accounts[i]['addressHex'] = address_hex(accounts[i]['address']) else: logger.error('Error... Address Size: {:d}'.format(size)) else: logger.error('Error... Public Key Size: {:d}'.format(size)) - logger.debug('Test Accounts:') for i in range(2): logger.debug('- Public Key {}: {}'.format(i, accounts[i]['publicKey'])) - logger.debug('- Address {}: {}'.format(i,accounts[i]['address'])) - - + logger.debug('- Address {}: {}'.format(i, accounts[i]['address'])) ''' Tron Protobuf ''' @@ -120,14 +137,15 @@ def address_hex(address): ############ logger.debug('\n\nTransfer Contract:') -tx = stub.CreateTransaction2(contract.TransferContract( +tx = stub.CreateTransaction2( + contract.TransferContract( owner_address=bytes.fromhex(accounts[1]['addressHex']), to_address=bytes.fromhex(accounts[0]['addressHex']), - amount=1 - )) + amount=1)) -raw_tx, result = ledgerSign(accounts[1]['path'],tx.transaction) -validSignature, txID = validateSignature.validate(raw_tx,result[0:65],accounts[1]['publicKey'][2:]) +raw_tx, result = ledgerSign(accounts[1]['path'], tx.transaction) +validSignature, txID = validateSignature.validate(raw_tx, result[0:65], + accounts[1]['publicKey'][2:]) logger.debug('- RAW: {}'.format(raw_tx)) logger.debug('- txID: {}'.format(txID)) logger.debug('- Signature: {}'.format(binascii.hexlify(result[0:65]))) @@ -141,7 +159,6 @@ def address_hex(address): #tx.transaction.signature.extend([bytes(result[0:65])]) #r = stub.BroadcastTransaction(tx.transaction) - ###################### # Send TRX with DATA # ###################### @@ -150,20 +167,21 @@ def address_hex(address): # check if device have data enable result = dongle.exchange(bytearray.fromhex("E0060000FF")) dataAllowed = result[0] & 0x01 -if dataAllowed==0: +if dataAllowed == 0: print("Data field not allowed, test should fail...") sys.exit(0) -tx = stub.CreateTransaction2(contract.TransferContract( +tx = stub.CreateTransaction2( + contract.TransferContract( owner_address=bytes.fromhex(accounts[1]['addressHex']), to_address=bytes.fromhex(accounts[0]['addressHex']), - amount=1 - )) + amount=1)) tx.transaction.raw_data.data = b'CryptoChain-TronSR Ledger Transactions Tests' -raw_tx, result = ledgerSign(accounts[1]['path'],tx.transaction) -validSignature, txID = validateSignature.validate(raw_tx,result[0:65],accounts[1]['publicKey'][2:]) +raw_tx, result = ledgerSign(accounts[1]['path'], tx.transaction) +validSignature, txID = validateSignature.validate(raw_tx, result[0:65], + accounts[1]['publicKey'][2:]) logger.debug('- RAW: {}'.format(raw_tx)) logger.debug('- txID: {}'.format(txID)) logger.debug('- Signature: {}'.format(binascii.hexlify(result[0:65]))) @@ -178,15 +196,16 @@ def address_hex(address): #################### logger.debug('\n\nTransfer Asset Contract:') -tx = stub.TransferAsset2(contract.TransferAssetContract( +tx = stub.TransferAsset2( + contract.TransferAssetContract( asset_name="1000166".encode(), owner_address=bytes.fromhex(accounts[1]['addressHex']), to_address=bytes.fromhex(accounts[0]['addressHex']), - amount=1 - )) + amount=1)) -raw_tx, result = ledgerSign(accounts[1]['path'],tx.transaction) -validSignature, txID = validateSignature.validate(raw_tx,result[0:65],accounts[1]['publicKey'][2:]) +raw_tx, result = ledgerSign(accounts[1]['path'], tx.transaction) +validSignature, txID = validateSignature.validate(raw_tx, result[0:65], + accounts[1]['publicKey'][2:]) logger.debug('- RAW: {}'.format(raw_tx)) logger.debug('- txID: {}'.format(txID)) logger.debug('- Signature: {}'.format(binascii.hexlify(result[0:65]))) @@ -201,16 +220,20 @@ def address_hex(address): ####################################### logger.debug('\n\nTransfer Asset Contract with Name/Decimals:') -tx = stub.TransferAsset2(contract.TransferAssetContract( +tx = stub.TransferAsset2( + contract.TransferAssetContract( asset_name="1002000".encode(), owner_address=bytes.fromhex(accounts[1]['addressHex']), to_address=bytes.fromhex(accounts[0]['addressHex']), - amount=1 - )) + amount=1)) # BitTorrent 1002000 -> Decimals: 6 -tokenSignature = ["0a0a426974546f7272656e7410061a46304402202e2502f36b00e57be785fc79ec4043abcdd4fdd1b58d737ce123599dffad2cb602201702c307f009d014a553503b499591558b3634ceee4c054c61cedd8aca94c02b"] -raw_tx, result = ledgerSign(accounts[1]['path'],tx.transaction, tokenSignature) -validSignature, txID = validateSignature.validate(raw_tx,result[0:65],accounts[1]['publicKey'][2:]) +tokenSignature = [ + "0a0a426974546f7272656e7410061a46304402202e2502f36b00e57be785fc79ec4043abcdd4fdd1b58d737ce123599dffad2cb602201702c307f009d014a553503b499591558b3634ceee4c054c61cedd8aca94c02b" +] +raw_tx, result = ledgerSign(accounts[1]['path'], tx.transaction, + tokenSignature) +validSignature, txID = validateSignature.validate(raw_tx, result[0:65], + accounts[1]['publicKey'][2:]) logger.debug('- RAW: {}'.format(raw_tx)) logger.debug('- txID: {}'.format(txID)) logger.debug('- Signature: {}'.format(binascii.hexlify(result[0:65]))) @@ -227,21 +250,20 @@ def address_hex(address): tx = tron.Transaction() newContract = contract.ExchangeCreateContract( - owner_address=bytes.fromhex(accounts[1]['addressHex']), - first_token_id="_".encode(), - first_token_balance=10000000000, - second_token_id="1000166".encode(), - second_token_balance=10000000 - ) + owner_address=bytes.fromhex(accounts[1]['addressHex']), + first_token_id="_".encode(), + first_token_balance=10000000000, + second_token_id="1000166".encode(), + second_token_balance=10000000) c = tx.raw_data.contract.add() c.type = tron.Transaction.Contract.ExchangeCreateContract param = Any() param.Pack(newContract) c.parameter.CopyFrom(param) - -raw_tx, result = ledgerSign(accounts[1]['path'],tx) -validSignature, txID = validateSignature.validate(raw_tx,result[0:65],accounts[1]['publicKey'][2:]) +raw_tx, result = ledgerSign(accounts[1]['path'], tx) +validSignature, txID = validateSignature.validate(raw_tx, result[0:65], + accounts[1]['publicKey'][2:]) logger.debug('- RAW: {}'.format(raw_tx)) logger.debug('- txID: {}'.format(txID)) logger.debug('- Signature: {}'.format(binascii.hexlify(result[0:65]))) @@ -258,25 +280,27 @@ def address_hex(address): tx = tron.Transaction() newContract = contract.ExchangeCreateContract( - owner_address=bytes.fromhex(accounts[1]['addressHex']), - first_token_id="_".encode(), - first_token_balance=10000000000, - second_token_id="1000166".encode(), - second_token_balance=10000000 - ) + owner_address=bytes.fromhex(accounts[1]['addressHex']), + first_token_id="_".encode(), + first_token_balance=10000000000, + second_token_id="1000166".encode(), + second_token_balance=10000000) c = tx.raw_data.contract.add() c.type = tron.Transaction.Contract.ExchangeCreateContract param = Any() param.Pack(newContract) c.parameter.CopyFrom(param) -# Token Signature -# Token 1: _ TRX +# Token Signature +# Token 1: _ TRX # Token 2: 1000166 CCT -tokenSignature = ["0a0354525810061a463044022037c53ecb06abe1bfd708bd7afd047720b72e2bfc0a2e4b6ade9a33ae813565a802200a7d5086dc08c4a6f866aad803ac7438942c3c0a6371adcb6992db94487f66c7", - "0a0b43727970746f436861696e10001a4730450221008417d04d1caeae31f591ae50f7d19e53e0dfb827bd51c18e66081941bf04639802203c73361a521c969e3fd7f62e62b46d61aad00e47d41e7da108546d954278a6b1"] -raw_tx, result = ledgerSign(accounts[1]['path'],tx, tokenSignature) -validSignature, txID = validateSignature.validate(raw_tx,result[0:65],accounts[1]['publicKey'][2:]) +tokenSignature = [ + "0a0354525810061a463044022037c53ecb06abe1bfd708bd7afd047720b72e2bfc0a2e4b6ade9a33ae813565a802200a7d5086dc08c4a6f866aad803ac7438942c3c0a6371adcb6992db94487f66c7", + "0a0b43727970746f436861696e10001a4730450221008417d04d1caeae31f591ae50f7d19e53e0dfb827bd51c18e66081941bf04639802203c73361a521c969e3fd7f62e62b46d61aad00e47d41e7da108546d954278a6b1" +] +raw_tx, result = ledgerSign(accounts[1]['path'], tx, tokenSignature) +validSignature, txID = validateSignature.validate(raw_tx, result[0:65], + accounts[1]['publicKey'][2:]) logger.debug('- RAW: {}'.format(raw_tx)) logger.debug('- txID: {}'.format(txID)) logger.debug('- Signature: {}'.format(binascii.hexlify(result[0:65]))) @@ -292,12 +316,11 @@ def address_hex(address): logger.debug('\n\nExchange Inject Contract:') tx = tron.Transaction() -newContract = contract.ExchangeInjectContract( - owner_address=bytes.fromhex(accounts[1]['addressHex']), - exchange_id=6, - token_id="1000166".encode(), - quant=10000000 - ) +newContract = contract.ExchangeInjectContract(owner_address=bytes.fromhex( + accounts[1]['addressHex']), + exchange_id=6, + token_id="1000166".encode(), + quant=10000000) c = tx.raw_data.contract.add() c.type = tron.Transaction.Contract.ExchangeInjectContract param = Any() @@ -305,9 +328,12 @@ def address_hex(address): c.parameter.CopyFrom(param) # Exchange 6 CCT <-> TRX -exchangeSignature = ["08061207313030303136361a0b43727970746f436861696e20002a015f3203545258380642473045022100fe276f30a63173b2440991affbbdc5d6d2d22b61b306b24e535a2fb866518d9c02205f7f41254201131382ec6c8b3c78276a2bb136f910b9a1f37bfde192fc448793"] -raw_tx, result = ledgerSign(accounts[1]['path'],tx, exchangeSignature) -validSignature, txID = validateSignature.validate(raw_tx,result[0:65],accounts[1]['publicKey'][2:]) +exchangeSignature = [ + "08061207313030303136361a0b43727970746f436861696e20002a015f3203545258380642473045022100fe276f30a63173b2440991affbbdc5d6d2d22b61b306b24e535a2fb866518d9c02205f7f41254201131382ec6c8b3c78276a2bb136f910b9a1f37bfde192fc448793" +] +raw_tx, result = ledgerSign(accounts[1]['path'], tx, exchangeSignature) +validSignature, txID = validateSignature.validate(raw_tx, result[0:65], + accounts[1]['publicKey'][2:]) logger.debug('- RAW: {}'.format(raw_tx)) logger.debug('- txID: {}'.format(txID)) logger.debug('- Signature: {}'.format(binascii.hexlify(result[0:65]))) @@ -323,12 +349,11 @@ def address_hex(address): logger.debug('\n\nExchange Withdraw Contract:') tx = tron.Transaction() -newContract = contract.ExchangeWithdrawContract( - owner_address=bytes.fromhex(accounts[1]['addressHex']), - exchange_id=6, - token_id="1000166".encode(), - quant=1000000 - ) +newContract = contract.ExchangeWithdrawContract(owner_address=bytes.fromhex( + accounts[1]['addressHex']), + exchange_id=6, + token_id="1000166".encode(), + quant=1000000) c = tx.raw_data.contract.add() c.type = tron.Transaction.Contract.ExchangeWithdrawContract param = Any() @@ -336,9 +361,12 @@ def address_hex(address): c.parameter.CopyFrom(param) # Exchange 6 CCT <-> TRX -exchangeSignature = ["08061207313030303136361a0b43727970746f436861696e20002a015f3203545258380642473045022100fe276f30a63173b2440991affbbdc5d6d2d22b61b306b24e535a2fb866518d9c02205f7f41254201131382ec6c8b3c78276a2bb136f910b9a1f37bfde192fc448793"] -raw_tx, result = ledgerSign(accounts[1]['path'],tx, exchangeSignature) -validSignature, txID = validateSignature.validate(raw_tx,result[0:65],accounts[1]['publicKey'][2:]) +exchangeSignature = [ + "08061207313030303136361a0b43727970746f436861696e20002a015f3203545258380642473045022100fe276f30a63173b2440991affbbdc5d6d2d22b61b306b24e535a2fb866518d9c02205f7f41254201131382ec6c8b3c78276a2bb136f910b9a1f37bfde192fc448793" +] +raw_tx, result = ledgerSign(accounts[1]['path'], tx, exchangeSignature) +validSignature, txID = validateSignature.validate(raw_tx, result[0:65], + accounts[1]['publicKey'][2:]) logger.debug('- RAW: {}'.format(raw_tx)) logger.debug('- txID: {}'.format(txID)) logger.debug('- Signature: {}'.format(binascii.hexlify(result[0:65]))) @@ -348,20 +376,18 @@ def address_hex(address): logger.error('- Valid: {}'.format(validSignature)) sys.exit(0) - ############################## # TRC10 Exchange Transaction # ############################## logger.debug('\n\nExchange Transaction Contract:') tx = tron.Transaction() -newContract = contract.ExchangeTransactionContract( - owner_address=bytes.fromhex(accounts[1]['addressHex']), - exchange_id=6, - token_id="1000166".encode(), - quant=10000, - expected=100 - ) +newContract = contract.ExchangeTransactionContract(owner_address=bytes.fromhex( + accounts[1]['addressHex']), + exchange_id=6, + token_id="1000166".encode(), + quant=10000, + expected=100) c = tx.raw_data.contract.add() c.type = tron.Transaction.Contract.ExchangeTransactionContract param = Any() @@ -369,9 +395,12 @@ def address_hex(address): c.parameter.CopyFrom(param) # Exchange 6 CCT <-> TRX -exchangeSignature = ["08061207313030303136361a0b43727970746f436861696e20002a015f3203545258380642473045022100fe276f30a63173b2440991affbbdc5d6d2d22b61b306b24e535a2fb866518d9c02205f7f41254201131382ec6c8b3c78276a2bb136f910b9a1f37bfde192fc448793"] -raw_tx, result = ledgerSign(accounts[1]['path'],tx, exchangeSignature) -validSignature, txID = validateSignature.validate(raw_tx,result[0:65],accounts[1]['publicKey'][2:]) +exchangeSignature = [ + "08061207313030303136361a0b43727970746f436861696e20002a015f3203545258380642473045022100fe276f30a63173b2440991affbbdc5d6d2d22b61b306b24e535a2fb866518d9c02205f7f41254201131382ec6c8b3c78276a2bb136f910b9a1f37bfde192fc448793" +] +raw_tx, result = ledgerSign(accounts[1]['path'], tx, exchangeSignature) +validSignature, txID = validateSignature.validate(raw_tx, result[0:65], + accounts[1]['publicKey'][2:]) logger.debug('- RAW: {}'.format(raw_tx)) logger.debug('- txID: {}'.format(txID)) logger.debug('- Signature: {}'.format(binascii.hexlify(result[0:65]))) @@ -388,26 +417,30 @@ def address_hex(address): tx = tron.Transaction() newContract = contract.VoteWitnessContract( - owner_address=bytes.fromhex(accounts[1]['addressHex']) - ) + owner_address=bytes.fromhex(accounts[1]['addressHex'])) tx.raw_data.ref_block_bytes = b'0000' tx.raw_data.timestamp = 110101010101 -# Vote list +# Vote list v1 = newContract.votes.add() -v1.vote_address=bytes.fromhex(address_hex("TKSXDA8HfE9E1y39RczVQ1ZascUEtaSToF")) -v1.vote_count=1 +v1.vote_address = bytes.fromhex( + address_hex("TKSXDA8HfE9E1y39RczVQ1ZascUEtaSToF")) +v1.vote_count = 1 v2 = newContract.votes.add() -v2.vote_address=bytes.fromhex(address_hex("TE7hnUtWRRBz3SkFrX8JESWUmEvxxAhoPt")) -v2.vote_count=1 +v2.vote_address = bytes.fromhex( + address_hex("TE7hnUtWRRBz3SkFrX8JESWUmEvxxAhoPt")) +v2.vote_count = 1 v3 = newContract.votes.add() -v3.vote_address=bytes.fromhex(address_hex("TTcYhypP8m4phDhN6oRexz2174zAerjEWP")) -v3.vote_count=1000 +v3.vote_address = bytes.fromhex( + address_hex("TTcYhypP8m4phDhN6oRexz2174zAerjEWP")) +v3.vote_count = 1000 v4 = newContract.votes.add() -v4.vote_address=bytes.fromhex(address_hex("TY65QiDt4hLTMpf3WRzcX357BnmdxT2sw9")) -v4.vote_count=1000 +v4.vote_address = bytes.fromhex( + address_hex("TY65QiDt4hLTMpf3WRzcX357BnmdxT2sw9")) +v4.vote_count = 1000 v5 = newContract.votes.add() -v5.vote_address=bytes.fromhex(address_hex("TSNbzxac4WhxN91XvaUfPTKP2jNT18mP6T")) -v5.vote_count=1000 +v5.vote_address = bytes.fromhex( + address_hex("TSNbzxac4WhxN91XvaUfPTKP2jNT18mP6T")) +v5.vote_count = 1000 # End vote list c = tx.raw_data.contract.add() c.type = tron.Transaction.Contract.VoteWitnessContract @@ -415,9 +448,10 @@ def address_hex(address): param.Pack(newContract) c.parameter.CopyFrom(param) -print( tx.raw_data.SerializeToString().hex() ) -raw_tx, result = ledgerSign(accounts[1]['path'],tx) -validSignature, txID = validateSignature.validate(raw_tx,result[0:65],accounts[1]['publicKey'][2:]) +print(tx.raw_data.SerializeToString().hex()) +raw_tx, result = ledgerSign(accounts[1]['path'], tx) +validSignature, txID = validateSignature.validate(raw_tx, result[0:65], + accounts[1]['publicKey'][2:]) logger.debug('- RAW: {}'.format(raw_tx)) logger.debug('- txID: {}'.format(txID)) logger.debug('- Signature: {}'.format(binascii.hexlify(result[0:65]))) @@ -427,27 +461,26 @@ def address_hex(address): logger.error('- Valid: {}'.format(validSignature)) sys.exit(0) - ##################### # Freeze Balance BW # ##################### logger.debug('\n\nFreeze Contract bandwidth:') tx = tron.Transaction() -newContract = contract.FreezeBalanceContract( - owner_address=bytes.fromhex(accounts[1]['addressHex']), - frozen_balance=10000000000, - frozen_duration=3, - resource=contract.BANDWIDTH - ) +newContract = contract.FreezeBalanceContract(owner_address=bytes.fromhex( + accounts[1]['addressHex']), + frozen_balance=10000000000, + frozen_duration=3, + resource=contract.BANDWIDTH) c = tx.raw_data.contract.add() c.type = tron.Transaction.Contract.FreezeBalanceContract param = Any() param.Pack(newContract) c.parameter.CopyFrom(param) -raw_tx, result = ledgerSign(accounts[1]['path'],tx) -validSignature, txID = validateSignature.validate(raw_tx,result[0:65],accounts[1]['publicKey'][2:]) +raw_tx, result = ledgerSign(accounts[1]['path'], tx) +validSignature, txID = validateSignature.validate(raw_tx, result[0:65], + accounts[1]['publicKey'][2:]) logger.debug('- RAW: {}'.format(raw_tx)) logger.debug('- txID: {}'.format(txID)) logger.debug('- Signature: {}'.format(binascii.hexlify(result[0:65]))) @@ -457,7 +490,6 @@ def address_hex(address): logger.error('- Valid: {}'.format(validSignature)) sys.exit(0) - ################################# # Freeze Balance Delegate Energy# ################################# @@ -465,20 +497,21 @@ def address_hex(address): tx = tron.Transaction() newContract = contract.FreezeBalanceContract( - owner_address=bytes.fromhex(accounts[1]['addressHex']), - frozen_balance=10000000000, - frozen_duration=3, - resource=contract.ENERGY, - receiver_address=bytes.fromhex(accounts[0]['addressHex']), - ) + owner_address=bytes.fromhex(accounts[1]['addressHex']), + frozen_balance=10000000000, + frozen_duration=3, + resource=contract.ENERGY, + receiver_address=bytes.fromhex(accounts[0]['addressHex']), +) c = tx.raw_data.contract.add() c.type = tron.Transaction.Contract.FreezeBalanceContract param = Any() param.Pack(newContract) c.parameter.CopyFrom(param) -raw_tx, result = ledgerSign(accounts[1]['path'],tx) -validSignature, txID = validateSignature.validate(raw_tx,result[0:65],accounts[1]['publicKey'][2:]) +raw_tx, result = ledgerSign(accounts[1]['path'], tx) +validSignature, txID = validateSignature.validate(raw_tx, result[0:65], + accounts[1]['publicKey'][2:]) logger.debug('- RAW: {}'.format(raw_tx)) logger.debug('- txID: {}'.format(txID)) logger.debug('- Signature: {}'.format(binascii.hexlify(result[0:65]))) @@ -488,25 +521,24 @@ def address_hex(address): logger.error('- Valid: {}'.format(validSignature)) sys.exit(0) - ###################### # Unfreeze Balance BW# ###################### logger.debug('\n\nUnfreeze Contract bandwidth:') tx = tron.Transaction() -newContract = contract.UnfreezeBalanceContract( - owner_address=bytes.fromhex(accounts[1]['addressHex']), - resource=contract.BANDWIDTH - ) +newContract = contract.UnfreezeBalanceContract(owner_address=bytes.fromhex( + accounts[1]['addressHex']), + resource=contract.BANDWIDTH) c = tx.raw_data.contract.add() c.type = tron.Transaction.Contract.UnfreezeBalanceContract param = Any() param.Pack(newContract) c.parameter.CopyFrom(param) -raw_tx, result = ledgerSign(accounts[1]['path'],tx) -validSignature, txID = validateSignature.validate(raw_tx,result[0:65],accounts[1]['publicKey'][2:]) +raw_tx, result = ledgerSign(accounts[1]['path'], tx) +validSignature, txID = validateSignature.validate(raw_tx, result[0:65], + accounts[1]['publicKey'][2:]) logger.debug('- RAW: {}'.format(raw_tx)) logger.debug('- txID: {}'.format(txID)) logger.debug('- Signature: {}'.format(binascii.hexlify(result[0:65]))) @@ -523,18 +555,19 @@ def address_hex(address): tx = tron.Transaction() newContract = contract.UnfreezeBalanceContract( - owner_address=bytes.fromhex(accounts[1]['addressHex']), - resource=contract.ENERGY, - receiver_address=bytes.fromhex(accounts[0]['addressHex']), - ) + owner_address=bytes.fromhex(accounts[1]['addressHex']), + resource=contract.ENERGY, + receiver_address=bytes.fromhex(accounts[0]['addressHex']), +) c = tx.raw_data.contract.add() c.type = tron.Transaction.Contract.UnfreezeBalanceContract param = Any() param.Pack(newContract) c.parameter.CopyFrom(param) -raw_tx, result = ledgerSign(accounts[1]['path'],tx) -validSignature, txID = validateSignature.validate(raw_tx,result[0:65],accounts[1]['publicKey'][2:]) +raw_tx, result = ledgerSign(accounts[1]['path'], tx) +validSignature, txID = validateSignature.validate(raw_tx, result[0:65], + accounts[1]['publicKey'][2:]) logger.debug('- RAW: {}'.format(raw_tx)) logger.debug('- txID: {}'.format(txID)) logger.debug('- Signature: {}'.format(binascii.hexlify(result[0:65]))) @@ -544,7 +577,6 @@ def address_hex(address): logger.error('- Valid: {}'.format(validSignature)) sys.exit(0) - ##################### # Widthdraw Balance # ##################### @@ -553,16 +585,16 @@ def address_hex(address): tx = tron.Transaction() newContract = contract.WithdrawBalanceContract( - owner_address=bytes.fromhex(accounts[1]['addressHex']) - ) + owner_address=bytes.fromhex(accounts[1]['addressHex'])) c = tx.raw_data.contract.add() c.type = tron.Transaction.Contract.WithdrawBalanceContract param = Any() param.Pack(newContract) c.parameter.CopyFrom(param) -raw_tx, result = ledgerSign(accounts[0]['path'],tx) -validSignature, txID = validateSignature.validate(raw_tx,result[0:65],accounts[0]['publicKey'][2:]) +raw_tx, result = ledgerSign(accounts[0]['path'], tx) +validSignature, txID = validateSignature.validate(raw_tx, result[0:65], + accounts[0]['publicKey'][2:]) logger.debug('- RAW: {}'.format(raw_tx)) logger.debug('- txID: {}'.format(txID)) logger.debug('- Signature: {}'.format(binascii.hexlify(result[0:65]))) @@ -572,7 +604,6 @@ def address_hex(address): logger.error('- Valid: {}'.format(validSignature)) sys.exit(0) - ################### # Proposal Create # ################### @@ -580,9 +611,8 @@ def address_hex(address): logger.debug('\n\Proposal Create Contract:') tx = tron.Transaction() -newContract = contract.ProposalCreateContract( - owner_address=bytes.fromhex(accounts[1]['addressHex']), - ) +newContract = contract.ProposalCreateContract(owner_address=bytes.fromhex( + accounts[1]['addressHex']), ) newContract.parameters[1] = 10000000 c = tx.raw_data.contract.add() c.type = tron.Transaction.Contract.ProposalCreateContract @@ -590,8 +620,9 @@ def address_hex(address): param.Pack(newContract) c.parameter.CopyFrom(param) -raw_tx, result = ledgerSign(accounts[1]['path'],tx) -validSignature, txID = validateSignature.validate(raw_tx,result[0:65],accounts[1]['publicKey'][2:]) +raw_tx, result = ledgerSign(accounts[1]['path'], tx) +validSignature, txID = validateSignature.validate(raw_tx, result[0:65], + accounts[1]['publicKey'][2:]) logger.debug('- RAW: {}'.format(raw_tx)) logger.debug('- txID: {}'.format(txID)) logger.debug('- Signature: {}'.format(binascii.hexlify(result[0:65]))) @@ -601,7 +632,6 @@ def address_hex(address): logger.error('- Valid: {}'.format(validSignature)) sys.exit(0) - #################### # Proposal Approve # #################### @@ -610,11 +640,10 @@ def address_hex(address): tx = tron.Transaction() -newContract = contract.ProposalApproveContract( - owner_address=bytes.fromhex(accounts[1]['addressHex']), - proposal_id=10, - is_add_approval=True - ) +newContract = contract.ProposalApproveContract(owner_address=bytes.fromhex( + accounts[1]['addressHex']), + proposal_id=10, + is_add_approval=True) c = tx.raw_data.contract.add() c.type = tron.Transaction.Contract.ProposalApproveContract @@ -622,8 +651,9 @@ def address_hex(address): param.Pack(newContract) c.parameter.CopyFrom(param) -raw_tx, result = ledgerSign(accounts[1]['path'],tx) -validSignature, txID = validateSignature.validate(raw_tx,result[0:65],accounts[1]['publicKey'][2:]) +raw_tx, result = ledgerSign(accounts[1]['path'], tx) +validSignature, txID = validateSignature.validate(raw_tx, result[0:65], + accounts[1]['publicKey'][2:]) logger.debug('- RAW: {}'.format(raw_tx)) logger.debug('- txID: {}'.format(txID)) logger.debug('- Signature: {}'.format(binascii.hexlify(result[0:65]))) @@ -633,7 +663,6 @@ def address_hex(address): logger.error('- Valid: {}'.format(validSignature)) sys.exit(0) - ################### # Proposal Delete # ################### @@ -643,9 +672,9 @@ def address_hex(address): tx = tron.Transaction() newContract = contract.ProposalDeleteContract( - owner_address=bytes.fromhex(accounts[1]['addressHex']), - proposal_id=10, - ) + owner_address=bytes.fromhex(accounts[1]['addressHex']), + proposal_id=10, +) c = tx.raw_data.contract.add() c.type = tron.Transaction.Contract.ProposalDeleteContract @@ -653,8 +682,9 @@ def address_hex(address): param.Pack(newContract) c.parameter.CopyFrom(param) -raw_tx, result = ledgerSign(accounts[1]['path'],tx) -validSignature, txID = validateSignature.validate(raw_tx,result[0:65],accounts[1]['publicKey'][2:]) +raw_tx, result = ledgerSign(accounts[1]['path'], tx) +validSignature, txID = validateSignature.validate(raw_tx, result[0:65], + accounts[1]['publicKey'][2:]) logger.debug('- RAW: {}'.format(raw_tx)) logger.debug('- txID: {}'.format(txID)) logger.debug('- Signature: {}'.format(binascii.hexlify(result[0:65]))) @@ -664,7 +694,6 @@ def address_hex(address): logger.error('- Valid: {}'.format(validSignature)) sys.exit(0) - ################## # Account Update # ################## @@ -673,9 +702,9 @@ def address_hex(address): tx = tron.Transaction() newContract = contract.AccountUpdateContract( - account_name=b'CryptoChainTest', - owner_address=bytes.fromhex(accounts[1]['addressHex']), - ) + account_name=b'CryptoChainTest', + owner_address=bytes.fromhex(accounts[1]['addressHex']), +) c = tx.raw_data.contract.add() c.type = tron.Transaction.Contract.AccountUpdateContract @@ -683,8 +712,9 @@ def address_hex(address): param.Pack(newContract) c.parameter.CopyFrom(param) -raw_tx, result = ledgerSign(accounts[1]['path'],tx) -validSignature, txID = validateSignature.validate(raw_tx,result[0:65],accounts[1]['publicKey'][2:]) +raw_tx, result = ledgerSign(accounts[1]['path'], tx) +validSignature, txID = validateSignature.validate(raw_tx, result[0:65], + accounts[1]['publicKey'][2:]) logger.debug('- RAW: {}'.format(raw_tx)) logger.debug('- txID: {}'.format(txID)) logger.debug('- Signature: {}'.format(binascii.hexlify(result[0:65]))) @@ -694,7 +724,6 @@ def address_hex(address): logger.error('- Valid: {}'.format(validSignature)) sys.exit(0) - ################## # TRC20 Transfer # ################## @@ -703,10 +732,12 @@ def address_hex(address): tx = tron.Transaction() newContract = contract.TriggerSmartContract( - owner_address=bytes.fromhex(accounts[1]['addressHex']), - contract_address=bytes.fromhex(address_hex("TBoTZcARzWVgnNuB9SyE3S5g1RwsXoQL16")), - data=bytes.fromhex("a9059cbb000000000000000000000000364b03e0815687edaf90b81ff58e496dea7383d700000000000000000000000000000000000000000000000000000000000f4240") - ) + owner_address=bytes.fromhex(accounts[1]['addressHex']), + contract_address=bytes.fromhex( + address_hex("TBoTZcARzWVgnNuB9SyE3S5g1RwsXoQL16")), + data=bytes.fromhex( + "a9059cbb000000000000000000000000364b03e0815687edaf90b81ff58e496dea7383d700000000000000000000000000000000000000000000000000000000000f4240" + )) c = tx.raw_data.contract.add() c.type = tron.Transaction.Contract.TriggerSmartContract @@ -716,8 +747,9 @@ def address_hex(address): pprint(newContract) -raw_tx, result = ledgerSign(accounts[1]['path'],tx) -validSignature, txID = validateSignature.validate(raw_tx,result[0:65],accounts[1]['publicKey'][2:]) +raw_tx, result = ledgerSign(accounts[1]['path'], tx) +validSignature, txID = validateSignature.validate(raw_tx, result[0:65], + accounts[1]['publicKey'][2:]) logger.debug('- RAW: {}'.format(raw_tx)) logger.debug('- txID: {}'.format(txID)) logger.debug('- Signature: {}'.format(binascii.hexlify(result[0:65]))) @@ -735,10 +767,12 @@ def address_hex(address): tx = tron.Transaction() newContract = contract.TriggerSmartContract( - owner_address=bytes.fromhex(accounts[1]['addressHex']), - contract_address=bytes.fromhex(address_hex("TBoTZcARzWVgnNuB9SyE3S5g1RwsXoQL16")), - data=bytes.fromhex("095ea7b3000000000000000000000000364b03e0815687edaf90b81ff58e496dea7383d700000000000000000000000000000000000000000000000000000000000f4240") - ) + owner_address=bytes.fromhex(accounts[1]['addressHex']), + contract_address=bytes.fromhex( + address_hex("TBoTZcARzWVgnNuB9SyE3S5g1RwsXoQL16")), + data=bytes.fromhex( + "095ea7b3000000000000000000000000364b03e0815687edaf90b81ff58e496dea7383d700000000000000000000000000000000000000000000000000000000000f4240" + )) c = tx.raw_data.contract.add() c.type = tron.Transaction.Contract.TriggerSmartContract @@ -748,8 +782,9 @@ def address_hex(address): pprint(newContract) -raw_tx, result = ledgerSign(accounts[1]['path'],tx) -validSignature, txID = validateSignature.validate(raw_tx,result[0:65],accounts[1]['publicKey'][2:]) +raw_tx, result = ledgerSign(accounts[1]['path'], tx) +validSignature, txID = validateSignature.validate(raw_tx, result[0:65], + accounts[1]['publicKey'][2:]) logger.debug('- RAW: {}'.format(raw_tx)) logger.debug('- txID: {}'.format(txID)) logger.debug('- Signature: {}'.format(binascii.hexlify(result[0:65]))) diff --git a/examples/signExchangeTransaction.py b/examples/signExchangeTransaction.py index 5f5b817b..36492730 100755 --- a/examples/signExchangeTransaction.py +++ b/examples/signExchangeTransaction.py @@ -6,11 +6,12 @@ import binascii parser = argparse.ArgumentParser() -parser.add_argument('--path', help="BIP32 path to retrieve. e.g. \"44'/195'/0'/0/0\".") +parser.add_argument('--path', + help="BIP32 path to retrieve. e.g. \"44'/195'/0'/0/0\".") args = parser.parse_args() if args.path == None: - args.path = "44'/195'/0'/0/0" + args.path = "44'/195'/0'/0/0" donglePath = parse_bip32_path(args.path) @@ -24,10 +25,14 @@ signatureCheck = "a1b321a521ff05b7159fee36c34c5918a7082125ef4152debf4ab73ffd366e8f4beec9d21c35c3d0c90db6de36f3b408a3f1449dc28f08b2a5a8ff04c95c007801" # P1 = 0x00 - first message -apduMessage1 = "E004{:02x}00".format(0x00) + '{:02x}'.format(int(len(donglePath) / 2) + 1 + int(len(transactionRaw) / 2)) + '{:02x}'.format(int(len(donglePath) / 4 / 2)) + donglePath + transactionRaw +apduMessage1 = "E004{:02x}00".format(0x00) + '{:02x}'.format( + int(len(donglePath) / 2) + 1 + + int(len(transactionRaw) / 2)) + '{:02x}'.format( + int(len(donglePath) / 4 / 2)) + donglePath + transactionRaw # Exchange info # To add info P1 = 0xA0 | 0x08 END | Index = 0 -apduMessage2 = "E004{:02x}00".format(0xA0 | 0x08 | 0x00) + '{:02x}'.format(int(len(exchangeInfo) / 2) ) + exchangeInfo +apduMessage2 = "E004{:02x}00".format(0xA0 | 0x08 | 0x00) + '{:02x}'.format( + int(len(exchangeInfo) / 2)) + exchangeInfo print("-= Tron Ledger =-") print("Sign Exchange Transaction") @@ -36,7 +41,7 @@ print(apduMessage2.strip()) result = dongle.exchange(bytearray.fromhex(apduMessage2)) print(binascii.hexlify(result[0:65])) -if binascii.hexlify(result[0:65]).decode()==signatureCheck: - print("Signature Validated!") +if binascii.hexlify(result[0:65]).decode() == signatureCheck: + print("Signature Validated!") else: - print("Signature Error!") \ No newline at end of file + print("Signature Error!") diff --git a/examples/signMessage.py b/examples/signMessage.py index 2bd18e3d..46fd1f20 100755 --- a/examples/signMessage.py +++ b/examples/signMessage.py @@ -12,15 +12,21 @@ import struct from Crypto.Hash import keccak -logging.basicConfig(level=logging.DEBUG, format="%(asctime)s - %(levelname)s - %(message)s") +logging.basicConfig(level=logging.DEBUG, + format="%(asctime)s - %(levelname)s - %(message)s") logger = logging.getLogger() + def apduMessage(INS, P1, P2, PATH, MESSAGE): hexString = "" if PATH: - hexString = "E0{:02x}{:02x}{:02x}{:02x}{:02x}{}".format(INS,P1,P2,(len(PATH)+len(MESSAGE))//2+1,len(PATH)//4//2,PATH+MESSAGE) + hexString = "E0{:02x}{:02x}{:02x}{:02x}{:02x}{}".format( + INS, P1, P2, (len(PATH) + len(MESSAGE)) // 2 + 1, + len(PATH) // 4 // 2, PATH + MESSAGE) else: - hexString = "E0{:02x}{:02x}{:02x}{:02x}{}".format(INS,P1,P2,len(MESSAGE)//2,MESSAGE) + hexString = "E0{:02x}{:02x}{:02x}{:02x}{}".format( + INS, P1, P2, + len(MESSAGE) // 2, MESSAGE) print(hexString) return bytearray.fromhex(hexString) @@ -44,19 +50,21 @@ def apduMessage(INS, P1, P2, PATH, MESSAGE): dongle = getDongle(True) -result = dongle.exchange(apduMessage(0x02,0x00,0x00,donglePath, "")) -size=result[0] -if size == 65 : - publicKey = result[1:1+size].hex() +result = dongle.exchange(apduMessage(0x02, 0x00, 0x00, donglePath, "")) +size = result[0] +if size == 65: + publicKey = result[1:1 + size].hex() -result = dongle.exchange(apduMessage(0x08,0x00,0x00, donglePath, encodedTx.hex())) +result = dongle.exchange( + apduMessage(0x08, 0x00, 0x00, donglePath, encodedTx.hex())) signedMessage = SIGN_MAGIC + str(len(args.message)).encode() + args.message keccak_hash = keccak.new(digest_bits=256) keccak_hash.update(signedMessage) hash = keccak_hash.digest() -validSignature = validateSignature.validateHASH(hash,result[0:65],publicKey[2:]) +validSignature = validateSignature.validateHASH(hash, result[0:65], + publicKey[2:]) logger.debug('- HASH: {}'.format(hash)) logger.debug('- Signature: {}'.format(binascii.hexlify(result[0:65]))) logger.debug('- Valid: {}'.format(validSignature)) diff --git a/examples/signPermissionedTransaction.py b/examples/signPermissionedTransaction.py index dd106a88..4cff765e 100644 --- a/examples/signPermissionedTransaction.py +++ b/examples/signPermissionedTransaction.py @@ -1,6 +1,7 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- import sys + sys.path.append("./examples/proto") from pprint import pprint @@ -15,7 +16,8 @@ import binascii import base58 -logging.basicConfig(level=logging.DEBUG, format="%(asctime)s - %(levelname)s - %(message)s") +logging.basicConfig(level=logging.DEBUG, + format="%(asctime)s - %(levelname)s - %(message)s") logger = logging.getLogger() # Start Ledger @@ -27,50 +29,67 @@ def chunks(l, n): for i in range(0, len(l), n): yield l[i:i + n] + def apduMessage(INS, P1, P2, PATH, MESSAGE): hexString = "" if PATH: - hexString = "E0{:02x}{:02x}{:02x}{:02x}{:02x}{}".format(INS,P1,P2,(len(PATH)+len(MESSAGE))//2+1,len(PATH)//4//2,PATH+MESSAGE) + hexString = "E0{:02x}{:02x}{:02x}{:02x}{:02x}{}".format( + INS, P1, P2, (len(PATH) + len(MESSAGE)) // 2 + 1, + len(PATH) // 4 // 2, PATH + MESSAGE) else: - hexString = "E0{:02x}{:02x}{:02x}{:02x}{}".format(INS,P1,P2,len(MESSAGE)//2,MESSAGE) + hexString = "E0{:02x}{:02x}{:02x}{:02x}{}".format( + INS, P1, P2, + len(MESSAGE) // 2, MESSAGE) print(hexString) return bytearray.fromhex(hexString) + def ledgerSign(PATH, tx, tokenSignature=[]): raw_tx = tx.raw_data.SerializeToString().hex() # Sign in chunks - chunkList = list(chunks(raw_tx,420)) - if len(tokenSignature)>0: + chunkList = list(chunks(raw_tx, 420)) + if len(tokenSignature) > 0: chunkList.extend(tokenSignature) # P1 = P1_FIRST = 0x00 - if len(chunkList)>1: - result = dongle.exchange(apduMessage(0x04,0x00,0x00, PATH, chunkList[0])) + if len(chunkList) > 1: + result = dongle.exchange( + apduMessage(0x04, 0x00, 0x00, PATH, chunkList[0])) else: - result = dongle.exchange(apduMessage(0x04,0x10,0x00, PATH, chunkList[0])) + result = dongle.exchange( + apduMessage(0x04, 0x10, 0x00, PATH, chunkList[0])) - for i in range(1,len(chunkList)-1-len(tokenSignature)): + for i in range(1, len(chunkList) - 1 - len(tokenSignature)): # P1 = P1_MODE = 0x80 - result = dongle.exchange(apduMessage(0x04,0x80,0x00, None, chunkList[i])) - - for i in range(0,len(tokenSignature)-1): - result = dongle.exchange(apduMessage(0x04,0xA0 | (0x00+i), 0x00, None, tokenSignature[i])) - + result = dongle.exchange( + apduMessage(0x04, 0x80, 0x00, None, chunkList[i])) + + for i in range(0, len(tokenSignature) - 1): + result = dongle.exchange( + apduMessage(0x04, 0xA0 | (0x00 + i), 0x00, None, + tokenSignature[i])) + # P1 = P1_LAST = 0x90 - if len(chunkList)>1: - if len(tokenSignature)>0: - result = dongle.exchange(apduMessage(0x04,0xA0 | 0x08 | (0x00+len(tokenSignature)-1),0x00, None, chunkList[len(chunkList)-1])) + if len(chunkList) > 1: + if len(tokenSignature) > 0: + result = dongle.exchange( + apduMessage(0x04, + 0xA0 | 0x08 | (0x00 + len(tokenSignature) - 1), + 0x00, None, chunkList[len(chunkList) - 1])) else: - result = dongle.exchange(apduMessage(0x04,0x90,0x00, None, chunkList[len(chunkList)-1])) + result = dongle.exchange( + apduMessage(0x04, 0x90, 0x00, None, + chunkList[len(chunkList) - 1])) return raw_tx, result + def address_hex(address): return base58.b58decode_check(address).hex().upper() + # Get Addresses logger.debug('-= Tron Ledger =-') - ''' Tron Protobuf ''' @@ -90,23 +109,21 @@ def address_hex(address): ''') tx = stub.CreateTransaction2( - contract.TransferContract( - owner_address=bytes.fromhex(address_hex("TUEZSdKsoDHQMeZwihtdoBiN46zxhGWYdH")), - to_address=bytes.fromhex(address_hex("TPnYqC2ukKyhEDAjqRRobSVygMAb8nAcXM")), - amount=100000 - ) - ) + contract.TransferContract( + owner_address=bytes.fromhex( + address_hex("TUEZSdKsoDHQMeZwihtdoBiN46zxhGWYdH")), + to_address=bytes.fromhex( + address_hex("TPnYqC2ukKyhEDAjqRRobSVygMAb8nAcXM")), + amount=100000)) # use permission 2 -tx.transaction.raw_data.contract[0].Permission_id=2 - - +tx.transaction.raw_data.contract[0].Permission_id = 2 -raw_tx, sign1 = ledgerSign(parse_bip32_path("44'/195'/0'/0/0"),tx.transaction) +raw_tx, sign1 = ledgerSign(parse_bip32_path("44'/195'/0'/0/0"), tx.transaction) tx.transaction.signature.extend([bytes(sign1[0:65])]) r = stub.BroadcastTransaction(tx.transaction) if r.result == True: - print("Success") + print("Success") else: - print("Fail") + print("Fail") diff --git a/examples/signStakeV2.py b/examples/signStakeV2.py index d8e0b7cd..609ae1f8 100644 --- a/examples/signStakeV2.py +++ b/examples/signStakeV2.py @@ -8,29 +8,40 @@ import validateSignature import binascii -logging.basicConfig(level=logging.DEBUG, format="%(asctime)s - %(levelname)s - %(message)s") +logging.basicConfig(level=logging.DEBUG, + format="%(asctime)s - %(levelname)s - %(message)s") logger = logging.getLogger() + def apduMessage(INS, P1, P2, PATH, MESSAGE): hexString = "" if PATH: - hexString = "E0{:02x}{:02x}{:02x}{:02x}{:02x}{}".format(INS,P1,P2,(len(PATH)+len(MESSAGE))//2+1,len(PATH)//4//2,PATH+MESSAGE) + hexString = "E0{:02x}{:02x}{:02x}{:02x}{:02x}{}".format( + INS, P1, P2, (len(PATH) + len(MESSAGE)) // 2 + 1, + len(PATH) // 4 // 2, PATH + MESSAGE) else: - hexString = "E0{:02x}{:02x}{:02x}{:02x}{}".format(INS,P1,P2,len(MESSAGE)//2,MESSAGE) + hexString = "E0{:02x}{:02x}{:02x}{:02x}{}".format( + INS, P1, P2, + len(MESSAGE) // 2, MESSAGE) print(hexString) return bytearray.fromhex(hexString) + parser = argparse.ArgumentParser() -parser.add_argument('--path', help="BIP32 path to retrieve. e.g. \"44'/195'/0'/0/0\".") +parser.add_argument('--path', + help="BIP32 path to retrieve. e.g. \"44'/195'/0'/0/0\".") args = parser.parse_args() if args.path == None: - args.path = "44'/195'/0'/0/0" + args.path = "44'/195'/0'/0/0" donglePath = parse_bip32_path(args.path) # get pubKey -apduMessage = "E0020000" + '{:02x}'.format(len(donglePath) + 1) + '{:02x}'.format(int(len(donglePath) / 4 / 2)) + donglePath +apduMessage = "E0020000" + '{:02x}'.format(len(donglePath) + + 1) + '{:02x}'.format( + int(len(donglePath) / 4 / + 2)) + donglePath apdu = bytearray.fromhex(apduMessage) print("-= Tron Ledger =-") @@ -38,10 +49,10 @@ def apduMessage(INS, P1, P2, PATH, MESSAGE): dongle = getDongle(True) result = dongle.exchange(apdu) -size=result[0] +size = result[0] pubKey = "" -if size == 65 : - pubKey = result[1:1+size].hex() +if size == 65: + pubKey = result[1:1 + size].hex() else: print("Error... Public Key Size: {:d}".format(size)) sys.exit(0) @@ -50,31 +61,38 @@ def apduMessage(INS, P1, P2, PATH, MESSAGE): # create freezeBalancev2 tx transactionRaw = "0a024e2c2208f311309df22deb2040a8c7a7eee6305a59083612550a34747970652e676f6f676c65617069732e636f6d2f70726f746f636f6c2e467265657a6542616c616e63655632436f6e7472616374121d0a15414e70ab426c186222a7e7f7bd0dbc2a4160073098108094ebdc03708088a4eee630" -apduMessage = "E0041000" + '{:02x}'.format(int(len(donglePath) / 2) + 1 + int(len(transactionRaw) / 2)) + '{:02x}'.format(int(len(donglePath) / 4 / 2)) + donglePath + transactionRaw +apduMessage = "E0041000" + '{:02x}'.format( + int(len(donglePath) / 2) + 1 + + int(len(transactionRaw) / 2)) + '{:02x}'.format( + int(len(donglePath) / 4 / 2)) + donglePath + transactionRaw apdu = bytearray.fromhex(apduMessage) print("Sign FreezeBalance") print(apduMessage.strip()) result = dongle.exchange(bytearray.fromhex(apduMessage)) -validSignature, txID = validateSignature.validate(transactionRaw,result[0:65],pubKey[2:]) +validSignature, txID = validateSignature.validate(transactionRaw, result[0:65], + pubKey[2:]) if (validSignature): logger.debug('- Valid: {}'.format(validSignature)) else: logger.error('- Valid: {}'.format(validSignature)) sys.exit(0) - # create unfreezeBalancev2 tx transactionRaw = "0a0298ee22084ad65d67e05fbae340e8f5c8cce5305a59083712550a36747970652e676f6f676c65617069732e636f6d2f70726f746f636f6c2e556e667265657a6542616c616e63655632436f6e7472616374121b0a154130ce79d807768856f5d60fb4bb3e3cdeb8c2978010c0843d70eeb4c5cce530" -apduMessage = "E0041000" + '{:02x}'.format(int(len(donglePath) / 2) + 1 + int(len(transactionRaw) / 2)) + '{:02x}'.format(int(len(donglePath) / 4 / 2)) + donglePath + transactionRaw +apduMessage = "E0041000" + '{:02x}'.format( + int(len(donglePath) / 2) + 1 + + int(len(transactionRaw) / 2)) + '{:02x}'.format( + int(len(donglePath) / 4 / 2)) + donglePath + transactionRaw apdu = bytearray.fromhex(apduMessage) print("Sign UnfreezeBalance") print(apduMessage.strip()) result = dongle.exchange(bytearray.fromhex(apduMessage)) -validSignature, txID = validateSignature.validate(transactionRaw,result[0:65],pubKey[2:]) +validSignature, txID = validateSignature.validate(transactionRaw, result[0:65], + pubKey[2:]) if (validSignature): logger.debug('- Valid: {}'.format(validSignature)) else: @@ -83,14 +101,18 @@ def apduMessage(INS, P1, P2, PATH, MESSAGE): # create WithdrawExpireUnfreeze tx transactionRaw = "0a0200fd220847e21951633b761c40e0d0f6f1e6305a5a083812560a3b747970652e676f6f676c65617069732e636f6d2f70726f746f636f6c2e5769746864726177457870697265556e667265657a65436f6e747261637412170a15414607716a6ca8fe2dc8f9e27c349a435191e4863970b5fdf2f1e630" -apduMessage = "E0041000" + '{:02x}'.format(int(len(donglePath) / 2) + 1 + int(len(transactionRaw) / 2)) + '{:02x}'.format(int(len(donglePath) / 4 / 2)) + donglePath + transactionRaw +apduMessage = "E0041000" + '{:02x}'.format( + int(len(donglePath) / 2) + 1 + + int(len(transactionRaw) / 2)) + '{:02x}'.format( + int(len(donglePath) / 4 / 2)) + donglePath + transactionRaw apdu = bytearray.fromhex(apduMessage) print("Sign WithdrawExpireUnfreeze") print(apduMessage.strip()) result = dongle.exchange(bytearray.fromhex(apduMessage)) -validSignature, txID = validateSignature.validate(transactionRaw,result[0:65],pubKey[2:]) +validSignature, txID = validateSignature.validate(transactionRaw, result[0:65], + pubKey[2:]) if (validSignature): logger.debug('- Valid: {}'.format(validSignature)) else: @@ -99,14 +121,18 @@ def apduMessage(INS, P1, P2, PATH, MESSAGE): # create delegateResource tx transactionRaw = "0a02b54922080ed077fa5aa937754090a287d7e5305a6f0839126b0a35747970652e676f6f676c65617069732e636f6d2f70726f746f636f6c2e44656c65676174655265736f75726365436f6e747261637412320a154130ce79d807768856f5d60fb4bb3e3cdeb8c2978018c0843d221541eaba05c556d953be0031b6ba4eeab309f20ab2cf7087e383d7e530" -apduMessage = "E0041000" + '{:02x}'.format(int(len(donglePath) / 2) + 1 + int(len(transactionRaw) / 2)) + '{:02x}'.format(int(len(donglePath) / 4 / 2)) + donglePath + transactionRaw +apduMessage = "E0041000" + '{:02x}'.format( + int(len(donglePath) / 2) + 1 + + int(len(transactionRaw) / 2)) + '{:02x}'.format( + int(len(donglePath) / 4 / 2)) + donglePath + transactionRaw apdu = bytearray.fromhex(apduMessage) print("Sign DelegateResource") print(apduMessage.strip()) result = dongle.exchange(bytearray.fromhex(apduMessage)) -validSignature, txID = validateSignature.validate(transactionRaw,result[0:65],pubKey[2:]) +validSignature, txID = validateSignature.validate(transactionRaw, result[0:65], + pubKey[2:]) if (validSignature): logger.debug('- Valid: {}'.format(validSignature)) else: @@ -115,17 +141,20 @@ def apduMessage(INS, P1, P2, PATH, MESSAGE): # create unDelegateResource tx transactionRaw = "0a024fe02208f346e938a781860d40e88ff8eee6305a71083a126d0a37747970652e676f6f676c65617069732e636f6d2f70726f746f636f6c2e556e44656c65676174655265736f75726365436f6e747261637412320a154130ce79d807768856f5d60fb4bb3e3cdeb8c2978018c0843d221541eaba05c556d953be0031b6ba4eeab309f20ab2cf70a6d1f4eee630" -apduMessage = "E0041000" + '{:02x}'.format(int(len(donglePath) / 2) + 1 + int(len(transactionRaw) / 2)) + '{:02x}'.format(int(len(donglePath) / 4 / 2)) + donglePath + transactionRaw +apduMessage = "E0041000" + '{:02x}'.format( + int(len(donglePath) / 2) + 1 + + int(len(transactionRaw) / 2)) + '{:02x}'.format( + int(len(donglePath) / 4 / 2)) + donglePath + transactionRaw apdu = bytearray.fromhex(apduMessage) print("Sign UnDelegateResource") print(apduMessage.strip()) result = dongle.exchange(bytearray.fromhex(apduMessage)) -validSignature, txID = validateSignature.validate(transactionRaw,result[0:65],pubKey[2:]) +validSignature, txID = validateSignature.validate(transactionRaw, result[0:65], + pubKey[2:]) if (validSignature): logger.debug('- Valid: {}'.format(validSignature)) else: logger.error('- Valid: {}'.format(validSignature)) sys.exit(0) - diff --git a/examples/signTRC10WithName.py b/examples/signTRC10WithName.py index b53e20a5..b14c0e0c 100755 --- a/examples/signTRC10WithName.py +++ b/examples/signTRC10WithName.py @@ -6,11 +6,12 @@ import binascii parser = argparse.ArgumentParser() -parser.add_argument('--path', help="BIP32 path to retrieve. e.g. \"44'/195'/0'/0/0\".") +parser.add_argument('--path', + help="BIP32 path to retrieve. e.g. \"44'/195'/0'/0/0\".") args = parser.parse_args() if args.path == None: - args.path = "44'/195'/0'/0/0" + args.path = "44'/195'/0'/0/0" donglePath = parse_bip32_path(args.path) @@ -24,10 +25,14 @@ signatureCheck = "c1a32ee50f112f2c38fd7f75961412f9af60d69adb822c507e2442a01275ff3738447c9392aaaaebefde0768936958cbf78c04a896c36b453a220ad5d07d555a00" # P1 = 0x00 - first message -apduMessage1 = "E004{:02x}00".format(0x00) + '{:02x}'.format(int(len(donglePath) / 2) + 1 + int(len(transactionRaw) / 2)) + '{:02x}'.format(int(len(donglePath) / 4 / 2)) + donglePath + transactionRaw +apduMessage1 = "E004{:02x}00".format(0x00) + '{:02x}'.format( + int(len(donglePath) / 2) + 1 + + int(len(transactionRaw) / 2)) + '{:02x}'.format( + int(len(donglePath) / 4 / 2)) + donglePath + transactionRaw # Token info # To add info P1 = 0xA0 | 0x08 END | Index = 0 -apduMessage2 = "E004{:02x}00".format(0xA0 | 0x08 | 0x00) + '{:02x}'.format(int(len(tokenInfo) / 2) ) + tokenInfo +apduMessage2 = "E004{:02x}00".format(0xA0 | 0x08 | 0x00) + '{:02x}'.format( + int(len(tokenInfo) / 2)) + tokenInfo print("-= Tron Ledger =-") print("Sign Exchange Transaction") @@ -36,7 +41,7 @@ print(apduMessage2.strip()) result = dongle.exchange(bytearray.fromhex(apduMessage2)) print(binascii.hexlify(result[0:65])) -if binascii.hexlify(result[0:65]).decode()==signatureCheck: - print("Signature Validated!") +if binascii.hexlify(result[0:65]).decode() == signatureCheck: + print("Signature Validated!") else: - print("Signature Error!") \ No newline at end of file + print("Signature Error!") diff --git a/examples/signTip712Message.py b/examples/signTip712Message.py new file mode 100644 index 00000000..3fc16bae --- /dev/null +++ b/examples/signTip712Message.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +from ledgerblue.comm import getDongle +from Crypto.Hash import keccak +from eth_keys import KeyAPI +from base import parse_bip32_path_to_bytes, parse_bip32_path, apduMessage +from eth_keys.datatypes import PublicKey +import argparse +import binascii +import sys +import validateSignature + +# Define here Chain_ID +CHAIN_ID = 0 + +# Magic define +SIGN_MAGIC = b'\x19\x01' + +parser = argparse.ArgumentParser() +parser.add_argument('--path', help="BIP 32 path to sign with") +parser.add_argument('--domainHash', help="Domain Hash (hex)") +parser.add_argument('--messageHash', help='Message Hash (hex)') +args = parser.parse_args() + +if args.path == None: + args.path = "44'/195'/0'/0/0" +if args.domainHash == None: + args.domainHash = "0101010101010101010101010101010101010101010101010101010101010101" +if args.messageHash == None: + args.messageHash = "0202020202020202020202020202020202020202020202020202020202020202" + +# get pubKey +donglePathStr = parse_bip32_path(args.path) +dongle = getDongle(True) +result = dongle.exchange(apduMessage(0x02, 0x00, 0x00, donglePathStr, "")) +size = result[0] +pubKey = "" +if size == 65: + pubKey = result[1:1 + size].hex() +else: + print("Error... Public Key Size: {:d}".format(size)) + sys.exit(0) +publicKey = PublicKey(bytes.fromhex(pubKey[2:])) + +domainHash = binascii.unhexlify(args.domainHash) +messageHash = binascii.unhexlify(args.messageHash) +encodedTx = domainHash + messageHash +donglePath = parse_bip32_path_to_bytes(args.path) +apdu = bytearray.fromhex("e00c0000") +apdu.append(len(donglePath) + 1 + len(encodedTx)) +apdu.append(len(donglePath) // 4) +apdu += donglePath + encodedTx +result = dongle.exchange(bytes(apdu)) +signature = KeyAPI.Signature(signature_bytes=result[0:65]) +msg_to_sign = SIGN_MAGIC + domainHash + messageHash +hash = keccak.new(digest_bits=256, data=msg_to_sign).digest() +pubkey = KeyAPI.PublicKey.recover_from_msg_hash(hash, signature) +validSignature = validateSignature.validateHASH(hash, result[0:65], pubKey[2:]) + +print("[INFO] Hash is: 0x", binascii.hexlify(hash).decode(), sep='') +print('{') +print(' "address get": "', publicKey.to_address(), '",', sep='') +print(' "address recover": "', pubkey.to_address(), '",', sep='') +print(' "domain hash": "', binascii.hexlify(domainHash), '",', sep='') +print(' "message hash": "', binascii.hexlify(messageHash), '",', sep='') +print(' "sig": "', signature, '",', sep='') +print(' "valid": "', validSignature, '",', sep='') +print(' "version": "3"') +print(' "signed": "ledger"') +print('}') diff --git a/examples/signTransaction.py b/examples/signTransaction.py index 1d857f48..58b2be78 100755 --- a/examples/signTransaction.py +++ b/examples/signTransaction.py @@ -6,15 +6,15 @@ import binascii parser = argparse.ArgumentParser() -parser.add_argument('--path', help="BIP32 path to retrieve. e.g. \"44'/195'/0'/0/0\".") +parser.add_argument('--path', + help="BIP32 path to retrieve. e.g. \"44'/195'/0'/0/0\".") args = parser.parse_args() if args.path == None: - args.path = "44'/195'/0'/0/0" + args.path = "44'/195'/0'/0/0" donglePath = parse_bip32_path(args.path) - # Create APDU message. transactionRaw = "0a027d52220889fd90c45b71f24740e0bcb0f2be2c5a67080112630a2d747970" \ "652e676f6f676c65617069732e636f6d2f70726f746f636f6c2e5472616e7366"\ @@ -26,7 +26,10 @@ "3185edd8a4dfda2d03aad569b856cfb3ed9db387b6589451797ff01c9c353583"\ "01" -apduMessage = "E0041000" + '{:02x}'.format(int(len(donglePath) / 2) + 1 + int(len(transactionRaw) / 2)) + '{:02x}'.format(int(len(donglePath) / 4 / 2)) + donglePath + transactionRaw +apduMessage = "E0041000" + '{:02x}'.format( + int(len(donglePath) / 2) + 1 + + int(len(transactionRaw) / 2)) + '{:02x}'.format( + int(len(donglePath) / 4 / 2)) + donglePath + transactionRaw apdu = bytearray.fromhex(apduMessage) print("-= Tron Ledger =-") @@ -36,7 +39,7 @@ print(apduMessage.strip()) result = dongle.exchange(bytearray.fromhex(apduMessage)) print(binascii.hexlify(result[0:65])) -if binascii.hexlify(result[0:65]).decode()==signatureCheck: - print("Signature Validated!") +if binascii.hexlify(result[0:65]).decode() == signatureCheck: + print("Signature Validated!") else: - print("Signature Error!") \ No newline at end of file + print("Signature Error!") diff --git a/examples/signTransactionExtension.py b/examples/signTransactionExtension.py index 6df7a71e..573ed873 100755 --- a/examples/signTransactionExtension.py +++ b/examples/signTransactionExtension.py @@ -6,20 +6,19 @@ import binascii parser = argparse.ArgumentParser() -parser.add_argument('--path', help="BIP32 path to retrieve. e.g. \"44'/195'/0'/0/0\".") +parser.add_argument('--path', + help="BIP32 path to retrieve. e.g. \"44'/195'/0'/0/0\".") args = parser.parse_args() if args.path == None: - args.path = "44'/195'/0'/0/0" + args.path = "44'/195'/0'/0/0" donglePath = parse_bip32_path(args.path) - transactionRaw = "0a02ee332208c90c7f40dfbdc51540e0dfe3ada62d5a860108041281010a30747970652e676f6f676c65617069732e636f6d2f70726f746f636f6c2e566f74655769746e657373436f6e7472616374124d0a15417773ff0ebd2d2c85761db01ae2b00c417bf1539312190a154167e39013be3cdd3814bed152d7439fb5b6791409100212190a1541c189fa6fc9ed7a3580c3fe291915d5c6a6259be710027089a2e0ada62d" transactionRawFIRST = "0a02ee332208c90c7f40dfbdc51540e0dfe3ada62d5a860108041281010a30747970652e676f6f676c65617069732e636f6d2f70726f746f636f6c2e566f74655769746e657373436f6e7472616374124d0a15417773ff0ebd2d2c85761db01ae2b00c417bf1539312190a154167e39013be3cdd3814" transactionRawEND = "bed152d7439fb5b6791409100212190a1541c189fa6fc9ed7a3580c3fe291915d5c6a6259be710027089a2e0ada62d" - transactionBIG1 = "0a02e85a2208c2b05ed1144dbfb240d8b9c98bf52d5ad901080412d4010a30747970652e676f6f676c65617069732e636f6d2f70726f746f636f6c2e566f74655769746e657373436f6e7472616374129f010a1541978dbd103cfe59c35e753d09dd44ae1ae64621c7121a0a154167e39013be3cdd38" transactionBIG2 = "14bed152d7439fb5b679140910e80712190a15412d7bdb9846499a2e5e6c5a7e6fb05731c83107c7106412190a1541c189fa6fc9" transactionBIG3 = "ed7a3580c3fe291915d5c6a6259be7100a12190a154138e3e3a163163db1f6cfceca1d1c64594dd1f0ca100112190a154178c842" @@ -31,33 +30,46 @@ # P1 = P1_SIGN = 0x10 dongle = getDongle(True) -apduMessage = "E0041000" + '{:02x}'.format(int(len(donglePath) / 2) + 1 + int(len(transactionRaw) / 2)) + '{:02x}'.format(int(len(donglePath) / 4 / 2)) + donglePath + transactionRaw +apduMessage = "E0041000" + '{:02x}'.format( + int(len(donglePath) / 2) + 1 + + int(len(transactionRaw) / 2)) + '{:02x}'.format( + int(len(donglePath) / 4 / 2)) + donglePath + transactionRaw result1 = dongle.exchange(bytearray.fromhex(apduMessage)) # P1 = P1_FIRST = 0x00 -apduMessage = "E0040000" + '{:02x}'.format(int(len(donglePath) / 2) + 1 + int(len(transactionRawFIRST) / 2)) + '{:02x}'.format(int(len(donglePath) / 4 / 2)) + donglePath + transactionRawFIRST +apduMessage = "E0040000" + '{:02x}'.format( + int(len(donglePath) / 2) + 1 + + int(len(transactionRawFIRST) / 2)) + '{:02x}'.format( + int(len(donglePath) / 4 / 2)) + donglePath + transactionRawFIRST result = dongle.exchange(bytearray.fromhex(apduMessage)) # P1 = P1_LAST = 0x90 -apduMessage = "E0049000" + '{:02x}'.format( int(len(transactionRawEND) / 2)) + transactionRawEND +apduMessage = "E0049000" + '{:02x}'.format(int( + len(transactionRawEND) / 2)) + transactionRawEND result2 = dongle.exchange(bytearray.fromhex(apduMessage)) -if (binascii.hexlify(result1[0:65]).decode()==binascii.hexlify(result2[0:65]).decode()): - print("Hash signature match") +if (binascii.hexlify(result1[0:65]).decode() == binascii.hexlify( + result2[0:65]).decode()): + print("Hash signature match") else: - print("Hash signature error") - + print("Hash signature error") # Sign in 4 batch # P1 = P1_FIRST = 0x00 -apduMessage = "E0040000" + '{:02x}'.format(int(len(donglePath) / 2) + 1 + int(len(transactionBIG1) / 2)) + '{:02x}'.format(int(len(donglePath) / 4 / 2)) + donglePath + transactionBIG1 +apduMessage = "E0040000" + '{:02x}'.format( + int(len(donglePath) / 2) + 1 + + int(len(transactionBIG1) / 2)) + '{:02x}'.format( + int(len(donglePath) / 4 / 2)) + donglePath + transactionBIG1 result1 = dongle.exchange(bytearray.fromhex(apduMessage)) # P1 = P1_MODE = 0x80 -apduMessage = "E0048000" + '{:02x}'.format( int(len(transactionBIG2) / 2)) + transactionBIG2 +apduMessage = "E0048000" + '{:02x}'.format(int( + len(transactionBIG2) / 2)) + transactionBIG2 result2 = dongle.exchange(bytearray.fromhex(apduMessage)) # P1 = P1_MODE = 0x80 -apduMessage = "E0048000" + '{:02x}'.format( int(len(transactionBIG3) / 2)) + transactionBIG3 +apduMessage = "E0048000" + '{:02x}'.format(int( + len(transactionBIG3) / 2)) + transactionBIG3 result3 = dongle.exchange(bytearray.fromhex(apduMessage)) # P1 = P1_LAST = 0x90 -apduMessage = "E0049000" + '{:02x}'.format( int(len(transactionBIG4) / 2)) + transactionBIG4 +apduMessage = "E0049000" + '{:02x}'.format(int( + len(transactionBIG4) / 2)) + transactionBIG4 result4 = dongle.exchange(bytearray.fromhex(apduMessage)) print("Signature: {}".format(binascii.hexlify(result4[0:65]).decode())) diff --git a/examples/testCustomContracts.py b/examples/testCustomContracts.py index 3b5d4c08..5bc25611 100755 --- a/examples/testCustomContracts.py +++ b/examples/testCustomContracts.py @@ -1,6 +1,7 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- import sys + sys.path.append("./examples/proto") from pprint import pprint @@ -15,7 +16,8 @@ import binascii import base58 -logging.basicConfig(level=logging.DEBUG, format="%(asctime)s - %(levelname)s - %(message)s") +logging.basicConfig(level=logging.DEBUG, + format="%(asctime)s - %(levelname)s - %(message)s") logger = logging.getLogger() @@ -24,79 +26,94 @@ def chunks(l, n): for i in range(0, len(l), n): yield l[i:i + n] + def apduMessage(INS, P1, P2, PATH, MESSAGE): hexString = "" if PATH: - hexString = "E0{:02x}{:02x}{:02x}{:02x}{:02x}{}".format(INS,P1,P2,(len(PATH)+len(MESSAGE))//2+1,len(PATH)//4//2,PATH+MESSAGE) + hexString = "E0{:02x}{:02x}{:02x}{:02x}{:02x}{}".format( + INS, P1, P2, (len(PATH) + len(MESSAGE)) // 2 + 1, + len(PATH) // 4 // 2, PATH + MESSAGE) else: - hexString = "E0{:02x}{:02x}{:02x}{:02x}{}".format(INS,P1,P2,len(MESSAGE)//2,MESSAGE) + hexString = "E0{:02x}{:02x}{:02x}{:02x}{}".format( + INS, P1, P2, + len(MESSAGE) // 2, MESSAGE) print(hexString) return bytearray.fromhex(hexString) + def ledgerSign(PATH, tx, tokenSignature=[]): raw_tx = tx.raw_data.SerializeToString().hex() # Sign in chunks - chunkList = list(chunks(raw_tx,420)) - if len(tokenSignature)>0: + chunkList = list(chunks(raw_tx, 420)) + if len(tokenSignature) > 0: chunkList.extend(tokenSignature) # P1 = P1_FIRST = 0x00 - if len(chunkList)>1: - result = dongle.exchange(apduMessage(0x04,0x00,0x00, PATH, chunkList[0])) + if len(chunkList) > 1: + result = dongle.exchange( + apduMessage(0x04, 0x00, 0x00, PATH, chunkList[0])) else: - result = dongle.exchange(apduMessage(0x04,0x10,0x00, PATH, chunkList[0])) + result = dongle.exchange( + apduMessage(0x04, 0x10, 0x00, PATH, chunkList[0])) - for i in range(1,len(chunkList)-1-len(tokenSignature)): + for i in range(1, len(chunkList) - 1 - len(tokenSignature)): # P1 = P1_MODE = 0x80 - result = dongle.exchange(apduMessage(0x04,0x80,0x00, None, chunkList[i])) - - for i in range(0,len(tokenSignature)-1): - result = dongle.exchange(apduMessage(0x04,0xA0 | (0x00+i), 0x00, None, tokenSignature[i])) - + result = dongle.exchange( + apduMessage(0x04, 0x80, 0x00, None, chunkList[i])) + + for i in range(0, len(tokenSignature) - 1): + result = dongle.exchange( + apduMessage(0x04, 0xA0 | (0x00 + i), 0x00, None, + tokenSignature[i])) + # P1 = P1_LAST = 0x90 - if len(chunkList)>1: - if len(tokenSignature)>0: - result = dongle.exchange(apduMessage(0x04,0xA0 | 0x08 | (0x00+len(tokenSignature)-1),0x00, None, chunkList[len(chunkList)-1])) + if len(chunkList) > 1: + if len(tokenSignature) > 0: + result = dongle.exchange( + apduMessage(0x04, + 0xA0 | 0x08 | (0x00 + len(tokenSignature) - 1), + 0x00, None, chunkList[len(chunkList) - 1])) else: - result = dongle.exchange(apduMessage(0x04,0x90,0x00, None, chunkList[len(chunkList)-1])) + result = dongle.exchange( + apduMessage(0x04, 0x90, 0x00, None, + chunkList[len(chunkList) - 1])) return raw_tx, result + def address_hex(address): return base58.b58decode_check(address).hex().upper() + accounts = [{ - "path": parse_bip32_path("44'/195'/0'/0/0"), - }, - { - "path": parse_bip32_path("44'/195'/1'/0/0"), - }] + "path": parse_bip32_path("44'/195'/0'/0/0"), +}, { + "path": parse_bip32_path("44'/195'/1'/0/0"), +}] # Get Addresses logger.debug('-= Tron Ledger =-') logger.debug('Requesting Public Keys...') dongle = getDongle(True) for i in range(2): - result = dongle.exchange(apduMessage(0x02,0x00,0x00,accounts[i]['path'], "")) - size=result[0] - if size == 65 : - accounts[i]['publicKey'] = result[1:1+size].hex() - size=result[size+1] - if size == 34 : - accounts[i]['address'] = result[67:67+size].decode() + result = dongle.exchange( + apduMessage(0x02, 0x00, 0x00, accounts[i]['path'], "")) + size = result[0] + if size == 65: + accounts[i]['publicKey'] = result[1:1 + size].hex() + size = result[size + 1] + if size == 34: + accounts[i]['address'] = result[67:67 + size].decode() accounts[i]['addressHex'] = address_hex(accounts[i]['address']) else: logger.error('Error... Address Size: {:d}'.format(size)) else: logger.error('Error... Public Key Size: {:d}'.format(size)) - logger.debug('Test Accounts:') for i in range(2): logger.debug('- Public Key {}: {}'.format(i, accounts[i]['publicKey'])) - logger.debug('- Address {}: {}'.format(i,accounts[i]['address'])) - - + logger.debug('- Address {}: {}'.format(i, accounts[i]['address'])) ''' Tron Protobuf ''' @@ -118,7 +135,7 @@ def address_hex(address): # check if device have custom contracts enable result = dongle.exchange(bytearray.fromhex("E0060000FF")) customAllowed = result[0] & 0x02 -if customAllowed==0: +if customAllowed == 0: print("Custom Contract not allowed, test should fail...") sys.exit(0) @@ -127,18 +144,20 @@ def address_hex(address): #################### logger.debug('\n\SmartContract Trigger: Deposit TRX in TWM Contract') data = '{:08x}'.format(0xd0e30db0) -tx = stub.TriggerContract(contract.TriggerSmartContract( +tx = stub.TriggerContract( + contract.TriggerSmartContract( owner_address=bytes.fromhex(accounts[1]['addressHex']), - contract_address=bytes.fromhex(address_hex("TTg3AAJBYsDNjx5Moc5EPNsgJSa4anJQ3M")), + contract_address=bytes.fromhex( + address_hex("TTg3AAJBYsDNjx5Moc5EPNsgJSa4anJQ3M")), call_value=1000000, - data=bytes.fromhex(data) - )) + data=bytes.fromhex(data))) -raw_tx, result = ledgerSign(accounts[1]['path'],tx.transaction) +raw_tx, result = ledgerSign(accounts[1]['path'], tx.transaction) tx.transaction.signature.extend([bytes(result[0:65])]) #r = stub.BroadcastTransaction(tx.transaction) -validSignature, txID = validateSignature.validate(raw_tx,result[0:65],accounts[1]['publicKey'][2:]) +validSignature, txID = validateSignature.validate(raw_tx, result[0:65], + accounts[1]['publicKey'][2:]) logger.debug('- RAW: {}'.format(raw_tx)) logger.debug('- txID: {}'.format(txID)) logger.debug('- Signature: {}'.format(binascii.hexlify(result[0:65]))) @@ -148,25 +167,26 @@ def address_hex(address): logger.error('- Valid: {}'.format(validSignature)) sys.exit(0) - ###################### # TWM Deposit Token # ###################### logger.debug('\n\SmartContract Trigger: Deposit BTT in TWM Contract') data = '{:08x}'.format(0xd0e30db0) -tx = stub.TriggerContract(contract.TriggerSmartContract( +tx = stub.TriggerContract( + contract.TriggerSmartContract( owner_address=bytes.fromhex(accounts[1]['addressHex']), - contract_address=bytes.fromhex(address_hex("TTg3AAJBYsDNjx5Moc5EPNsgJSa4anJQ3M")), + contract_address=bytes.fromhex( + address_hex("TTg3AAJBYsDNjx5Moc5EPNsgJSa4anJQ3M")), call_token_value=1000000, token_id=1002000, - data=bytes.fromhex(data) - )) + data=bytes.fromhex(data))) -raw_tx, result = ledgerSign(accounts[1]['path'],tx.transaction) +raw_tx, result = ledgerSign(accounts[1]['path'], tx.transaction) tx.transaction.signature.extend([bytes(result[0:65])]) #r = stub.BroadcastTransaction(tx.transaction) -validSignature, txID = validateSignature.validate(raw_tx,result[0:65],accounts[1]['publicKey'][2:]) +validSignature, txID = validateSignature.validate(raw_tx, result[0:65], + accounts[1]['publicKey'][2:]) logger.debug('- RAW: {}'.format(raw_tx)) logger.debug('- txID: {}'.format(txID)) logger.debug('- Signature: {}'.format(binascii.hexlify(result[0:65]))) @@ -180,21 +200,20 @@ def address_hex(address): # TWM Withdraw TRX # #################### logger.debug('\n\SmartContract Trigger: Withdraw TRX in TWM Contract') -data = '{:08x}{:064x}'.format( - 0x0a857040, - int(10000) - ) -tx = stub.TriggerContract(contract.TriggerSmartContract( +data = '{:08x}{:064x}'.format(0x0a857040, int(10000)) +tx = stub.TriggerContract( + contract.TriggerSmartContract( owner_address=bytes.fromhex(accounts[1]['addressHex']), - contract_address=bytes.fromhex(address_hex("TTg3AAJBYsDNjx5Moc5EPNsgJSa4anJQ3M")), - data=bytes.fromhex(data) - )) + contract_address=bytes.fromhex( + address_hex("TTg3AAJBYsDNjx5Moc5EPNsgJSa4anJQ3M")), + data=bytes.fromhex(data))) -raw_tx, result = ledgerSign(accounts[1]['path'],tx.transaction) +raw_tx, result = ledgerSign(accounts[1]['path'], tx.transaction) tx.transaction.signature.extend([bytes(result[0:65])]) #r = stub.BroadcastTransaction(tx.transaction) -validSignature, txID = validateSignature.validate(raw_tx,result[0:65],accounts[1]['publicKey'][2:]) +validSignature, txID = validateSignature.validate(raw_tx, result[0:65], + accounts[1]['publicKey'][2:]) logger.debug('- RAW: {}'.format(raw_tx)) logger.debug('- txID: {}'.format(txID)) logger.debug('- Signature: {}'.format(binascii.hexlify(result[0:65]))) @@ -204,8 +223,6 @@ def address_hex(address): logger.error('- Valid: {}'.format(validSignature)) sys.exit(0) - - ####################### # TWM Withdraw Token # ####################### @@ -214,18 +231,20 @@ def address_hex(address): 0xa1afaf8e, int(1002000), int(1000000), - ) -tx = stub.TriggerContract(contract.TriggerSmartContract( +) +tx = stub.TriggerContract( + contract.TriggerSmartContract( owner_address=bytes.fromhex(accounts[1]['addressHex']), - contract_address=bytes.fromhex(address_hex("TTg3AAJBYsDNjx5Moc5EPNsgJSa4anJQ3M")), - data=bytes.fromhex(data) - )) + contract_address=bytes.fromhex( + address_hex("TTg3AAJBYsDNjx5Moc5EPNsgJSa4anJQ3M")), + data=bytes.fromhex(data))) -raw_tx, result = ledgerSign(accounts[1]['path'],tx.transaction) +raw_tx, result = ledgerSign(accounts[1]['path'], tx.transaction) tx.transaction.signature.extend([bytes(result[0:65])]) #r = stub.BroadcastTransaction(tx.transaction) -validSignature, txID = validateSignature.validate(raw_tx,result[0:65],accounts[1]['publicKey'][2:]) +validSignature, txID = validateSignature.validate(raw_tx, result[0:65], + accounts[1]['publicKey'][2:]) logger.debug('- RAW: {}'.format(raw_tx)) logger.debug('- txID: {}'.format(txID)) logger.debug('- Signature: {}'.format(binascii.hexlify(result[0:65]))) diff --git a/examples/validateSignature.py b/examples/validateSignature.py index c1ebd75e..67734522 100755 --- a/examples/validateSignature.py +++ b/examples/validateSignature.py @@ -4,7 +4,8 @@ import hashlib import logging -logging.basicConfig(level=logging.DEBUG, format="%(asctime)s - %(levelname)s - %(message)s") +logging.basicConfig(level=logging.DEBUG, + format="%(asctime)s - %(levelname)s - %(message)s") logger = logging.getLogger() @@ -12,25 +13,26 @@ def getPublicKey(transaction, signature): s = Signature(signature_bytes=bytes.fromhex(signature)) txID = hashlib.sha256(bytes.fromhex(transaction)).digest() keys = KeyAPI('eth_keys.backends.NativeECCBackend') - public_key = keys.ecdsa_recover(txID,s) + public_key = keys.ecdsa_recover(txID, s) logger.debug(' PublicKey: {}'.format(public_key)) return public_key + def validate(transaction, signature, public_key): try: s = Signature(signature_bytes=signature) txID = hashlib.sha256( - bytes.fromhex(transaction) if type(transaction) is str else transaction - ).digest() + bytes.fromhex(transaction) if type(transaction) is + str else transaction).digest() keys = KeyAPI('eth_keys.backends.NativeECCBackend') publicKey = PublicKey(bytes.fromhex(public_key)) - return keys.ecdsa_verify(txID,s,publicKey), txID.hex() + return keys.ecdsa_verify(txID, s, publicKey), txID.hex() except: return False, "" + def validateHASH(txID, signature, public_key): s = Signature(signature_bytes=signature) keys = KeyAPI('eth_keys.backends.NativeECCBackend') publicKey = PublicKey(bytes.fromhex(public_key)) - return keys.ecdsa_verify(txID,s,publicKey) - + return keys.ecdsa_verify(txID, s, publicKey) diff --git a/src/handlers/dispatcher.c b/src/handlers/dispatcher.c index 1695fe03..bd26593b 100644 --- a/src/handlers/dispatcher.c +++ b/src/handlers/dispatcher.c @@ -64,6 +64,9 @@ int apdu_dispatcher(const command_t *cmd) { case INS_SIGN_PERSONAL_MESSAGE: return handleSignPersonalMessage(cmd->p1, cmd->p2, cmd->data, cmd->lc); + case INS_SIGN_TIP_712_MESSAGE: + return handleSignTIP712Message(cmd->p1, cmd->p2, cmd->data, cmd->lc); + default: return io_send_sw(E_INS_NOT_SUPPORTED); } diff --git a/src/handlers/handlers.h b/src/handlers/handlers.h index 8dbd6237..573f9ade 100644 --- a/src/handlers/handlers.h +++ b/src/handlers/handlers.h @@ -29,6 +29,7 @@ #define INS_GET_APP_CONFIGURATION 0x06 // version and settings #define INS_SIGN_PERSONAL_MESSAGE 0x08 #define INS_GET_ECDH_SECRET 0x0A +#define INS_SIGN_TIP_712_MESSAGE 0x0C #define P1_CONFIRM 0x01 #define P1_NON_CONFIRM 0x00 @@ -51,3 +52,4 @@ int handleSignByHash(uint8_t p1, uint8_t p2, uint8_t *workBuffer, uint16_t dataL int handleGetAppConfiguration(uint8_t p1, uint8_t p2, uint8_t *workBuffer, uint16_t dataLength); int handleSignPersonalMessage(uint8_t p1, uint8_t p2, uint8_t *workBuffer, uint16_t dataLength); int handleECDHSecret(uint8_t p1, uint8_t p2, uint8_t *workBuffer, uint16_t dataLength); +int handleSignTIP712Message(uint8_t p1, uint8_t p2, uint8_t *workBuffer, uint16_t dataLength); diff --git a/src/handlers/sign_tip712_message.c b/src/handlers/sign_tip712_message.c new file mode 100644 index 00000000..4fd3769b --- /dev/null +++ b/src/handlers/sign_tip712_message.c @@ -0,0 +1,69 @@ +/******************************************************************************* + * Tron Ledger Wallet + * (c) 2023 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ +#include +#include + +#include "cx.h" +#include "io.h" + +#include "format.h" + +#include "helpers.h" +#include "ui_review_menu.h" +#include "app_errors.h" +#include "handlers.h" +#include "parse.h" +#include "ui_globals.h" +#include "settings.h" + +int handleSignTIP712Message(uint8_t p1, uint8_t p2, uint8_t *workBuffer, uint16_t dataLength) { + uint8_t i; + if (!HAS_SETTING(S_SIGN_BY_HASH)) { + return io_send_sw(E_MISSING_SETTING_SIGN_BY_HASH); + } + + if ((p1 != 00) || (p2 != 00)) { + return io_send_sw(E_INCORRECT_P1_P2); + } + if (dataLength < 1) { + return io_send_sw(E_INCORRECT_DATA); + } + messageSigningContext712.pathLength = workBuffer[0]; + if ((messageSigningContext712.pathLength < 0x01) || + (messageSigningContext712.pathLength > MAX_BIP32_PATH)) { + return io_send_sw(E_INCORRECT_DATA); + } + workBuffer++; + dataLength--; + for (i = 0; i < messageSigningContext712.pathLength; i++) { + if (dataLength < 4) { + return io_send_sw(E_INCORRECT_DATA); + } + messageSigningContext712.bip32Path[i] = U4BE(workBuffer, 0); + workBuffer += 4; + dataLength -= 4; + } + if (dataLength < HASH_SIZE * 2) { + return io_send_sw(E_INCORRECT_DATA); + } + memmove(messageSigningContext712.domainHash, workBuffer, HASH_SIZE); + memmove(messageSigningContext712.messageHash, workBuffer + HASH_SIZE, HASH_SIZE); + + ux_flow_display(APPROVAL_SIGN_TIP72_TRANSACTION, false); + + return 0; +} diff --git a/src/parse.c b/src/parse.c index dd03cd6b..d8cb924e 100644 --- a/src/parse.c +++ b/src/parse.c @@ -19,7 +19,7 @@ #include "pb.h" #include "misc/TronApp.pb.h" - +#include "format.h" #include "parse.h" #include "settings.h" #include "tokens.h" @@ -889,3 +889,20 @@ parserStatus_e processTx(uint8_t *buffer, uint32_t length, txContent_t *content) return USTREAM_PROCESSING; } + +int bytes_to_string(char *out, size_t outl, const void *value, size_t len) { + if (outl <= 2) { + // Need at least '0x' and 1 digit + return -1; + } + if (strlcpy(out, "0x", outl) != 2) { + goto err; + } + if (format_hex(value, len, out + 2, outl - 2) < 0) { + goto err; + } + return 0; +err: + *out = '\0'; + return -1; +} \ No newline at end of file diff --git a/src/parse.h b/src/parse.h index 4adf6afc..c55674e6 100644 --- a/src/parse.h +++ b/src/parse.h @@ -23,6 +23,14 @@ #define MAX_RAW_SIGNATURE 65 #define MAX_TOKEN_LENGTH 67 +#define NETWORK_STRING_MAX_SIZE 16 +#ifdef TARGET_NANOS +#define SHARED_CTX_FIELD_1_SIZE 100 +#else +#define SHARED_CTX_FIELD_1_SIZE 256 +#endif +#define SHARED_CTX_FIELD_2_SIZE 40 + typedef union { protocol_TransferContract transfer_contract; protocol_TransferAssetContract transfer_asset_contract; @@ -143,6 +151,31 @@ typedef struct txContent_t { uint32_t customData; } txContent_t; +typedef struct messageSigningContext712_t { + uint8_t pathLength; + uint32_t bip32Path[MAX_BIP32_PATH]; + uint8_t domainHash[32]; + uint8_t messageHash[32]; +} messageSigningContext712_t; + +typedef struct txStringProperties_t { + char fullAddress[43]; + char fullAmount[79]; // 2^256 is 78 digits long + char maxFee[50]; + char nonce[8]; // 10M tx per account ought to be enough for everybody + char network_name[NETWORK_STRING_MAX_SIZE]; +} txStringProperties_t; + +typedef struct strDataTmp_t { + char tmp[SHARED_CTX_FIELD_1_SIZE]; + char tmp2[SHARED_CTX_FIELD_2_SIZE]; +} strDataTmp_t; + +typedef union { + txStringProperties_t common; + strDataTmp_t tmp; +} strings_t; + bool setContractType(contractType_e type, char *out, size_t outlen); bool setExchangeContractDetail(contractType_e type, char *out, size_t outlen); @@ -163,4 +196,6 @@ parserStatus_e processTx(uint8_t *buffer, uint32_t length, txContent_t *content) extern txContent_t txContent; extern txContext_t txContext; +int bytes_to_string(char *out, size_t outl, const void *value, size_t len); + #endif diff --git a/src/ui/ui_globals.c b/src/ui/ui_globals.c index c876757f..13543a5c 100644 --- a/src/ui/ui_globals.c +++ b/src/ui/ui_globals.c @@ -34,6 +34,8 @@ char fullHash[HASH_SIZE * 2 + 1]; int8_t votes_count; transactionContext_t transactionContext; publicKeyContext_t publicKeyContext; +messageSigningContext712_t messageSigningContext712; +strings_t strings; bool ui_callback_address_ok(bool display_menu) { helper_send_response_pubkey(&publicKeyContext); @@ -147,3 +149,138 @@ bool ui_callback_ecdh_ok(bool display_menu) { return false; } } + +static const uint8_t TIP_712_MAGIC[] = {0x19, 0x01}; + +void format_signature_out(const uint8_t *signature) { + memset(G_io_apdu_buffer, 0x00, 64); + uint8_t offset = 0; + uint8_t xoffset = 4; // point to r value + // copy r + uint8_t xlength = signature[xoffset - 1]; + if (xlength == 33) { + xlength = 32; + xoffset++; + } + memmove(G_io_apdu_buffer + offset + 32 - xlength, signature + xoffset, xlength); + offset += 32; + xoffset += xlength + 2; // move over rvalue and TagLEn + // copy s value + xlength = signature[xoffset - 1]; + if (xlength == 33) { + xlength = 32; + xoffset++; + } + memmove(G_io_apdu_buffer + offset + 32 - xlength, signature + xoffset, xlength); +} + +bool ui_callback_signMessage712_v0_ok(bool display_menu) { + uint32_t tx = 0; + cx_err_t err; + + cx_ecfp_private_key_t privateKey; + uint8_t signature[100]; + unsigned int info = 0; + + cx_sha3_t sha3; + uint8_t hash[32]; + io_seproxyhal_io_heartbeat(); + + if (cx_keccak_init_no_throw(&sha3, 256) != CX_OK) { + return false; + } + + if (cx_hash_no_throw((cx_hash_t *) &sha3, + 0, + (uint8_t *) TIP_712_MAGIC, + sizeof(TIP_712_MAGIC), + NULL, + 0) != CX_OK) { + return false; + } + + if (cx_hash_no_throw((cx_hash_t *) &sha3, + 0, + messageSigningContext712.domainHash, + sizeof(messageSigningContext712.domainHash), + NULL, + 0) != CX_OK) { + return false; + } + + if (cx_hash_no_throw((cx_hash_t *) &sha3, + CX_LAST, + messageSigningContext712.messageHash, + sizeof(messageSigningContext712.messageHash), + hash, + sizeof(hash)) != CX_OK) { + return false; + } + PRINTF("TIP712 hash to sign %.*H\n", 32, hash); + + io_seproxyhal_io_heartbeat(); + // Get private key + err = bip32_derive_init_privkey_256(CX_CURVE_256K1, + messageSigningContext712.bip32Path, + messageSigningContext712.pathLength, + &privateKey, + NULL); + if (err != CX_OK) { + goto end; + } + + io_seproxyhal_io_heartbeat(); + unsigned int signatureLength = sizeof(signature); + if (cx_ecdsa_sign_no_throw(&privateKey, + CX_RND_RFC6979 | CX_LAST, + CX_SHA256, + hash, + sizeof(hash), + signature, + &signatureLength, + &info) != CX_OK) { + return false; + } + + format_signature_out(signature); + G_io_apdu_buffer[64] = 0; + if (info & CX_ECCINFO_PARITY_ODD) { + G_io_apdu_buffer[64]++; + } + tx = 65; + +end: + // Clear tmp buffer data + explicit_bzero(&privateKey, sizeof(privateKey)); + + if (err == CX_OK) { + // Send back the response, do not restart the event loop + io_send_response_pointer(G_io_apdu_buffer, tx, E_OK); + } else { + io_send_sw(E_SECURITY_STATUS_NOT_SATISFIED); + } + + if (display_menu) { + // Display back the original UX + ui_idle(); + } + + if (err == CX_OK) { + return true; + } else { + return false; + } +} + +bool ui_callback_signMessage712_v0_cancel(bool display_menu) { + G_io_apdu_buffer[0] = 0x69; + G_io_apdu_buffer[1] = 0x85; + // Send back the response, do not restart the event loop + io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, 2); + if (display_menu) { + // Display back the original UX + ui_idle(); + } + + return true; +} \ No newline at end of file diff --git a/src/ui/ui_globals.h b/src/ui/ui_globals.h index 506cef0d..43b00aa8 100644 --- a/src/ui/ui_globals.h +++ b/src/ui/ui_globals.h @@ -43,9 +43,13 @@ extern char fullHash[HASH_SIZE * 2 + 1]; extern int8_t votes_count; extern transactionContext_t transactionContext; extern publicKeyContext_t publicKeyContext; +extern messageSigningContext712_t messageSigningContext712; +extern strings_t strings; bool ui_callback_tx_ok(bool display_menu); bool ui_callback_tx_cancel(bool display_menu); bool ui_callback_address_ok(bool display_menu); bool ui_callback_signMessage_ok(bool display_menu); bool ui_callback_ecdh_ok(bool display_menu); +bool ui_callback_signMessage712_v0_cancel(bool display_menu); +bool ui_callback_signMessage712_v0_ok(bool display_menu); \ No newline at end of file diff --git a/src/ui/ui_review_menu.h b/src/ui/ui_review_menu.h index ef47b3b7..f81c885e 100644 --- a/src/ui/ui_review_menu.h +++ b/src/ui/ui_review_menu.h @@ -37,6 +37,7 @@ typedef enum { APPROVAL_DELEGATE_RESOURCE_TRANSACTION, APPROVAL_UNDELEGATE_RESOURCE_TRANSACTION, APPROVAL_WITHDRAWEXPIREUNFREEZE_TRANSACTION, + APPROVAL_SIGN_TIP72_TRANSACTION, } ui_approval_state_t; void ux_flow_display(ui_approval_state_t state, bool warning); diff --git a/src/ui/ui_review_menu_bagl.c b/src/ui/ui_review_menu_bagl.c index 388b86fa..eb1ccdf4 100644 --- a/src/ui/ui_review_menu_bagl.c +++ b/src/ui/ui_review_menu_bagl.c @@ -756,6 +756,77 @@ UX_DEF(ux_sign_flow, &ux_sign_flow_4_step, &ux_sign_flow_5_step); +// Sign TRC712 message +////////////////////////////////////////////////////////////////////// + +void prepare_domain_hash_v0() { + bytes_to_string(strings.tmp.tmp, + sizeof(strings.tmp.tmp), + messageSigningContext712.domainHash, + 32); +} + +void prepare_message_hash_v0() { + bytes_to_string(strings.tmp.tmp, + sizeof(strings.tmp.tmp), + messageSigningContext712.messageHash, + 32); +} + +UX_STEP_NOCB(ux_sign_712_v0_1_step, + pnn, + { + &C_icon_certificate, + "Sign", + "typed message", + }); +UX_STEP_NOCB_INIT(ux_sign_712_v0_2_step, + bnnn_paging, + prepare_domain_hash_v0(), + { + .title = "Domain hash", + .text = strings.tmp.tmp, + }); +UX_STEP_NOCB_INIT(ux_sign_712_v0_3_step, + bnnn_paging, + prepare_message_hash_v0(), + { + .title = "Message hash", + .text = strings.tmp.tmp, + }); +UX_STEP_VALID(ux_sign_712_v0_4_step, + pbb, + ui_callback_signMessage712_v0_ok(true), + { + &C_icon_validate_14, + "Sign", + "message", + }); +UX_STEP_VALID(ux_sign_712_v0_5_step, + pbb, + ui_callback_signMessage712_v0_cancel(true), + { + &C_icon_crossmark, + "Cancel", + "signature", + }); + +// UX_DEF(ux_sign_712_v0_flow, +// &ux_sign_712_v0_1_step, +// &ux_sign_712_v0_2_step, +// &ux_sign_712_v0_3_step, +// &ux_sign_712_v0_4_step, +// &ux_sign_712_v0_5_step); + +const ux_flow_step_t *const ux_sign_712_v0_flow[] = { + &ux_sign_712_v0_1_step, + &ux_sign_712_v0_2_step, + &ux_sign_712_v0_3_step, + &ux_sign_712_v0_4_step, + &ux_sign_712_v0_5_step, + FLOW_END_STEP, +}; + // CUSTOM CONTRACT ////////////////////////////////////////////////////////////////////// UX_STEP_NOCB(ux_approval_custom_contract_1_step, @@ -969,6 +1040,9 @@ void ux_flow_display(ui_approval_state_t state, bool data_warning) { : ux_approval_withdraw_expire_unfreeze_flow), NULL); break; + case APPROVAL_SIGN_TIP72_TRANSACTION: + ux_flow_init(0, ux_sign_712_v0_flow, NULL); + break; default: PRINTF("This should not happen !\n"); break; diff --git a/src/ui/ui_review_menu_nbgl.c b/src/ui/ui_review_menu_nbgl.c index 90e1a572..0b9ab510 100644 --- a/src/ui/ui_review_menu_nbgl.c +++ b/src/ui/ui_review_menu_nbgl.c @@ -138,6 +138,8 @@ static void reviewChoice(bool confirm) { ret = ui_callback_signMessage_ok(false); } else if (txInfos.state == APPROVAL_SHARED_ECDH_SECRET) { ret = ui_callback_ecdh_ok(false); + } else if (txInfos.state == APPROVAL_SIGN_TIP72_TRANSACTION) { + ret = ui_callback_signMessage712_v0_ok(false); } else { ret = ui_callback_tx_ok(false); } @@ -153,7 +155,11 @@ static void reviewChoice(bool confirm) { } static void rejectConfirmation(void) { - ui_callback_tx_cancel(false); + if (txInfos.state == APPROVAL_SIGN_TIP72_TRANSACTION) { + ui_callback_signMessage712_v0_cancel(false); + } else { + ui_callback_tx_cancel(false); + } nbgl_useCaseReviewStatus(STATUS_TYPE_TRANSACTION_REJECTED, ui_idle); } @@ -165,6 +171,11 @@ static void rejectChoice(void) { rejectConfirmation); } +static char *format_hash(const uint8_t *hash, char *buffer, size_t buffer_size, size_t offset) { + bytes_to_string(buffer + offset, buffer_size - offset, hash, 32); + return buffer + offset; +} + static void prepareTxInfos(ui_approval_state_t state, bool data_warning) { memset(&txInfos, 0, sizeof(txInfos)); memset(&infoLongPress, 0, sizeof(infoLongPress)); @@ -308,6 +319,21 @@ static void prepareTxInfos(ui_approval_state_t state, bool data_warning) { txInfos.flowTitle = "Review message"; infoLongPress.text = "Sign message"; break; + case APPROVAL_SIGN_TIP72_TRANSACTION: + txInfos.fields[0].item = "Domain hash"; + txInfos.fields[0].value = format_hash(messageSigningContext712.domainHash, + strings.tmp.tmp, + sizeof(strings.tmp.tmp), + 0); + txInfos.fields[1].item = "Message hash"; + txInfos.fields[1].value = format_hash(messageSigningContext712.messageHash, + strings.tmp.tmp, + sizeof(strings.tmp.tmp), + 70); + pairList.nbPairs = 2; + txInfos.flowTitle = "Review message"; + infoLongPress.text = "Sign message"; + break; case APPROVAL_CUSTOM_CONTRACT: txInfos.warnings[CUSTOM_CONTRACT_WARNING] = true; txInfos.fields[0].item = "Contract"; diff --git a/tests/snapshots/flex/test_trx_sign_tip712/00000.png b/tests/snapshots/flex/test_trx_sign_tip712/00000.png new file mode 100644 index 00000000..80e6cfdf Binary files /dev/null and b/tests/snapshots/flex/test_trx_sign_tip712/00000.png differ diff --git a/tests/snapshots/flex/test_trx_sign_tip712/00001.png b/tests/snapshots/flex/test_trx_sign_tip712/00001.png new file mode 100644 index 00000000..ad37fc08 Binary files /dev/null and b/tests/snapshots/flex/test_trx_sign_tip712/00001.png differ diff --git a/tests/snapshots/flex/test_trx_sign_tip712/00002.png b/tests/snapshots/flex/test_trx_sign_tip712/00002.png new file mode 100644 index 00000000..21660563 Binary files /dev/null and b/tests/snapshots/flex/test_trx_sign_tip712/00002.png differ diff --git a/tests/snapshots/flex/test_trx_sign_tip712/00003.png b/tests/snapshots/flex/test_trx_sign_tip712/00003.png new file mode 100644 index 00000000..aa088be4 Binary files /dev/null and b/tests/snapshots/flex/test_trx_sign_tip712/00003.png differ diff --git a/tests/snapshots/flex/test_trx_sign_tip712/00004.png b/tests/snapshots/flex/test_trx_sign_tip712/00004.png new file mode 100644 index 00000000..be51a9d5 Binary files /dev/null and b/tests/snapshots/flex/test_trx_sign_tip712/00004.png differ diff --git a/tests/snapshots/flex/test_trx_sign_tip712/00005.png b/tests/snapshots/flex/test_trx_sign_tip712/00005.png new file mode 100644 index 00000000..8a75d8c4 Binary files /dev/null and b/tests/snapshots/flex/test_trx_sign_tip712/00005.png differ diff --git a/tests/snapshots/nanos/test_trx_sign_tip712/00000.png b/tests/snapshots/nanos/test_trx_sign_tip712/00000.png new file mode 100644 index 00000000..910bc430 Binary files /dev/null and b/tests/snapshots/nanos/test_trx_sign_tip712/00000.png differ diff --git a/tests/snapshots/nanos/test_trx_sign_tip712/00001.png b/tests/snapshots/nanos/test_trx_sign_tip712/00001.png new file mode 100644 index 00000000..40515f8f Binary files /dev/null and b/tests/snapshots/nanos/test_trx_sign_tip712/00001.png differ diff --git a/tests/snapshots/nanos/test_trx_sign_tip712/00002.png b/tests/snapshots/nanos/test_trx_sign_tip712/00002.png new file mode 100644 index 00000000..faf62b05 Binary files /dev/null and b/tests/snapshots/nanos/test_trx_sign_tip712/00002.png differ diff --git a/tests/snapshots/nanos/test_trx_sign_tip712/00003.png b/tests/snapshots/nanos/test_trx_sign_tip712/00003.png new file mode 100644 index 00000000..21e96175 Binary files /dev/null and b/tests/snapshots/nanos/test_trx_sign_tip712/00003.png differ diff --git a/tests/snapshots/nanos/test_trx_sign_tip712/00004.png b/tests/snapshots/nanos/test_trx_sign_tip712/00004.png new file mode 100644 index 00000000..a2b48cba Binary files /dev/null and b/tests/snapshots/nanos/test_trx_sign_tip712/00004.png differ diff --git a/tests/snapshots/nanos/test_trx_sign_tip712/00005.png b/tests/snapshots/nanos/test_trx_sign_tip712/00005.png new file mode 100644 index 00000000..d0c22057 Binary files /dev/null and b/tests/snapshots/nanos/test_trx_sign_tip712/00005.png differ diff --git a/tests/snapshots/nanos/test_trx_sign_tip712/00006.png b/tests/snapshots/nanos/test_trx_sign_tip712/00006.png new file mode 100644 index 00000000..5ddeee94 Binary files /dev/null and b/tests/snapshots/nanos/test_trx_sign_tip712/00006.png differ diff --git a/tests/snapshots/nanos/test_trx_sign_tip712/00007.png b/tests/snapshots/nanos/test_trx_sign_tip712/00007.png new file mode 100644 index 00000000..9cf81f79 Binary files /dev/null and b/tests/snapshots/nanos/test_trx_sign_tip712/00007.png differ diff --git a/tests/snapshots/nanos/test_trx_sign_tip712/00008.png b/tests/snapshots/nanos/test_trx_sign_tip712/00008.png new file mode 100644 index 00000000..9af5a476 Binary files /dev/null and b/tests/snapshots/nanos/test_trx_sign_tip712/00008.png differ diff --git a/tests/snapshots/nanos/test_trx_sign_tip712/00009.png b/tests/snapshots/nanos/test_trx_sign_tip712/00009.png new file mode 100644 index 00000000..f5c2d677 Binary files /dev/null and b/tests/snapshots/nanos/test_trx_sign_tip712/00009.png differ diff --git a/tests/snapshots/nanos/test_trx_sign_tip712/00010.png b/tests/snapshots/nanos/test_trx_sign_tip712/00010.png new file mode 100644 index 00000000..c76320e2 Binary files /dev/null and b/tests/snapshots/nanos/test_trx_sign_tip712/00010.png differ diff --git a/tests/snapshots/nanosp/test_trx_sign_tip712/00000.png b/tests/snapshots/nanosp/test_trx_sign_tip712/00000.png new file mode 100644 index 00000000..00a89fd6 Binary files /dev/null and b/tests/snapshots/nanosp/test_trx_sign_tip712/00000.png differ diff --git a/tests/snapshots/nanosp/test_trx_sign_tip712/00001.png b/tests/snapshots/nanosp/test_trx_sign_tip712/00001.png new file mode 100644 index 00000000..9ef4af9e Binary files /dev/null and b/tests/snapshots/nanosp/test_trx_sign_tip712/00001.png differ diff --git a/tests/snapshots/nanosp/test_trx_sign_tip712/00002.png b/tests/snapshots/nanosp/test_trx_sign_tip712/00002.png new file mode 100644 index 00000000..9da987be Binary files /dev/null and b/tests/snapshots/nanosp/test_trx_sign_tip712/00002.png differ diff --git a/tests/snapshots/nanosp/test_trx_sign_tip712/00003.png b/tests/snapshots/nanosp/test_trx_sign_tip712/00003.png new file mode 100644 index 00000000..34c92571 Binary files /dev/null and b/tests/snapshots/nanosp/test_trx_sign_tip712/00003.png differ diff --git a/tests/snapshots/nanosp/test_trx_sign_tip712/00004.png b/tests/snapshots/nanosp/test_trx_sign_tip712/00004.png new file mode 100644 index 00000000..c9969a17 Binary files /dev/null and b/tests/snapshots/nanosp/test_trx_sign_tip712/00004.png differ diff --git a/tests/snapshots/nanosp/test_trx_sign_tip712/00005.png b/tests/snapshots/nanosp/test_trx_sign_tip712/00005.png new file mode 100644 index 00000000..e7ffedd9 Binary files /dev/null and b/tests/snapshots/nanosp/test_trx_sign_tip712/00005.png differ diff --git a/tests/snapshots/nanosp/test_trx_sign_tip712/00006.png b/tests/snapshots/nanosp/test_trx_sign_tip712/00006.png new file mode 100644 index 00000000..d3bef128 Binary files /dev/null and b/tests/snapshots/nanosp/test_trx_sign_tip712/00006.png differ diff --git a/tests/snapshots/nanox/test_trx_sign_tip712/00000.png b/tests/snapshots/nanox/test_trx_sign_tip712/00000.png new file mode 100644 index 00000000..00a89fd6 Binary files /dev/null and b/tests/snapshots/nanox/test_trx_sign_tip712/00000.png differ diff --git a/tests/snapshots/nanox/test_trx_sign_tip712/00001.png b/tests/snapshots/nanox/test_trx_sign_tip712/00001.png new file mode 100644 index 00000000..9ef4af9e Binary files /dev/null and b/tests/snapshots/nanox/test_trx_sign_tip712/00001.png differ diff --git a/tests/snapshots/nanox/test_trx_sign_tip712/00002.png b/tests/snapshots/nanox/test_trx_sign_tip712/00002.png new file mode 100644 index 00000000..9da987be Binary files /dev/null and b/tests/snapshots/nanox/test_trx_sign_tip712/00002.png differ diff --git a/tests/snapshots/nanox/test_trx_sign_tip712/00003.png b/tests/snapshots/nanox/test_trx_sign_tip712/00003.png new file mode 100644 index 00000000..34c92571 Binary files /dev/null and b/tests/snapshots/nanox/test_trx_sign_tip712/00003.png differ diff --git a/tests/snapshots/nanox/test_trx_sign_tip712/00004.png b/tests/snapshots/nanox/test_trx_sign_tip712/00004.png new file mode 100644 index 00000000..c9969a17 Binary files /dev/null and b/tests/snapshots/nanox/test_trx_sign_tip712/00004.png differ diff --git a/tests/snapshots/nanox/test_trx_sign_tip712/00005.png b/tests/snapshots/nanox/test_trx_sign_tip712/00005.png new file mode 100644 index 00000000..e7ffedd9 Binary files /dev/null and b/tests/snapshots/nanox/test_trx_sign_tip712/00005.png differ diff --git a/tests/snapshots/nanox/test_trx_sign_tip712/00006.png b/tests/snapshots/nanox/test_trx_sign_tip712/00006.png new file mode 100644 index 00000000..d3bef128 Binary files /dev/null and b/tests/snapshots/nanox/test_trx_sign_tip712/00006.png differ diff --git a/tests/snapshots/stax/test_trx_sign_tip712/00000.png b/tests/snapshots/stax/test_trx_sign_tip712/00000.png new file mode 100644 index 00000000..338de560 Binary files /dev/null and b/tests/snapshots/stax/test_trx_sign_tip712/00000.png differ diff --git a/tests/snapshots/stax/test_trx_sign_tip712/00001.png b/tests/snapshots/stax/test_trx_sign_tip712/00001.png new file mode 100644 index 00000000..f0b62653 Binary files /dev/null and b/tests/snapshots/stax/test_trx_sign_tip712/00001.png differ diff --git a/tests/snapshots/stax/test_trx_sign_tip712/00002.png b/tests/snapshots/stax/test_trx_sign_tip712/00002.png new file mode 100644 index 00000000..64a8a381 Binary files /dev/null and b/tests/snapshots/stax/test_trx_sign_tip712/00002.png differ diff --git a/tests/snapshots/stax/test_trx_sign_tip712/00003.png b/tests/snapshots/stax/test_trx_sign_tip712/00003.png new file mode 100644 index 00000000..3e733241 Binary files /dev/null and b/tests/snapshots/stax/test_trx_sign_tip712/00003.png differ diff --git a/tests/snapshots/stax/test_trx_sign_tip712/00004.png b/tests/snapshots/stax/test_trx_sign_tip712/00004.png new file mode 100644 index 00000000..2ba6d27d Binary files /dev/null and b/tests/snapshots/stax/test_trx_sign_tip712/00004.png differ diff --git a/tests/snapshots/stax/test_trx_sign_tip712/00005.png b/tests/snapshots/stax/test_trx_sign_tip712/00005.png new file mode 100644 index 00000000..bc68c518 Binary files /dev/null and b/tests/snapshots/stax/test_trx_sign_tip712/00005.png differ diff --git a/tests/test_trx.py b/tests/test_trx.py index 4e6c1466..8db27e1d 100644 --- a/tests/test_trx.py +++ b/tests/test_trx.py @@ -6,6 +6,7 @@ import sys import struct import re +import binascii from ragger.error import ExceptionRAPDU from contextlib import contextmanager from pathlib import Path @@ -15,6 +16,7 @@ from tron import TronClient, Errors, CLA, InsType from ragger.bip import pack_derivation_path from utils import check_tx_signature, check_hash_signature +from eth_keys import KeyAPI ''' Tron Protobuf ''' @@ -60,7 +62,7 @@ def test_trx_get_version(self, backend, firmware, navigator): major, minor, patch = client.unpackGetVersionResponse(resp.data) path = str(Path(__file__).parent.parent.resolve()) + "/VERSION" version_file = open(path, "r").read() - version = re.findall("(\d)\.(\d)\.(\d)", version_file) + version = re.findall(r"(\d)\.(\d)\.(\d)", version_file) assert (major == int(version[0][0])) assert (minor == int(version[0][1])) assert (patch == int(version[0][2])) @@ -506,6 +508,34 @@ def test_trx_sign_hash(self, backend, firmware, navigator): assert check_hash_signature(hash_to_sign, resp.data[0:65], client.getAccount(0)['publicKey'][2:]) + def test_trx_sign_tip712(self, backend, firmware, navigator): + client = TronClient(backend, firmware, navigator) + domainHash = bytes.fromhex( + '6137beb405d9ff777172aa879e33edb34a1460e701802746c5ef96e741710e59') + messageHash = bytes.fromhex( + 'eb4221181ff3f1a83ea7313993ca9218496e424604ba9492bb4052c03d5c3df8') + data = pack_derivation_path(client.getAccount(0)['path']) + data += domainHash + data += messageHash + + with backend.exchange_async(CLA, InsType.SIGN_TIP_712_MESSAGE, 0x00, + 0x00, data): + if firmware.is_nano: + text = "message" + else: + text = "Hold to sign" + client.navigate(Path(currentframe().f_code.co_name), text) + + resp = backend.last_async_response + + # Magic define + SIGN_MAGIC = b'\x19\x01' + msg_to_sign = SIGN_MAGIC + domainHash + messageHash + hash = keccak.new(digest_bits=256, data=msg_to_sign).digest() + + assert check_hash_signature(hash, resp.data[0:65], + client.getAccount(0)['publicKey'][2:]) + def test_trx_send_permissioned(self, backend, firmware, navigator): client = TronClient(backend, firmware, navigator) tx = client.packContract( diff --git a/tests/tron.py b/tests/tron.py index 43b326d0..96a04177 100644 --- a/tests/tron.py +++ b/tests/tron.py @@ -61,6 +61,7 @@ class InsType(IntEnum): GET_APP_CONFIGURATION = 0x06 # Version and settings SIGN_PERSONAL_MESSAGE = 0x08 GET_ECDH_SECRET = 0x0A + SIGN_TIP_712_MESSAGE = 0x0C class Errors(IntEnum):