Standards

What Faraday takes in is a published standard, followed and checked against an implementation Faraday did not write, or Faraday's own rule that fails closed. Work on an unpublished standard, or on a construction of Faraday's own that has not been reviewed, stays in the repository, compiled out of the app.

The rule The standards How it is checked What stays out Sources

The rule

From Faraday's STANDARDS §0, written in decision F109 on 2026-10-23.

A published standard, followed and checked

A wallet kind, key method, format or signing procedure is in the app when it follows a published standard (a BIP at Complete or Deployed, a SLIP, an RFC, or a convention other wallets already use), is built in full or names the part it leaves out, and is checked against that standard's vectors or another implementation.

A draft that is stable enough

A draft whose text has held still, that has independent implementations and that Faraday's cross-check agrees with, can be in the app. The tables below mark it as a draft; codex32, BIP 93, is one.

Faraday's own, conservative

Where no standard exists, Faraday's own format or rule is in the app when it fails closed (a refusal, a record layout) and a decision records it. A cryptographic construction of Faraday's own is in the app only once it has been reviewed, or when it can only add to a standard's strength, as mixing a person's own randomness into the system's does.

Checked against an implementation Faraday did not write

Anything that makes or reads a key, a secret, a seed or backup encoding, an address, a signature or a transaction is checked against an independent implementation: a pinned reference in the cross-check, or the other tool itself end to end (Bitcoin Core, gpg, openssl), and against the standard's published vectors where they exist. Where no other implementation exists, a reference written from the specification, never from Faraday's code, counts.

Screen and flow logic, and code that carries bytes without reading them, rest on Faraday's own tests. New cryptographic code lands with its check; a gap found later is closed before 1.0.

Otherwise it waits in the repository

A feature whose standard is unpublished, or whose construction is Faraday's own and not yet reviewed, stays in the repository, built and tested but compiled out of the app, until its standard is published or it is reviewed.

Scope

Faraday is an offline Bitcoin signer and its keys' keeper. A feature outside that, however well specified, is not taken on.

The standards Faraday follows

Each standard, what Faraday uses it for, and what Faraday's results are checked against. BIP statuses are BIP 3's (Draft, Complete, Deployed), read from the BIPs repository on 2026-10-23. A cross-check area is the part of the cross-check, below, that recomputes one kind of result with a reference Faraday did not write.

Wallets

StandardWhat Faraday uses it forChecked against
BIP 32, 44, 49, 84, 86, 341 and 380 to 386 (Deployed)Single-key wallets (pkh, sh(wpkh), wpkh, tr) and watch-only wallets: derivation, addresses and descriptorsBIP 32 vectors; Bitcoin Core 31.1 end to end; cross-check areas bip32 and addr
BIP 48 (Deployed), BIP 67 (Complete), BIP 383 (Deployed)Multisig wsh and sh(wsh) with sortedmulti. A key with no origin is refusedBitcoin Core end to end, two sessions combined; Sparrow, Coldcard and Electrum files
The m/45' export of Coldcard and Unchained, a conventionLegacy multisig sh(sortedmulti), with m/45' as an account; not BIP 45's own schemeBitcoin Core end to end; Unchained and Coldcard files
BIP 386 and 387 (Deployed)Taproot multisig tr(H, sortedmulti_a). Its path, m/48'/c'/0'/3', has no standard and is Faraday's choiceBIP 387 vectors; a Bitcoin Core 31.1 PSBT round trip
BIP 379 (Draft), BIP 382 and 386 (Deployed), BIP 388 (Complete), BIP 389 (Draft)Reading miniscript wallets and timelocked recovery, in Liana's shapes. Create does not make oneBitcoin Core end to end for the wsh timelock and Taproot tree wallets; Liana's files
BIP 327 (Deployed), BIP 328 and 373 (Complete), BIP 390 (Draft)MuSig2 wallets, key path only: signing with the session open between rounds, or signing lastAll eight BIP 327 vector files; BIP 328 and 390 vectors; cross-check area musig against BIP 327's reference code; Bitcoin Core 31.1 round trip in both orders
BIP 352 (Complete), BIP 392 (Draft), BIP 321 and 353 (Complete)Receiving silent payments: labels and the scan key's exportAll BIP 352 vectors, both sides; cross-check area sp against BIP 352's reference code

Keys and backups

StandardWhat Faraday uses it forChecked against
BIP 39 (Deployed)Seed words: ten word lists, every length. A passphrase is printable ASCII, at most 256 bytesThe official and Japanese vectors; the bip39 crate; cross-check area bip39 against python-mnemonic
SLIP-0039Shamir shares of secrets of 16 to 32 bytesAll 45 vectors; cross-check area slip39 against python-shamir-mnemonic, word for word
BIP 93, codex32 (Draft)codex32 shares: making, checking, deriving and recovering them, the worksheets, and error correction, which is opt-in and off by defaultEvery BIP 93 vector, the 55 invalid strings included; the booklet's and the volvelle's tables; cross-check areas codex32 and codex32-correct against python-codex32
The codex32 booklet, SSS32 of 2023-03-07Dice for a codex32 secret, six-faced dice onlyThe booklet's tables; cross-check area codex32
Codex32QR/v1-48, the profile of one SeedSigner forkcodex32 strings as QR codes, 48 characters only; longer profiles are refused. The profile is new and not peer-reviewed. It comes from FractalEncrypt's SeedSigner fork, branch codex/codex32-error-correction (MIT). The full-string QR is the form the codex32 authors' discussion 66, "CodexQR", describes, and that is where the format is being settled; Faraday draws no compact CodexQR until it is. Faraday writes the code in alphanumeric mode, as the profile's pictures are, and reads either mode. It follows the profile for the QR, not that device's workflowThe profile's vectors and its 22 pictures, each read from its pixels and found to be Faraday's code of its string, module for module (6 under the mask the profile's encoder chose); cross-check areas codex32 for the strings and seedqr for the code and the picture, against Project Nayuki's qrcodegen
Coldcard's Seed XOR documentSeed XOR, 2 to 4 partsColdcard's two examples and two made here; cross-check area xor against python-mnemonic
BIP 85 (Deployed)Child keys from a seed: applications 2', 32', 39', 128169', 707764' and 707785'BIP 85 vectors; cross-check area bip85 against BIP 85's reference implementation
The dice procedures of Coldcard, SeedSigner, Keystone and BitBoxKeys from dice: 99 rolls for 256 bits, as those tools acceptTranscripts from those tools; cross-check area entropy, the three procedures written from the quoted sources
Convention: coins and hex, most significant bit firstKeys from coin flips and from hexadecimalCross-check area entropy, a reference written from the repository's description of the procedure
No standard: playing cards, camera noise, and the mix of sourcesKeys from cards (SHA-256 of one-byte draw indices) and from camera frames (SHA-256 of the frames' digests), and the mix of sources (SHA-256 over their commitments). All hash-based; the risk is lowCross-check area entropy, a reference written from the repository's description of each, never from Faraday's code
No standard: the session's own randomnessA person's own randomness mixed into the system's, never in place of itCross-check area own-randomness, the construction written out over hashlib
No standard: the desktop dice rollerDice rolled on screen, labelled "simulated dice", on the desktop app onlyCross-check area roller, both rollers against the values the codex32 specification states
SeedSigner's SeedQRSeedQR and CompactSeedQR, EnglishSeedSigner's nine test codes; cross-check area seedqr, the specification written out over python-mnemonic and the codes module for module against Project Nayuki's qrcodegen
LND's aezeed, over AEZ v5Reading an LND seed, for its node keyAEZ reference vectors; LND's cipher seed and node id; cross-check area lightning for the outer layer (checksum, version). AEZ itself has no second implementation
KeePass's KDBX 4Exporting passwords: write only, ChaCha20 and Argon2idCross-check area kdbx: every file read back by pykeepass
The EFF word listsDiceware passphrasesThe lists' digests

Signing and moving data

StandardWhat Faraday uses it forChecked against
BIP 174, PSBT version 0 (Deployed)Signing for every wallet kind above. A key comes only from the PSBT's originBIP 174 vectors; Bitcoin Core end to end; cross-check area psbt for reading and writing PSBTs
BIP 143, 341 and 342 (Deployed)Sighashes: all are computed; only ALL and DEFAULT are signedBitcoin Core end to end; cross-check area tx against Bitcoin Core's test framework: Core's 500 legacy sighashes, BIP 143's thirteen and BIP 341's key-path sighashes
RFC 6979; Bitcoin Core's low-R grindingECDSA nonces, low-R by defaultRFC 6979 vectors; the self-test
BIP 340 (Deployed)Schnorr signatures: zero aux_rand by default, fresh randomness as an optionlibsecp256k1's vectors, in the self-test
BIP 173 and 350 (Deployed)Addresses, and the check of a scanned address against the first 100 receive and change addressesBitcoin Core end to end; cross-check area addr against Bitcoin Core's test framework
BIP 380 to 387 (Deployed), BIP 388 (Complete), BIP 389 and 390 (Draft)Descriptors and their checksums, with h marking a hardened stepBitcoin Core's checksums; cross-check area addr, with BIP 380's own checksum code and Core's descriptors.py
BIP 137 (Deployed), BIP 322 (Complete)Signing and checking messages; BIP 322's simple form onlyBIP 322's vectors from the BIPs repository; Trezor's and Electrum's BIP 137 vectors; cross-check area msg
BIP 129, BSMS (Complete)Multisig setup records without encryption; signer records' signatures are checkedThe BIP's examples; Nunchuk's and Sparrow's records
Blockchain Commons' UR: BCR-2020-005, 006, 012 and othersAnimated QR codes, the legacy crypto-* types and fountain codesBCR-2020-012 vectors; SeedSigner's and Keystone's codes; cross-check area ur against foundation-ur-py, with URKit's vectors
BBQr, bbqr.orgAnimated QR codes: reads base32, hex and zlib, writes base32Cross-check area bbqr against Coinkite's Python library
Specter's pNofM, as Specter and SeedSigner use it; not publishedMulti-part QR codes, read and writtenCross-check area bbqr, against SeedSigner's reader
Other wallets' file formatsWallet files from the wallets INTEROP §2 listsFiles from those wallets' test suites

Tools

StandardWhat Faraday uses it forChecked against
RFC 6238 and 4226; the otpauth:// formatTOTP codesRFC 6238 vectors
RFC 4880 and 9580, version 4 packets; GnuPG's behaviourA GPG key: Ed25519 certification and a signing subkeyJudged by gpg 2.4 and paperkey 1.6
UEFI, Authenticode, X.509 and CMSSecure Boot keys: PK, KEK and db, RSA-2048, .auth files and signingopenssl and sbverify
ldk-node and rust-lightning; LND's aezeedLightning node keysFive ldk vectors made with the lightning crate, version 0.2.6; LND's own; cross-check area lightning, both derivations written from the quoted sources
EntropyLab's counterVanity addressesTwo EntropyLab vectors; cross-check area vanity, the search written from EntropyLab's counter
BIP 141 and 144 (Deployed)Decoding a transactionCross-check area tx: txid, wtxid, weight and bytes against Bitcoin Core's test framework
BIP 379 (Draft); rust-miniscript's compilerThe miniscript compiler, for SegWit or Taprootrust-miniscript

The full tables, with how much of each standard is built and every choice Faraday made, are in STANDARDS §2 to §5.

How it is checked

On a developer's machine, offline. No hosted service runs any of it.

Published vectors

Each standard's published test vectors are kept in the repository's tools/vectors folder, and Faraday's tests and the cross-check run them.

The cross-check

Decision F79 (just crosscheck). Faraday's own Rust answers requests, and pure-Python references Faraday did not write recompute every answer: the BIPs' reference code, Bitcoin Core's functional-test framework, python-mnemonic, python-shamir-mnemonic, python-codex32, Coinkite's BBQr library, foundation-ur-py and Project Nayuki's qrcodegen; where no other implementation exists, a reference written from the specification's text. It runs over every published vector and a corpus of random inputs drawn from a fixed seed, in twenty-four areas, and stops at the first disagreement, with its inputs and both answers.

Before each run, every area is given an answer changed on purpose, and the run fails unless every area reports it.

Pinned and offline

The references are copied into the repository's tools/reference folder, each with its source and its SHA-256; a file that does not match is refused. Argon2id and XChaCha20-Poly1305 come from the Linux distribution's signed packages, not pip. The cross-check runs in a network namespace with no interfaces, and nothing of it is in an image or an app.

The stamp, at every commit

A passing run records a hash of the crypto sources and the crypto crates' entries in Cargo.lock. The repository's lint (just lint) fails when they no longer match, so a change to the crypto, or a version bump of a crypto crate, is not committed without a passing cross-check. The stamp is a record, not a security control.

Before every release

The cross-check runs again with a new random seed and about ten times the random cases (just crosscheck --fresh); a disagreement it finds is kept as a new vector. Every fuzz target runs for 10 minutes (just fuzz-release); any crash fails it.

Other tools, end to end

Where another program does the same job, Faraday's output goes through it: Bitcoin Core 31.1 for wallets and PSBTs, gpg 2.4 and paperkey 1.6 for GPG keys, openssl and sbverify for Secure Boot keys, pykeepass for KDBX files, and other wallets' own files.

Fuzzing

Thirty-seven cargo-fuzz targets, one per parser of something the device did not write: a camera frame, a scanned code, a PSBT, a key share, a file on a stick. A new parser of untrusted input gets its fuzz target in the change that adds it.

Dependencies

Decision F71. The repository's lint runs cargo vet --locked: every dependency is trusted by a named publisher (rust-bitcoin, RustCrypto, dalek and others), covered by an imported audit, or an exemption whose page in docs/deps says "not reviewed". Every direct dependency has such a page. Sources are pinned by Cargo.lock's checksums, and every build passes --locked. The lint also runs cargo deny, which checks advisories, licences and sources.

What the checks do not catch

What stays out of the app

Built and tested in the repository, or not taken on. From STANDARDS §0.1.

Left outWhyWhere it stands
FROST threshold walletsBIP 445 is not published, and signing across places is Faraday's own construction, not yet reviewedCompiled out of the app (F109). The code is in the repository, built and tested, behind a feature no shipped app turns on. It comes back when BIP 445 is published and signing across places is reviewed
MuSig2 signing across placesFaraday's own construction, not yet reviewedCompiled out of the app (F109). MuSig2 with the session open between rounds, and signing last, stay
Sending to silent paymentsBIP 374 and BIP 375 are drafts; receiving, BIP 352, is in the appBuilt in the repository's core, not reached from the app
SSH signatures and an SSH CA, minisign and signify, an X.509 certificate authorityOutside a Bitcoin signer's scopeNot planned

Where Faraday is stricter than the standard

Each refuses what a standard allows. From STANDARDS §6.

Faraday's own constructions, for outside review

Ranked by how much a mistake would cost. From STANDARDS §7. The Audits page says how to submit a review.

  1. Signing across places, for MuSig2 and FROST. Compiled out of the app until it is reviewed.
  2. The FROST trusted dealer and the wallet around it. Compiled out of the app.
  3. The vault: Faraday's own container over Argon2id, HKDF-SHA256 and XChaCha20-Poly1305, with four equal slots. Checked against its own vectors and a Python reader written over independent primitives.
  4. The session's random generator, SHA-256 over concatenations. Every nonce and key Faraday draws passes through it, and a person's own randomness is mixed into it, never in place of the system's.
  5. Entropy from cards, camera frames and a mix of sources, which have no published procedure. All hash-based; the risk is low.
  6. Secure Boot RSA keys from a random-number adapter written here, feeding a release candidate of the rsa crate.

Audits

Not built

From STANDARDS §2 to §5.

Sources

In the Faraday repository on GitHub. Where this page and those files differ, the files are right.

Buy me a coffee

Donations to Faraday's development, in bitcoin.

QR code to come
Lightning
QR code to come
Bitcoin