808bits

Fireblocks Recovery Utility: what verify mode actually checks

2026-06-12 · updated 2026-09-03 · 3 min

A Fireblocks backup kit is a ZIP file with one JSON document and a handful of ciphertexts. Verify mode decrypts the ciphertexts, adds them up modulo the curve order, multiplies the sum by the generator point, and compares the result to a hex string inside the JSON. If the bytes match, the tool prints Verified!, in green. That is all the word means.

I read the verify path in both tools Fireblocks publishes for this, the old Python script and the current desktop Recovery Utility, as they were on GitHub this spring, because I wanted to know what a customer can honestly claim after a green line on an air-gapped laptop. The answer turned out to be narrower than the word suggests.

Publishing the tooling at all is good design. Your exit from the platform does not depend on the platform being alive.

Verify is recover with one flag

The desktop app’s Verify page and its Recover page are the same form. RecoveryForm passes dangerouslyRecoverPrivateKeys: !verifyOnly into the same function. The private keys are computed either way. What changes is whether they survive to the result object: with the flag false, the code deletes xprv and fprv before returning. The legacy script does the same behind a --prv flag and a y/N prompt that defaults to no.

It is a good design. A routine check does not turn into a key-handling incident.

Between decrypt and delete, the shares are combined and the result is compared to publicKey in metadata.json. One mismatch and the Utility throws Mismatch between recovered keys and metadata - unable to continue. The legacy tool prints the expected and computed keys for the failing key and carries on to the next one, which I preferred, for what that is worth.

Correction, 3 September 2026. An earlier version of this article said the shares are recombined by Lagrange interpolation. That is true only for the older share format. Keys created under the CMP protocol are additive shares and are summed directly.

What the green line proves

For that kit, on that machine, on that day: your recovery RSA key and its passphrase are correct, the owner’s mobile passphrase is correct, every key id in the metadata has shares in the ZIP and every share has an entry in the metadata, and the shares produce the private key whose public key the kit says it should have. That is worth having.

Three things it takes on trust

The reference is inside the kit. The public key the tool compares against was written into metadata.json by the same system that wrote the shares. A Verified! proves the kit is self-consistent. Binding it to your workspace is a human comparing two 111-character base58 strings against the console, and the tool does not do that part.

The chain code is copied, not checked. The extended key you see is built from a chain code read straight out of the metadata. It is not reconstructed from shares and nothing checks it. A wrong one would pass the key-level comparison and derive wrong addresses for every wallet.

The kit is a snapshot. The Utility iterates keysets from 1 to the highest id it finds in the metadata. A keyset created after the backup was cut does not fail the check. The check never hears about it.

There is a fourth one, in the wallet-level check the Utility offers after verification. It is the one I would want a board to know about before it accepts a verification report, and it sits in the source next to a TODO.

The tool makes one check cheap. The questions a board asks start where that check stops.