DocumentationDevice AppExplanationCryptography general concepts

Cryptography — why the rules exist

The Ledger security model gives each application a controlled, auditable window into the device’s cryptographic capabilities. The rules in Cryptography requirements are not arbitrary — each one exists to close a specific class of attack. This page explains the reasoning behind them.

The threat model

A device app operates in an environment where the host computer may be compromised. The attacker controls the data sent to the device, can intercept responses, and can observe timing. The Secure Element isolates the private key material, but only if the application itself does not inadvertently expose it.

The rules below address the most common ways applications have done exactly that.

Why you must not store secrets derived from the seed

The seed is the root of every private key the device will ever derive. If an application stores a derived key — even encrypted, even on the device’s own flash — it creates a persistent copy of a secret that was designed to be ephemeral.

The correct model is derive on demand, erase immediately. An application derives a key for a single operation, uses it, and calls explicit_bzero before the stack frame is torn down. This limits the window during which an attacker with code-execution capability could extract the key.

Why blind signing is forbidden

Allowing an application to sign an arbitrary hash is equivalent to allowing it to sign an arbitrary transaction. An attacker who controls the host can present a hash of a transaction the user did not intend to authorise. The user sees a prompt to confirm, but confirming means signing a transaction they never reviewed.

The mitigation is structural: only sign data with a known, validated format. For user-supplied “personal” messages, prepend a fixed prefix that cannot be a valid transaction prefix. This makes it impossible to repurpose a personal-message signature as a transaction signature.

Why user approval is always required

Without explicit user approval, the device becomes a signing oracle. Any process on the host — including malware — can instruct the device app to sign whatever it sends. Requiring a physical button press means the attacker must have physical access to the device, which is outside the threat model.

Consider whether your application should also require approval before revealing a public key. Some users prefer not to expose account public keys until a transaction actually requires it, since an exposed public key narrows the anonymity set.

Why you must use the SDK’s cryptographic primitives

Side-channel attacks — timing attacks, power-analysis attacks, electromagnetic leakage — are not theoretical on embedded secure hardware. The SDK’s cryptographic functions are implemented with constant-time guarantees and hardware acceleration specifically designed to resist these attacks on the Secure Element.

Custom implementations, even correct ones from a pure-cryptography perspective, almost certainly lack these mitigations. If the SDK does not support the primitive you need, contact Ledger to discuss adding it rather than implementing it yourself.

Why _no_throw variants are required

The cx_ecdsa_sign family of functions raises an exception on failure using a non-standard C exception mechanism. Exception paths are difficult to reason about and have historically been the source of private-key leaks: the explicit_bzero call that was supposed to run after the signing operation is skipped when the exception is thrown, leaving key material on the stack.

The _no_throw equivalents return an error code instead of throwing, making it straightforward to clean up in all code paths — a standard if (err != CX_OK) { goto cleanup; } pattern with explicit_bzero in the cleanup label.

Further reading

Ledger
Copyright © Ledger SAS. All rights reserved. Ledger, Ledger Stax, Ledger Flex, Ledger Nano, Ledger Nano S, Ledger OS, Ledger Wallet, [LEDGER] (logo), [L] (logo) are trademarks owned by Ledger SAS.