Ledger Security Bulletin 007

04 October 2019: Monero private key retrieval.


The Monero App for Ledger Nano was found to be vulnerable to a private key retrieval through the use of a malicious Monero Client (desktop application).

Some computational elements are encrypted by the Nano S with a key only known to the Monero application, and sent to the desktop client for later use, due to space limitations on the Nano. During the final step of the signature (MLSAG sign), the client sends back some sensitive encrypted elements which the app uses to compute a Schnorr signature. A malicious client can misuse this by replaying earlier elements of this computation, and induce a variant of a nonce-reuse attack (see for example the PS3 Fail).

This replay of commands is possible because the key derived by the app to encrypt elements is static, and there is no message authentication.

Technical details

The attack can be summarized by looking at what happens during the very last step of a Monero transaction, the MLSAG signature (specifically paragraph 5.0.1). We need to define and name some of the variables that are used beforehand:

$b$: the private spend key $a$: the private view key $spk$: the private symmetric key used by the Nano app to encrypt its outgoing secrets

$spk$ is derived from $a$, $b$ and other elements, but is static, meaning its value never changes for a given wallet seed.

The part of the calculation we are mostly interested in exploiting is this one:

$s_i = \alpha_i - c_i.x_i \mod l$

This computation is performed when the app receives the MLSAG_SIGN command.

For this command, the Nano retrieves $\alpha_i$ and $x_i$ in encrypted form from the client. The decryption key is $spk$, which is only known to the app.

Now, we assume the Monero client is compromised by an attacker, and can arbitrarily deviate from the protocol. For our exploit, it will simply send some values during the above signature computation that are not the expected ones.

First step: normal behaviour

The attacker-controlled client performs a correct first signature with the Nano App and sends the expected $AES_{spk}[\alpha_0]$ and $AES_{spk}[x_0]$ values. He gets:


Note that the modified client also knows $c_0$ because it receives it unencrypted during the MLSAG_HASH command, which takes place right before the SIGN command.

Second step: injection

On a second spend request from the user, the client participates in generating the signature $s_1$, but sends $AES_{spk}[\alpha_0]$ and $AES_{spk}[x_0]$ again. The result is:

Again, it also knows the value of $c_1$.

Ephemeral key extraction

We can retrieve the value of $x_0$ by computing:

Knowing $c_0$ and $c_1$ we have:

Master private key extraction

$x_0$ is only an ephemeral private key, but we can actually retrieve the private spend key from it.

Its value is defined as:

The value $R$ is the transaction public key which was generated by the sender. It is the result of the scalar multiplication of the basepoint $P$ by a secret scalar $r$ known only to the sender.

View key leakage

The view key $a$ can be retrieved by the compromised client because it is usually exported by the users to the client directly.

This means the compromised client can compute $H(a.R || index)$ ($R$ and $index$ are known to the client) by himself, subtract it from $x_0$ and obtain $b$.


This vulnerability allows extracting the user’s Monero private spend key through a malicious Monero client. Being a flaw in the protocol between the Nano application and the Monero desktop client, it could affect both Nano S and Nano X users.


A patch on both the Nano application (commit 5d0658ad) and the Monero client (PR 5958) were issued that prevents the replay of values across transactions. This also protects against possible variants of the attack.

We are also currently working to provide a simpler and more secure protocol in the future, that would also avoid reusing values within the same transaction.


  1. PS3 Epic Fail - 27C3
  2. Ring Confidential Transactions - Monero Research Lab
  3. add hmac on secret during TX - GitHub
  4. For client v0.15 with app 1.4: protocol fix + address display #5958 - GitHub