APDU requests - SkycoinProject/ledger-nano GitHub Wiki

APDU (Application Protocol Data Unit)

In the Ledger app, each command/response packet is called an APDU. The application is driven by a never-ending APDU interpretation loop called straight from the application main function. More about APDU: good overview, wiki page, ledger app structure and I/O

BIP44 path

For nearly every call you need to send BIP44 address, which consists of 5 levels, 4 bytes each.

(m / purpose / coin_type / account / change / address_index)

Purpose is always equal to 0x8000002C. Coin_type is always equal to (Skycoin doesn't register their coin_type). You can use account different for your purpose, so you use just 0. As the address will be seen outside the wallet in Ledger app, so change has to be 0. For address_index you can just use 0. More about BIP44.

Implemented APDUs:

1. Get Skycoin public key:

This command returns the compressed public key for the given BIP44 path. After that you can check your skycoin address in main menu -> settings -> address.

Description:

  • Command
CLA INS P1 P2 Lc Le
A1 0x04
  • Input data
Description Length
BIP44 address 20
  • Output data
Description Length
Public key 33

2. Get signed public key:

This command returns signed public key, so companion app can check, that Ledger device is genuine. More details on Ledger documentation.

Description:

  • Command
CLA INS P1 P2 Lc Le
A1 0x08
  • Input data
Description Length
BIP44 address 20
  • Output data
Description Length
Signed public key 65

(more about signing here)

3. Get Skycoin address:

This command returns the skycoin address from your public key.

Important: it will also store the BIP44 path to the memory

Description:

  • Command
CLA INS P1 P2 Lc Le
A1 0x02
  • Input data
Description Length
BIP44 address 20
  • Output data
Description Length
Address 36

4. Sign transaction:

This command gets a raw transaction as an input data and returns a signed transaction (which is ready to be broadcasted throughout the blockchain)

Important: we do not send BIP44 path here so you need to call "Get Skycoin Address" firstly, so the path will be stored and could be used for signing

Description:

  • Command
CLA INS P1 P2 Lc Le
A1 0x10
  • Input data
Description Length
Input num 4
Input* 32
Address index 4
Ouput num 4
Ouput* 37
  • Output data
Description Length
Inner Hash 32
Signed input* 65

According to BIP44 standard, you can use different accounts and address indexes and each of them has another public key, so inputs related to different paths should be signed with different public keys. Also, BIP44 says, that one transaction should have addresses only from on account, so for each input, we need to know only new address index. But Ledger should know the account index, so before signing transactions, you should use getPublicKey or getAddress.

If signing process will be canceled, then you will get 0x6B0 as an error status code

Note: "*" - array of such objects

Check python scripts: generating_txn.py and sign_transaction.py to get more understanding of how transaction should be sended and then how to receive its signature

5. Get app version:

This command returns the version of Ledger app.

Description:

  • Command
CLA INS P1 P2 Lc Le
A1 0x01
  • Output data
Description Length
App version 3

Example of ADPU call

Let's get our Skycoin address from ADPU call using BIP44 path 8000002 / C80000378 / 00000000 / 00000000/ 00000000

CLA INS P1 P2 Lc Data field Le
0x80 0x02 0x00 0x00 0x14 8000002C80000378000000000000000000000000 0x24

So, our request will have a format

80020000148000002C8000037800000000000000000000000024

From Ledger we will get

323536544632453176784a7831355779686567516f55795150424d31386e7264634a429000

And then after transforming bytes to the string we will get

256TF2E1vxJx15WyhegQoUyQPBM18nrdcJB