Skip to content

Latest commit

 

History

History
2546 lines (1822 loc) · 90.8 KB

blue-app-commands.rst

File metadata and controls

2546 lines (1822 loc) · 90.8 KB

\pagebreak

\pagebreak

License

Author: Cédric Mesnil <cslashm@gmail.com>

License:

Copyright 2017-2019 Cédric Mesnil <cslashm@gmail.com>, Ledger SAS

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

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.

\pagebreak

Introduction

We want to enforce key protection, transaction confidentiality and transaction integrity against potential malware on the Host. To achieve that we propose to use a Ledger Nano S/X as a 2nd factor trusted device. Such a device has small amount of memory and is not capable of holding the entire transaction or building the required proofs in RAM. So we need to split the process between the host and the NanoS. This draft note explain how.

To summarize, the signature process is:

. Generate a TX key pair (\mathit{r, R})

. Process Stealth Payment ID

. For each input \mathit{T_{in}} to spend:

  • Compute the input public derivation data \mathfrak{D}_\mathrm{in}
  • Compute the spend key (\mathit{x_{in}, P_{in}}) from \mathit{R_{in}} and \mathit{b}
  • Compute the key image \mathit{I_{in}} of \mathit{x_{in}}

. For each output \mathit{T_{out}} :

  • Compute the output secret derivation data \mathfrak{D}_\mathrm{out}
  • Compute the output public key \mathit{P_{out}}

. For each output \mathit{T_{out}} :

  • compute the range proof
  • blind the amount
  • compute the view tag

. Compute the final confidential ring signature

. Return TX

\pagebreak

Notation

Elliptic curve points, such as pubic keys, are written in italic upper case, and scalars, such as private keys, are written in italic lower case:

  • \mathit{spk} : protection key
  • (\mathit{r, R}) : transaction key pair
  • (\mathit{a, A}) (\mathit{b, B}) : sender main view/spend key pair
  • (\mathit{c, C}) (\mathit{d, D}) : sender sub view/spend key pair
  • \mathit{A_{out}} \mathit{B_{out}} : receiver main view/spend public keys
  • \mathit{C_{out}} \mathit{D_{out}} : receiver sub view/spend public key
  • \mathit{H} : 2nd group generator, such \mathit{H = h.G} and \mathit{h} is unknown
  • \mathcal{\mathrm{amount}} : amount to send/spend
  • \mathcal{\mathrm{mask}} : secret amount mask factor
  • \mathit{C_v} : commitment to a with v such \mathit{C_v = k.G + v.H}
  • \mathit{\alpha_{in}} : secret co-signing key for ith input
  • \mathit{x_{in}} : secret signing key for ith input
  • \mathit{P_{in}} : public key of ith input
  • \mathit{P_{out}} : public key of ith output
  • \mathfrak{D}_\mathrm{out} \mathfrak{D}_\mathrm{in} : first level derivation data

Hash and encryption function:

  • \mathtt{AES} : [k](m) AES encryption of m with key k
  • \mathtt{AES^{-1}} : [k](c) AES decryption of c with key k

Others:

  • \mathit{PayID} : Stealth payment ID
  • \mathtt{ENC\_PAYMENT\_ID\_TAIL} : 0x82

\pagebreak

Commands overview

Introduction

Hereafter are the code integration and application specification.

The commands are divided in three sets:

  • Provisioning
  • Low level crypto command
  • High level transaction command

The low level set is a direct mapping of some crypto Monero function. For such command the Monero function will be referenced.

The high level set encompasses functions that handle the confidential/sensitive part of full transaction

Common command format

All command follow the generic ISO7816 command format, with the following meaning:

byte length description
CLA 01 Protocol version
INS 01 Command
P1 01 Sub command
P2 01 Command/Sub command counter
LC 01 byte length of data
data

01

var

options

additional data

When a command/sub-command can be sent repeatedly, the counter must be increased by one at each command. The flag last sub command indicator must be set to indicate another command will be sent.

Common option encoding

x--------

1--------

0--------

Last sub command indicator

More identical subcommand forthcoming

Last sub command

\pagebreak

Provisioning And Key Management

Overview

There is no provisioning in a standard setup. Both key pairs (\mathit{a, A}) and (\mathit{b, B}) should be derived under BIP44 path.

The general BIP44 path is :

/ purpose' / coin_type' / account' / change / address_index

and is defined as follow for any Monero main address:

`` /44'/128'/account'/0/0``

so in hexa:

/0x8000002C/0x80000080/0x8......./0x00000000/0x00000000

The address_index is set to 0 for the main address and will be used as sub-address index according to kenshi84 fork.

In case an already existing key needs to be transferred, an optional dedicated command may be provided. As there is no secure messaging for now, this transfer shall be done from a trusted Host. Moreover, as provisioning is not handled by Monero client, a separate tool must be provided.

Commands

Reset

Description

Restart the application and check client/application versions compatibility.

Command

CLA INS P1 P2 LC
03 02 00 00 ll

Command data

Length Value
01 00
var string version, without trailing null byte

Response data

Length Value
01 Application major version
01 Application minor version
01 Application micro version

Put keys

Description

Put sender key pairs.

This command allows to set specific key on the device and should only be used for testing purpose.

The application shall:

check \mathit{A} == \mathit{a}.|G|
check \mathit{B} == \mathit{b}.|G|
store \mathit{a}, \mathit{A}, \mathit{b}, \mathit{B}

Command

CLA INS P1 P2 LC
03 22 00 00 e0

Command data

Length Value
01 00
20 \mathit{a}
20 \mathit{A}
20 \mathit{b}
20 \mathit{B}
5f Base58 encoded public key

Response data

Length Value
   

Get Public Key

Description

Retrieves public base58 encoded public key.

Command

CLA INS P1 P2 LC
03 20 01 00 01

Command data

Length Value
01 00

Response data

Length Value
20 "A" view public key
20 "B" view spend key
5f Base58 encoded public key

Get Private View Keys

Description

Retrieves the private view key in order to accelerate the blockchain scan.

The device should ask the user to accept or reject this export. If rejected the client will use the device for scanning the blockchain.

Command

CLA INS P1 P2 LC
03 20 02 00 01

Command data

Length Value
01 00

Response data

Length Value
20 "a" secret view key

Display Address

Monero

Description

Display requested main address, sub address or integrated address.

compute \mathit{x} = |dec|[|spk|](\widetilde{\mathit{x}})

if payment ID is provided:

compute \mathit{xP} = \mathit{x}.|G|
check \mathit{xP} == \mathit{P}

Command

CLA INS P1 P2 LC
03 21 xx 00 11

if P1 is '00' display non-integrated address.

if P1 is '01' display integrated address.

Any other value will be rejected.

Command data

Length Value
01 00
08 index (Major.minor) \mathit{index}
08 Payment ID, (or '0000000000000000')

Response data

Length Value
   

\pagebreak

Low level crypto commands

Overview

This section describe lowlevel commands that can be used in a transaction or not.

Commands

Verify Keys

Monero

device_default::verify_keys.

Description

Verify that the provided private key and public key match.

compute \mathit{x} = |dec|[|spk|](\widetilde{\mathit{x}})
compute \mathit{xP} = \mathit{x}.|G|
check \mathit{xP} == \mathit{P}

Command

CLA INS P1 P2 LC
03 26 xx 00 41

if P1 is '00' the provided public key will be used.

if P1 is '01' the public view is key will be used and the provided private key will be 'ignored'

if P1 is '02' the public spend is key will be used and the provided private key will be 'ignored'

Any other value will be rejected.

Command data

Length Value
01 00
20 secret key \widetilde{\mathit{x}}
20 public key or '00'*32 \mathit{P}

Response data

Length Value
   

Get ChaCha8 PreKey

Monero

Description

compute \mathit{s} = |H|(|a| | \mathit{B} | \mathtt{ENC\_PAYMENT\_ID\_TAIL})

return the full internal state (200 bytes) of Keccak.

Command

CLA INS P1 P2 LC
03 24 00 00 00

Command data

Length Value
   

Response data

Length Value
C8 ChaCha8 prekey

Generate Key Derivation

Monero

crypto::generate_key_derivation.

Description

Compute the secret key derivation and return it encrypted.

compute \mathit{x} = |dec|[|spk|](\widetilde{\mathit{x}})
compute \mathfrak{D}_\mathrm{in} = |keyDrv|(|x|,|P|)
compute \widetilde{\mathfrak{D}_\mathrm{in}} = |enc|[|spk|](\mathfrak{D}_\mathrm{in})

return \widetilde{\mathfrak{D}_\mathrm{in}}.

Command

CLA INS P1 P2 LC
03 32 00 00 41 or 61

Command data

Length Value
01 00
20 public key \mathit{P}
20 secret key \widetilde{\mathit{x}}
20 ephemeral hmac (optional, only during active transaction)

Response data

Length Value
20 encrypted key derivation \widetilde{\mathfrak{D}_\mathrm{in}}
20 ephemeral hmac (optional, only during active transaction)

Derivation To Scalar

Monero

crypto::derivation_to_scalar.

Description

Transform a secret derivation data to a secret scalar according to its index.

compute \mathfrak{D}_\mathrm{in} = |dec|[|spk|](\widetilde{\mathfrak{D}_\mathrm{in}})
compute \mathit{s} = |Hps|(|Drv|, \mathit{index})
compute \widetilde{\mathit{s}} = |enc|[|spk|](\mathit{s})

return \widetilde{\mathit{s}}.

Command

CLA INS P1 P2 LC
03 34 00 00 25 or 45

Command data

Length Value
01 00
20 encrypted key derivation \widetilde{\mathfrak{D}_\mathrm{in}}
20 ephemeral hmac (optional, only during active transaction)
04 index

Response data

Length Value
20 encrypted scalar \widetilde{\mathit{s}}
20 ephemeral hmac (optional, only during active transaction)

Derive Public Key

Monero

crypto::derive_public_key.

Description

Compute a new public key from some secret derivation data, a parent public key and its index.

compute \widetilde{\mathfrak{D}_\mathrm{in}} = |dec|[|spk|](\widetilde{\mathfrak{D}_\mathrm{in}})

derivation_to_scalar:

compute \mathit{s} = |Hps|(|Drv|, \mathit{index})

then:

compute \mathit{P}' = |P|+|s|.|G|

return \mathit{P}'.

Command

CLA INS P1 P2 LC
03 36 00 00 25 or 45

Command data

Length Value
01 00
20 encrypted key derivation \widetilde{\mathfrak{D}_\mathrm{in}}
20 ephemeral hmac (optional, only during active transaction)
04 index
20 public key \mathit{P}

Response data

Length Value
20 public key \mathit{P}'

Derive Secret Key

Monero

crypto::derive_secret_key.

Description

Compute a new secret key from some secret derivation data, a parent secret key and its index.

compute \widetilde{\mathfrak{D}_\mathrm{in}} = |dec|[|spk|](\widetilde{\mathfrak{D}_\mathrm{in}})
compute \mathit{x} = |dec|[|spk|](\widetilde{\mathit{x}})

derivation_to_scalar:

compute \mathit{s} = |Hps|(|Drv|, \mathit{index})

then:

compute \mathit{x}' = (|x|+|s|) % \mathtt{\#n}
compute \widetilde{\mathit{x}}' = |enc|[|spk|](\mathit{x})

return \widetilde{\mathit{x}}.

Command

CLA INS P1 P2 LC
03 38 00 00 65 or 85

Command data

Length Value
01 00
20 encrypted key derivation \widetilde{\mathfrak{D}_\mathrm{in}}
20 ephemeral hmac (optional, only during active transaction)
04 index
20 encrypted secret key \widetilde{\mathit{x}}
20 ephemeral hmac (optional, only during active transaction)

Response data

Length Value
20 encrypted derived secret key \widetilde{\mathit{x}}'
20 ephemeral hmac (optional, only during active transaction)

Derive Subaddress Public Key

Monero

crypto_ops::derive_subaddress_public_key.

Description

compute \widetilde{\mathfrak{D}_\mathrm{in}} = |dec|[|spk|](\widetilde{\mathfrak{D}_\mathrm{in}})
compute \mathit{s} = |Hps|(|Drv|, \mathit{index})
compute \mathit{P}' = \mathit{P} - \mathit{s}.|G|

return \mathit{P}'

Command

CLA INS P1 P2 LC
03 46 00 00 45 or 65

Command data

Length Value
01 00
20 public key \mathit{P}
20 encrypted derivation key \widetilde{\mathfrak{D}_\mathrm{in}}
20 ephemeral hmac (optional, only during active transaction)
04 index \mathit{index}

Response data

Length Value
20 sub public key \mathit{P}'

Get Subaddress Spend Public Key

Monero

device_default::get_subaddress_spend_public_key.

Description

get_subaddress_secret_key:

compute \mathit{s} = |H|("SubAddr" \| |a| | \mathit{index} )
compute \mathit{x} = \mathit{s} % \mathtt{\#n}

then:

compute \mathit{D = \mathit{B} + \mathit{x}.|G|

return \mathit{D

Command

CLA INS P1 P2 LC
03 4A 00 00 09

Command data

Length Value
01 00
08 index (Major.minor) \mathit{index}

Response data

Length Value
20 sub spend public key \mathit{D

Get Subaddress Secret Key

Monero

get_subaddress_secret_key

Description

compute \mathit{x} = |dec|[|spk|](\widetilde{\mathit{x}})
compute \mathit{s} = |H|("SubAddr" \| |x| | \mathit{index} )
compute \mathit{d} = \mathit{s} % \mathtt{\#n}
compute \widetilde{\mathit{d_{i}}} = |dec|[|spk|](\mathit{d})

return \widetilde{\mathit{d_{i}}}

Command

CLA INS P1 P2 LC
03 4C 00 00 39 or 59

Command data

Length Value
01 00
20 secret key \widetilde{\mathit{x}}
20 ephemeral hmac (optional, only during active transaction)
08 index (Major.minor) \mathit{index}

Response data

Length Value
20 sub secret key \widetilde{\mathit{d_{i}}}
20 ephemeral hmac (optional, only during active transaction)

Get Subaddress

Monero

device_default::get_subaddress_secret_key.

Description

compute \mathit{s} = |H|("SubAddr" \| |a| | \mathit{index} )
compute \mathit{x} = \mathit{s} % \mathtt{\#n}

then:

compute \mathit{D = \mathit{B} + \mathit{x}.|G|
compute \mathit{C} = \mathit{A}.|D|

return \mathit{C}, \mathit{D

Command

CLA INS P1 P2 LC
03 48 00 00 09

Command data

Length Value
01 00
08 index (Major.minor) \mathit{index}

Response data

Generate Key Image

Monero

crypto::generate_key_image.

Description

Compute the key image of a key pair.

compute \mathit{x} = |dec|[|spk|](\widetilde{\mathit{x}})
compute \mathit{P}' = |Hp|(|P|)
compute \mathit{Img(P)} = \mathit{x}.|P|'

return \mathit{Img(P)}.

Command

CLA INS P1 P2 LC
03 3A 00 00 41 or 61

Command data

Length Value
01 00
20 public key \mathit{P}
20 secret key \widetilde{\mathit{x}}
20 ephemeral hmac (optional, only during active transaction)

Response data

Length Value
20 key image \mathit{Img(P)}

Derive View Tag

Monero

crypto::derive_view_tag.

Description

Derive the view tag of an output.

compute \mathfrak{D}_\mathrm{in} = |dec|[|spk|](\widetilde{\mathfrak{D}_\mathrm{in}})
compute \mathit{view\_tag\_full} = |Hs|("view_tag" \|, |Drv|, \mathit{index})
compute \mathit{view\_tag} = |vtf|[0:1]

return \mathit{view\_tag}.

Command

CLA INS P1 P2 LC
03 3B 00 00 25 or 45

Command data

Length Value
01 00
20 encrypted key derivation \widetilde{\mathfrak{D}_\mathrm{in}}
20 ephemeral hmac (optional, only during active transaction)
04 index

Response data

Length Value
01 view tag \mathit{view\_tag}

Generate Keypair

Monero

crypto::generate_keys.

Description

Generate a new keypair and return it. The secret key is returned encrypted.

generate \mathit{x}
compute \mathit{xP} = \mathit{x}.|P|
compute \widetilde{\mathit{x}} = |enc|[|spk|](\mathit{x})

return \mathit{P}, \widetilde{\mathit{x}}.

Command

CLA INS P1 P2 LC
03 40 00 00 01

Command data

Length Value
01 00

Response data

Length Value
20 public key \mathit{P}
20 encrypted secret key \widetilde{\mathit{x}}
20 ephemeral hmac (optional, only during active transaction)

Secret Key To Public Key

Monero

crypto::secret_key_to_public_key.

Description

Compute a public key from secret a secret key.

compute \mathit{x} = |dec|[|spk|](\widetilde{\mathit{x}})
compute \mathit{P} = \mathit{x}.|G|

return \mathit{P}.

Command

CLA INS P1 P2 LC
03 30 00 00 21 or 41

Command data

Length Value
01 00
20 encrypted secret key \widetilde{\mathit{x}}
20 ephemeral hmac (optional, only during active transaction)

Response data

Length Value
20 public key \mathit{P}

Secret Add

Monero

sc_add

Description

compute \mathit{x_1} = |dec|[|spk|](\widetilde{\mathit{x_1}})
compute \mathit{x_2} = |dec|[|spk|](\widetilde{\mathit{x_2}})
compute \mathit{x} = \mathit{x_1} + \mathit{x_2}
compute \widetilde{\mathit{x}} = |enc|[|spk|](\mathit{x})

return \widetilde{\mathit{x}}.

Command

CLA INS P1 P2 LC
03 3C 00 00 41 or 61

Command data

Length Value
01 00
20 secret key \widetilde{\mathit{x_1}}
20 ephemeral hmac (optional, only during active transaction)
20 secret key \widetilde{\mathit{x_2}}
20 ephemeral hmac (optional, only during active transaction)

Response data

Length Value
20 secret key \widetilde{\mathit{x}}
20 ephemeral hmac (optional, only during active transaction)

Secret Scalar Mult Key

Monero

rct::scalarmultKey.

Description

Multiply a secret scalar with a public key.

compute \mathit{x} = |dec|[|spk|](\widetilde{\mathit{x}})
compute \mathit{xP} = \mathit{x}.|P|

return \mathit{xP}

Command

CLA INS P1 P2 LC
03 42 00 00 41 or 61

Command data

Length Value
01 00
20 public key \mathit{P}
20 secret key \widetilde{\mathit{x}}
20 ephemeral hmac (optional, only during active transaction)

Response data

Length Value
20 new public key \mathit{xP}

Secret Scalar Mult Base

Monero

rct::scalarmultBase.

Description

Multiply a secret scalar with the publis base point \mathit{G}.

compute \mathit{x} = |dec|[|spk|](\widetilde{\mathit{x}})
compute \mathit{xG} = \mathit{x}.|G|

return \mathit{xG}

Command

CLA INS P1 P2 LC
03 44 00 00 21 or 41

Command data

Length Value
01 00
20 secret key \widetilde{\mathit{x}}
20 ephemeral hmac (optional, only during active transaction)

Response data

Length Value
00  
20 new public key \mathit{xG}

Stealth

Monero

Description

Encrypt payment ID

compute \mathit{x} = |dec|[|spk|](\widetilde{\mathit{x}})
compute \mathfrak{D}_\mathrm{in} = |keyDrv|(|P|, \mathit{x})
compute \mathit{s} = |Hs|( |DRV| | \mathtt{ENC\_PAYMENT\_ID\_TAIL})
compute \mathit{PayID} = |ePayID|^|s|

return \mathit{PayID}

Command

CLA INS P1 P2 LC
03 76 00 00 61 or 81

Command data

Length Value
01 00
20 public key \mathit{P}
20 encryped secret key \widetilde{\mathit{x}}
20 ephemeral hmac (optional, only during active transaction)
20 encryped payment ID \widetilde{\mathit{PayID}}

Response data

Unblind

Monero

Description

Unblind amount and his mask.

First:

compute \mathcal{AK}_\mathrm{amount} = |dec|[|spk|](\widetilde{\mathcal{AK}_\mathrm{amount}})

If blind V1:

compute \mathit{s} = |Hs|(|AKout|)
compute \widetilde{\mathcal{\mathrm{mask}}} = \mathcal{\mathrm{mask}}-\mathit{s}
compute \mathit{s} = |Hs|(|a|)
compute \widetilde{\mathcal{\mathrm{amount}}} = \mathcal{\mathrm{amount}}-\mathit{s}
If blind V2:
compute \mathcal{\mathrm{mask}} = |Hs|("commitment_mask" \| |Akout|) % \mathtt{\#n}
compute \mathit{s} = |Hs|("amount" \| |Akout|)
compute |v|[0:7] = |ev|[0:7]^|s|[0:7]

return \widetilde{\mathcal{\mathrm{mask}}},|ev|

Command

CLA INS P1 P2 LC
03 7A 00 00 61 or 81

specific options

-------xx

-------10

-------00

Commitment scheme version

Blind V2

Blind V1

Command data

Length Value
01 xx
20 encryped blinding factor \mathcal{AK}_\mathrm{amount}
20 ephemeral hmac (optional, only during active transaction)
20 blinded mask \widetilde{\mathcal{\mathrm{mask}}}
20 blinded amount \widetilde{\mathcal{\mathrm{amount}}}

Response data

Length Value
20 mask \widetilde{\mathcal{\mathrm{mask}}}
20 amount \widetilde{\mathcal{\mathrm{amount}}}

High Level Transaction command

Transaction process overview

The transaction is mainly generated in construct_tx_and_get_tx_key (or construct_tx) and construct_tx_with_tx_key functions.

First, a new transaction keypair (\mathit{r, R}) is generated.

Then, the stealth payment id is processed if any.

Then, for each input transaction to spend, the input key image is retrieved.

Then, for each output transaction, the epehemeral destination key and the blinding key amount \mathcal{AK}_\mathrm{amount} are computed.

Once \mathit{T_{in}} and \mathit{T_{out}} keys are set up, the genRCT/genRctSimple function is called.

First a commitment \mathit{C_v} to each \mathcal{\mathrm{amount}} amount and its associated range proof are computed to ensure the \mathcal{\mathrm{amount}} amount confidentiality. The commitment and its range proof do not imply any secret and generate \mathit{C_v}, \mathcal{\mathrm{mask}} such \mathit{C_v = k.G + v.H}.

Then \mathcal{\mathrm{mask}} and \mathcal{\mathrm{amount}} are blinded by using the \mathcal{AK}_\mathrm{amount} which is only known in an encrypted form by the host.

After all commitments have been setup, the confidential ring signature happens. This signature is performed by calling proveRctMG which then calls MLSAG_Gen.

At this point the amounts and destination keys must be validated on the NanoS. This information is embedded in the message to sign by calling get_pre_mlsag_hash, prior to calling ProveRctMG. So the get_pre_mlsag_hash function will have to be modified to serialize the rv transaction to NanoS which will validate the tuple <amount,dest> and compute the prehash. The prehash will be kept inside NanoS to ensure its integrity. Any further access to the prehash will be delegated.

Once the prehash is computed, the proveRctMG is called. This function only builds some matrix and vectors to prepare the signature which is performed by the final call MLSAG_Gen.

During this last step some ephemeral key pairs are generated : \mathit{\alpha_{in}}, \mathit{\alpha_{in}.G}. All \mathit{\alpha_{in}} must be kept secret to protect the \mathit{x_{in}} keys. Moreover we must avoid signing arbitrary values during the final loop.

In order to achieve this validation, we need to approve the original destination address |Aout||Bout|, which is not recoverable from P out . Here the only solution is to pass the original destination with the \mathcal{\mathrm{mask}}, \mathcal{\mathrm{amount}}, \mathcal{AK}_\mathrm{amount}.

Unblind \mathcal{\mathrm{mask}} and \mathcal{\mathrm{amount}} and then verify the commitment \mathit{C_v = k.G + v.H}. If \mathit{C_v} is verified and user validate \mathit{A_{out}},|Bout| and \mathcal{\mathrm{amount}}, continue.

\pagebreak

Transaction State Machine

During a transaction the following state machine is enforced:

OPEN_TX{1} -----------------------------------------------------
                                                               |
----------------------------------------------------------------
|
----> STEALTH{1} -----------------------------------------------
                                                               |
----------------------------------------------------------------
|
 ----> GEN_TXOUT_KEYS{*} ---------------------------------------
                                                               |
------------------------------------------------------------ ---
|
----> PREFIX_HASH{1} ---> PREFIX_HASH{*} ---> PREFIX_HASH{1} ---
        (ph_init)          (ph_update)        (ph_finalize)    |
                                                               |
----------------------------------------------------------------
|
----> GEN_COMMITMENT_MASK{*} -----------------------------------
        only for real TX                                       |
                                                               |
----------------------------------------------------------------
|
----> BLIND ----------------------------------------------------
                                                               |
----------------------------------------------------------------
|
----> VALIDATE{1} ---> VALIDATE{*} --- VALIDATE{*} <------------
  mlsag_ph_init     mlsag__update    mlsag__finalize           |
                                                               |
---------------------------------------------------------------
|
----> MLSAG{1} ------> MLSAG{*} ------> MLSAG{1} ---------------
  --> mlsag_prepare    mlsag_hash       mlsag_sign --          |
  |                                                 |          |
  ---------------------------------------------------          |
                                                               |
----------------------------------------------------------------
|
----> CLOSE_TX

Note this state machine assume the multi-signature is not supported. For multi-signature the INS_MLSAG/mlsag_prepare and INS_MLSAG/mlsag_sign may be received several time.

Transaction Commands

Open TX

Description

Open a new transaction. Once open the device impose a certain order in subsequent commands:

  • OpenTX
  • Stealth
  • Get TX output keys
  • Blind *
  • Initialize MLSAG-prehash
  • Update MLSAG-prehash *
  • Finalize MLSAG-prehash
  • MLSAG prepare
  • MLSAG hash *
  • MLSAG sign
  • CloseTX

During this sequence low level API remains available, but no other transaction can be started until the current one is finished or aborted.

Initialize \mathcal{H}_\mathrm{outkeys}
compute initial transaction key pair (\mathit{r, R})

return (\mathit{r, R})

Command

CLA INS P1 P2 LC
03 70 01 cnt 05

Command data

Length Value
01 options
04 account identifier (ignored, RFU)

Response data

Length Value
20 public transaction key \mathit{R}
20 encrypted private transaction key \widetilde{\mathit{r}}
20 ephemeral hmac
20 ephemeral hmac of view key
20 ephemeral hmac of spend key

Set Signature Mode

Description

Set the signature to 'fake' or 'real'. In fake mode a random key is used to signed the transaction and no user confirmation is requested.

Command

CLA INS P1 P2 LC
03 72 01 00 02

Command data

Response data

Length Value
   

Hash Prefix

Hash prefix init

Description

Init prefix hash and ask user to validate time lock

Command

CLA INS P1 P2 LC
03 7D 01 cnt 05

Command data

Length Value
01 options
varint TX version
varint TX timelock

Response data

Length Value
   
Hash prefix update

Description

Update prefix hash with raw data. Options fields tells if there is more data to come or not.

Command

CLA INS P1 P2 LC
03 7D 02 cnt 05

Command data

Length Value
01 options
var raw data to hash

Response data

Length Value
   

Generate Commitment Mask

Description

compute \mathit{s} = |Hs|("commitment_mask" \| |AKout|)

Return \mathit{s}

Command

CLA INS P1 P2 LC
03 77 00 00 21

Command data

Length Value
01 00
20 encryped blinding factor \mathcal{AK}_\mathrm{amount}
20 ephemeral hmac

Response data

Length Value
20 commitment mask \mathit{s}

Blind

Monero

Description

Blind amount and his mask.

First:

compute \mathcal{AK}_\mathrm{amount} = |dec|[|spk|](\widetilde{\mathcal{AK}_\mathrm{amount}})

If blind V1:

compute \mathit{s} = |Hs|(|AKout|)
compute \widetilde{\mathcal{\mathrm{mask}}} = |k|+|s|
compute \mathit{s} = |Hs|(|a|)
compute \widetilde{\mathcal{\mathrm{amount}}} = |v|+|s|

If blind V2:

set \widetilde{\mathcal{\mathrm{mask}}} to 32 zero bytes
compute \mathit{s} = |Hs|("amount" \| |AKout|)
compute \widetilde{\mathcal{\mathrm{amount}}} = |v|[0:7]^|s|[0:7]

return \widetilde{\mathcal{\mathrm{mask}}},|ev|

Command

CLA INS P1 P2 LC
03 78 00 00 81

specific options

-------xx

-------10

-------00

Commitment scheme version

Blind V2

Blind V1

Command data

Length Value
01 xx
20 encryped blinding factor \mathcal{AK}_\mathrm{amount}
20 ephemeral hmac
20 mask \mathcal{\mathrm{mask}}
20 amount \mathcal{\mathrm{amount}}

Response data

Length Value
20 blinded mask \widetilde{\mathcal{\mathrm{mask}}}
20 blinded amount \widetilde{\mathcal{\mathrm{amount}}}

Generate TX output keys

Description

Compute additional key \mathit{P} if needed, amount key blinding and ephemeral destination key.

if \mathit{need\_additional\_key} :
if \mathit{is\_subaddress} :
compute \mathit{R}' = \mathit{additional\_key}.|Bout|
else
compute \mathit{R}' = \mathit{additional\_key}.|G|

if \mathit{is\_change\_address} :
compute \mathfrak{D}_\mathrm{in} = |keyDrv|(|a|,|R|)
else
if \mathit{need\_additional\_key} and \mathit{is\_subaddress}:
compute \mathfrak{D}_\mathrm{in} = |keyDrv|(|ak|,|Aout|)|
else:
compute \mathfrak{D}_\mathrm{in} = |keyDrv|(|r|,|Aout|)

compute \mathcal{AK}_\mathrm{amount} = |Hps|(|Drv|,|idx|)
compute \widetilde{\mathcal{AK}_\mathrm{amount}} = |enc|[|spk|](\mathcal{AK}_\mathrm{amount})

compute \mathit{s} = |Hps|(|Drv|,|idx|)
compute \mathit{P} = |Bout|+|s|.|G|

update \mathcal{H}_\mathrm{outkeys} : |Hupd|(|Aout|,|Bout|,is_change,|AKout|)
if option 'last' is set:
finalize \mathcal{H}_\mathrm{outkeys}

The application returns

Command

CLA INS P1 P2 LC
03 7B 01 cnt EC

Command data

Response data

Validate and Pre Hash

Initialize MLSAG-prehash

Description

During the first step, the application updates the \mathcal{H} with the transaction header:

if cnt == 1

Finalize \mathcal{H}_\mathrm{outkeys}
Initialize \mathcal{H}_\mathrm{outkeys}'
Initialize \mathcal{H}_\mathrm{commitment}
Initialize \mathcal{H}
update \mathcal{H} : |Hupd|(txnFee)
request user to validate txnFee

else

update \mathcal{H} : |Hupd|(pseudoOut)

Command

Command data

if cnt==1 :
Length Value
01 options
01 type
varint txnFee

if cnt>1 :

Length Value
01 options
20 pseudoOut
Update MLSAG-prehash

Description

On the second step the application receives amount and destination and check values. It also re-compute the \mathcal{H}_\mathrm{outkeys} value to ensure consistency with steps 3 and 4. So for each command received, do:

compute \mathcal{AK}_\mathrm{amount} = |dec|[|spk|](\widetilde{\mathcal{AK}_\mathrm{amount}})

update \mathcal{H}_\mathrm{outkeys}'' : |Hupd|(|Aout| | \mathit{B_{out}} | is_change | \mathcal{AK}_\mathrm{amount})

if blind v1
compute \mathcal{\mathrm{mask}} = \widetilde{\mathcal{\mathrm{mask}}} - |Hs|(|Akout|)
compute \mathcal{\mathrm{amount}} = \widetilde{\mathcal{\mathrm{amount}}} - |Hs|(|Hs|(|Akout|))

if blind v2
compute \mathcal{\mathrm{mask}} = |Hs|("commitment_mask"||Akout|)) % \mathtt{\#n}
compute \mathit{s} = |Hs|("amount"|||Akout|)
compute |v|[0:7] = |ev|[0:7] ^ |s|[0:7]

check \mathit{C_v} == \mathcal{\mathrm{mask}}.|G| + \mathcal{\mathrm{amount}}.|H| |
update \mathcal{H}_\mathrm{commitment} : |Hupd|(|Ct|)

if last command:
finalize \mathcal{H}_\mathrm{outkeys}'
check \mathcal{H}_\mathrm{outkeys}' == \mathcal{H}_\mathrm{outkeys}
finalize \mathcal{H}_\mathrm{commitment}


update \mathcal{H} : |Hupd|(ecdhInfo)

ask user validation of \mathit{A_{out}}, \mathit{B_{out}}, \mathcal{\mathrm{amount}}

Command

CLA INS P1 P2 LC
03 7C 02 cnt E3

Command data

Length Value
01 options
01 1 if sub-address, 0 else
01 1 if change-address, 0 else
20 Real destination public view key \mathit{A_{out}}
20 Real destination public spend key \mathit{B_{out}}
20 encrypted amount key blinding \widetilde{\mathcal{AK}_\mathrm{amount}}
20 ephemeral hmac
20 \mathit{C_v} of \mathcal{\mathrm{amount}},|k|
40

one serialized ecdhInfo :

{
bytes[32] mask (\widetilde{\mathcal{\mathrm{mask}}})
bytes[32] amount (\widetilde{\mathcal{\mathrm{amount}}})
}

specific options

-------xx

-------10

-------00

Mask scheme version

Blind V2

Blind V1

Note: Whatever the mask scheme is, \mathcal{\mathrm{amount}} is always transmitted as 32 bytes.

Finalize MLSAG-prehash

Description

Finally the application receives the last part of data:

if cnt == 1
Initialize \mathcal{H}_\mathrm{commitment}'

if last command:
finalize \mathcal{H}_\mathrm{commitment}'
check \mathcal{H}_\mathrm{commitment} == \mathcal{H}_\mathrm{commitment}'
\mathit{s} = finalize \mathcal{H}
compute \mathcal{H} = \mathtt{HashToScalar} (message | \mathit{s} | proof)

else
update \mathcal{H}_\mathrm{commitment}': |Hupd|(|Ct|)
update \mathcal{H}: |Hupd|(|Ct|)

Keep \mathcal{H}

Command

CLA INS P1 P2 LC
03 7C 03 cnt 21

Command data

not last:

Length Value
01 options
20

one serialized commitment :

{
bytes[32] mask (\mathit{C_v})
}

last:

Length Value
01 options
20 message (rctSig.message)
20 proof (proof range hash)

Response data

Length Value
   

MLSAG

MLSAG prepare

Description

Generate the matrix ring parameters:

generate \mathit{\alpha_{in}} ,
compute \mathit{\alpha_{in}.G}
if real key:
check the order of \mathit{H_i}
compute \mathit{\alpha_{in}.H_i}
compute \widetilde{\mathit{\alpha_{in}}} = |enc|[|spk|](\mathit{\alpha_{in}})
if not option_clear_xin:
compute \mathit{x_{in}} = |dec|[|spk|](\widetilde{\mathit{x_{in}}})
compute \mathit{II_{in}} = \mathit{x_{in}}.|Hi|



return \widetilde{\mathit{\alpha_{in}}} , \mathit{\alpha_{in}.G} [\mathit{\alpha_{in}.H_i}, \mathit{II_{in}}]

Command

CLA INS P1 P2 LC
03 7E 01 cnt 61

specific options

------x--

------1--

------0--

Mask scheme version

unencrypted \mathit{x_{in}}

encryted \widetilde{\mathit{x_{in}}}

Command data

for real key:

Length Value
01 options
20 point
20 secret spend key \widetilde{\mathit{x_{in}}}
20 ephemeral hmac

for random ring key

Length Value
01 options

Response data

for real key:

Length Value
20 encrypted \mathit{\alpha_{in}} : \widetilde{\mathit{\alpha_{in}}}
20 ephemeral hmac
20 \mathit{\alpha_{in}.G}
20 \mathit{II_{in}}
20 \mathit{\alpha_{in}.H_i}

for random ring key

Length Value
20 encrypted \mathit{\alpha_{in}} : \widetilde{\mathit{\alpha_{in}}}
20 ephemeral hmac
20 \mathit{\alpha_{in}.G}
MLSAG hash

Description

Compute the last matrix ring parameter:

if cnt == 1:
replace the inputs by the previously computed MLSAG-prehash
initialize \mathcal{H}

update \mathcal{H}: |Hs|(inputs)

if last command:
c = finalize \mathcal{H} % \mathtt{\#n}

Command

CLA INS P1 P2 LC
03 7E 02 cnt 21

Command data

Length Value
01 options
20 inputs

Response data

if last command

Length Value
20 c

else

Length Value
   
MLSAG sign

Description

Finally compute all signatures:

compute \mathit{\alpha_{in}} = |dec|[|spk|](\widetilde{\mathit{\alpha_{in}}})
compute \mathit{x_{in}} = |dec|[|spk|](\widetilde{\mathit{x_{in}}})
compute \mathit{ss} = (\mathit{\alpha_{in}} - \mathit{c} * \mathit{x_{in}} ) % \mathit{l}

return \mathit{ss}

Command

CLA INS P1 P2 LC
03 7E 03 cnt 81

Command data

Length Value
01 options
20 \widetilde{\mathit{x_{in}}}
20 ephemeral hmac
20 \widetilde{\mathit{\alpha_{in}}}
20 ephemeral hmac

Response data

Length Value
20 signature \mathit{ss}

Conclusion

Let's Go

Annexes

References

Helper functions

|keyDrv| (\mathtt{KeyDerivation})

input : r , P
output: \mathfrak{D}
Monero: generate_key_derivation

\mathfrak{D} = r.P
\mathfrak{D} = 8.\mathfrak{D}

|Hs| (\mathtt{HashToScalar})

input: raw
output: s


\mathit{s} = |H|(raw)

|Hps| (\mathtt{HashPointToScalar})

input: D, idx
output: s

data = point2bytes(D) | varint(idx)

|Hp| (\mathtt{HashToPoint})

input: P
output: Q

data = point2bytes(P)
Q = ge\_from\_fe(s)

DeriveAES

input: R,a,b
output: spk

seed = sha256(R|a|b|R)
data = sha256(seed)
spk = lower16(data)