Skip to content

Integration manual

Sergey Tolmachev edited this page May 22, 2018 · 25 revisions

Introduction

The integration of the application consists of several parts: the development of an application for the device and the protocol of interaction (check this repo) and the integration of the communication library, implementation of the protocol of interaction with the device in the final application.

Ledger Application

The source code for the application is contained in this repository. The build and install instructions is here.

Application protocol

At this moment (the application is in development), there are 2 commands: obtaining a public key (also returns a private key and the test message signature for debugging, in production it is necessary to remove) and the signature of the passed message.

Cryptography protocol

Waves uses ED25519 signature with X25519 keys (Montgomery form), but Ledger (like most of integrated cryptography devices) don't support X25519 keys. But there're the libraries with conversion functions from ED25519 keys to X25519 (Curve25519) crypto_sign_ed25519_pk_to_curve25519(curve25519_pk, ed25519_pk) for public key and crypto_sign_ed25519_sk_to_curve25519(curve25519_sk, ed25519_skpk) for private key:

I use the ED25519 keys and the signature inside the Ledger application, then you need to convert the keys from the device to X25519 format using that function on the client side. Looks like the ED25519 algo from Ledger SDK already installs 'sign' bit into the signature from the public key, so no any additional convertation for signature are needed (unlike the signature of libsodium).

Ledger app protocol

Service statuses:

SW_OK 0x9000
SW_USER_CANCELLED 0x9100
SW_CONDITIONS_NOT_SATISFIED 0x6985
SW_BUFFER_OVERFLOW 0x6990
SW_INCORRECT_P1_P2 0x6A86
SW_INS_NOT_SUPPORTED 0x6D00
SW_CLA_NOT_SUPPORTED  0x6E00
SW_SECURITY_STATUS_NOT_SATISFIED 0x6982

bip32 path

bip32 path bytes are the bytes of 5 int values. Waves bip32 path prefix is 5741564' = 0x80579bfc, so the bip32 path of first used address on the device is 44'/5741564'/0'/0'/1'. In bytes this is 0x8000002c80579bfc800000008000000080000001.

Getting a public key

hex message bytes

80 04 80 00 14 8000002c80579bfc800000008000000080000001

80 [command: 1 byte: 04 hex] [ask user confirmation: 1 byte: 01 hex] [unused: 1 byte: 00 hex] [payload size: 1 byte: 14 hex: 20 bytes] [bip32 path bytes: 20 bytes: ...]

Answer

If request success:

[public key bytes: 32 bytes] [base58 address bytes: 35 bytes] [service status: 2 bytes: should be 9000 = SW_OK]

or

SW_USER_CANCELLED (9100) if user canceled the request

The error code will returns in error cause.

SW_CONDITIONS_NOT_SATISFIED (6985) if some required condition was failed

Example:

=> 80048000148000002c80579bfc800000008000000080000001
<= 3897f7c45e11ef1e2ef9a6d70f378053c6a0e0a7b2f4cbb8d7eecebd585d237e3350444365616b57636b52764b357656654a6e4379315232724531757442634a4d77749000
publicKey (base58): 4ovEU8YpbHTurwzw8CDZaCD7m6LpyMTC4nrJcgDHb4Jh
address: 3PDCeakWckRvK5vVeJnCy1R2rE1utBcJMwt
=> 80048000148000002c80579bfc800000008000000080000001
<= 9100

Sign message

Big message should be chunked by 128 bytes

hex message for first part

80 02 00 00 7b 8000 002c...

80 02 [not last command message: 1 byte: 00 hex] [unused: 1 byte: 00 hex] [payload size byte: 7b hex: 123 bytes] [bip32 path bytes: 20 bytes: ...] [amount decimals: 1 byte] [fee decimals: 1 byte] [tx chunk bytes: 101 bytes]

hex message for next parts

80 02 [not last command message: 1 byte: 00 hex] [unused: 1 byte: 00 hex] [payload size byte: 7b hex: 123 bytes] [tx chunk bytes: 123 bytes]

hex message for last part

80 02 80 00 18 3ed87...

80 02 [last command message: 1 byte: 80 hex] [unused: 1 byte: 00 hex] [payload size byte: 18 hex: 24 bytes] [last 24 tx bytes]

For signing order add byte 252 before first byte of payload data, for some data - 253, for request - 254, for message - 255. This byte will not be signed, it tells the device what type of message it is sent to display in the user interface. Nothing needs to be transferred for transactions, the first byte of the tx body data is the transaction type and it will be signed as expected.

Answer

SW_OK (9000) after each chunk

[signature: 64 bytes] [service status: should be 9000 = SW_OK] after last one

or

SW_USER_CANCELLED (9100) if user canceled the request

The error code will returns in error cause.

SW_CONDITIONS_NOT_SATISFIED (6985) if some required condition was failed SW_BUFFER_OVERFLOW (6990) if max transaction size was reached (650 bytes for now)

Example:

=> 800200007b8000002c80579bfc8000000080000000800000010808043897f7c45e11ef1e2ef9a6d70f378053c6a0e0a7b2f4cbb8d7eecebd585d237e0181121cb46877fbc5c8059919e2a9cf03dcf2fbb112020ec38b7d868b7dd742810000000163692c9e25000000000000000100000000000186a00157da1ca8737e159b76
<= 9000
=> 80028000183ed87810231ea189c0bce5352d630abc0006707269766574
<= 3fadbf76acb7d05289bf6d43fc5a702564415fa3b7ce26bbfcdc1b79ec6827ba9d4758e586f63004c0dd1a9d937034ed48c3d989d0278f9bfe89c3040e87558a9000
signature 2Gqr8cjpGUwxgRPjnjb9FGcKBQr7tvSQmZwo17fV5Krd9LQnScDAQyc9wg43DrBRqN1bdFqTqJKXfj44sq4LG4pH
=> 800200007b8000002c80579bfc8000000080000000800000010808043897f7c45e11ef1e2ef9a6d70f378053c6a0e0a7b2f4cbb8d7eecebd585d237e0181121cb46877fbc5c8059919e2a9cf03dcf2fbb112020ec38b7d868b7dd742810000000163692c9e25000000000000000100000000000186a00157da1ca8737e159b76
<= 9000
=> 80028000183ed87810231ea189c0bce5352d630abc0006707269766574
<= 9100

Communication library

You should pick one for your project language:

There is a test Python implementation of communication with ledger Waves app.

Clone this wiki locally