Attack-cost estimates
The published estimates describe different attacker-knowledge assumptions. None is a measured entropy value for an individual device.
Firmware and cryptographic detail.
Block, Coinkite, LLFOURN and otaliptus describe the search space using different assumptions about what an attacker knows. The figures below are candidate counts, not direct measurements of seed entropy. They should not be combined without carrying their assumptions forward.
"This analysis is based on our current understanding of the situation. We have not done full empirical testing to confirm exploitability."Block Engineering, disclosure summary
| Source | Mk2 / Mk3 | Mk4 / Mk5 / Q | Assumptions represented |
|---|---|---|---|
| Block | 2^0 with timers known;~2^16.3 with stable RTC;2^32 ceiling with the UID-XOR-SysTick word unknown;<2^40.7 loose ceiling | ≤2^32 with known fallback state;<2^73.3 loose ceiling | For Mk4-class devices, these figures assume a successful reseed. Block's narrow cases assume the UID, call history and relevant timing state are known or constrained. The 2^32 Mk2/Mk3 figure is the ceiling Block gives when the effective 32-bit UID-XOR-SysTick value is entirely unknown; Block adds that unknown call history multiplies these counts further. Its broader figures deliberately treat correlated timer fields independently and are enumeration ceilings, not entropy measurements. |
| Block, conditional no-reseed path | not applicable | 2^0 with fallback state known;<2^41.3 loose ceiling | A catchable early-initialisation error could leave libngu at its public initial state. Block says ordinary secure-element failures appear to halt instead, so this source path remains conditional pending hardware validation. |
| Coinkite | Mk3: ~2^40Mk2: not separately stated | ~2^72 | Upper scenarios that retain uncertainty from the MCU identifier and timing inputs. These are estimates, not measurements across a device population. The backgrounder states the 40-bit figure for Mk3 and says nothing separately about Mk2, so carrying it across to Mk2 would be a further derivation from the shared code path. |
| LLFOURN | Mk3: ~2^40.3Mk2: not separately stated | ~2^72.3 | A stated Mk3 model of about 2^20 possible MCU identifiers, 80,000 timing states and 16 button-press variants, plus the 32-bit reseed term on Mk4-class devices. The source does not decompose the 16 variants further. Applying the Mk3 figure to Mk2 would be a separate derivation from their shared path. |
| LLFOURN follow-up | not separately quantified | ~2^58.3 to ~2^62.3 | LLFOURN later said the Mk4-class space was probably 10 to 14 bits smaller than the original 2^72.3 estimate because clock-related assumptions could be narrowed. The subtraction shown here is derived from that statement. |
| LLFOURN, known-UID scenario | not stated | 2^32 | In a later reply, LLFOURN said a pessimistic view in which the UID is known and button presses and clock behaviour are more predictable leaves 32 bits of work per Mk4 theft. This converges on Block's lower scenario through an explicit attacker-knowledge assumption. |
| otaliptus, tentative model | not stated | ~2^52 to ~2^63 if RTC is problematic; ~2^75 to ~2^88 otherwise | Assumes a remote attacker does not know the UID, estimates 20 to 21 bits from the wafer-coordinate word, narrows practical SysTick positions, and treats the Mk4 RTC contribution as unresolved. The author explicitly labels the post brainstorming and lists details that may be wrong. |
The MCU identifier term
The affected MicroPython fallback reads one 32-bit word from the STM32L4's 96-bit unique-identifier area. It combines that word with the SysTick counter, and seeds two other state words from the real-time clock and its subsecond register.
micropython/ports/stm32/rng.c and mpconfigboard_common.h
#define MP_HAL_UNIQUE_ID_ADDRESS (0x1fff7590) pad = *(uint32_t *)MP_HAL_UNIQUE_ID_ADDRESS ^ SysTick->VAL; n = RTC->TR; d = RTC->SSR;
ST documents the first UID word as wafer-coordinate data and the remaining
words as wafer and lot information. That field layout explains why an
analyst might model fewer than 2^32 possible first words, but it
does not by itself establish a COLDCARD-specific range. This project holds
no population sample of device UIDs, so
LLFOURN's 2^20 assumption
remains unchecked here.
The unresolved RTC term
otaliptus isolates a second uncertainty that the headline bit counts can hide: whether the real-time clock contributes useful variation on Mk4-class devices. The post models roughly 24 additional bits if it does, and no such contribution in the pessimistic case, then broadens both results to reflect uncertainty in the other inputs. It does not report that Mk4 RTC behaviour is broken. The author says that question is unanswered.
This archive has no runtime measurements that resolve it. The resulting ranges therefore belong beside the other published scenarios, not above them as a replacement estimate.
flowchart LR
UID["STM32L4 96-bit UID"] --> W1["first 32-bit word\nread by fallback"]
UID --> W23["remaining 64 bits\nnot read by fallback"]
W1 --> MIX["XOR with SysTick"]
RTC["RTC time and subsecond"] --> STATE["other Yasmarang state"]
MIX --> STATE
STATE --> OUT["MicroPython fallback output"]
Verified data flow. The diagram does not assign an entropy value to any input.
Illustrative half-space times
The following table applies time = 2^(bits - 1) / rate. Calling
half the space an average assumes that the target is uniformly positioned in
the enumerated order and that the attacker has no better prioritisation. The
device-state distributions have not been measured, so this is a sensitivity
model, not an empirical average or a forecast of attacker capability. A day
is 86,400 seconds and a year is 365.25 days in the displayed conversions.
The displayed rates are input values, not benchmarks reported by the sources. One candidate means an end-to-end check against the available address, public key or xpub. Its real cost varies with the device-state model, derivation path, batching, hardware and target information. In particular, the same numeric rate must not be assumed to describe both raw generator-state enumeration and BIP39 passphrase testing.
| Scenario | Candidates | 4,000/s | 2 million/s | 16 million/s | 1 billion/s |
|---|---|---|---|---|---|
| Mk2/Mk3, Block stable-RTC scenario | 2^16.3 | 10 seconds | 0.02 seconds | 0.003 seconds | 0.00004 seconds |
| Mk3, approximately 40-bit scenario | 2^40 | 4.4 years | 3.2 days | 9.5 hours | 9.2 minutes |
| Mk4-class, Block successful-reseed scenario with known fallback state | 2^32 | 6.2 days | 17.9 minutes | 2.2 minutes | 2.1 seconds |
| LLFOURN follow-up range | 2^58.3 to 2^62.3 | 1.4 to 22.5 million years | 2,800 to 45,000 years | 351 to 5,600 years | 5.6 to 90 years |
| Approximately 72-bit scenario | 2^72 | 18.7 billion years | 37.4 million years | 4.7 million years | 74,800 years |
The in-browser estimator applies the same formula to every source-labelled scenario and lets you add uniform dice or passphrase assumptions without sending or storing the inputs.
How a candidate is checked
A candidate mnemonic can be passed through BIP39's 2,048-round PBKDF2-HMAC-SHA512 step and the relevant wallet derivation path. A known address, or an extended public key obtained separately, then provides an offline comparison target. There is no device PIN or network rate limit in that comparison.
Precomputation can reduce repeated work only to the extent that candidate inputs and derivation paths are shared across targets. Device-specific UID and timing assumptions limit how broadly one table applies. How much precomputation has actually been done is not visible in the public evidence.