Documentation Menu
Security Model
W2QR’s threat model, key lifecycle, and honest trade-offs.
Threat model
W2QR protects against an attacker who obtains your QR code — whether by stealing the paper, intercepting a photo, or accessing your cloud storage. The attacker may also have unlimited computing resources to brute-force passwords.
W2QR does not protect against:
- - Malware on your device at the time of encryption or decryption
- - Shoulder surfing / someone watching you type your password
- - A compromised browser or operating system
No password verifier
This is W2QR’s strongest security guarantee. There is no stored hash, MAC, known plaintext, AEAD tag, wallet address, or any other artifact that lets someone check if a password is correct without going to the blockchain.
Every password decrypts to a valid BIP-39 seed phrase. To find the real one, the attacker must derive wallet addresses from each candidate and check them on-chain — economically infeasible at scale.
Client-side only
All cryptographic operations happen in your browser. The W2QR server never receives:
- - Your password
- - Your seed phrase (mnemonic)
- - Your private keys
- - Your wallet addresses
All encryption and decryption runs in your browser. The W2QR server never stores or receives your password, seed phrase, private keys, or wallet addresses.
Key lifecycle
Trust domains
The system is designed so that no single trust domain can access your wallet:
| Domain | Knows | Cannot access |
|---|---|---|
| You | Password, QR, catchy phrase | — |
| Google Drive / W2QR server | Encrypted backup ciphertext (if backed up) | Password, mnemonic, private keys |
| Device | Biometric credentials (if enrolled) | Password, mnemonic without biometric verification |
| QR thief | Ciphertext only | Password, mnemonic, private keys |
Honest trade-offs
Rate limiting
Server-side API routes are rate-limited per IP address. All access attempts are audit-logged. All error messages are generic — the server never reveals whether an operation succeeded or failed for security reasons.
TOTP as an optional second factor
Google Authenticator (TOTP) can be added as an optional second factor for wallet access — useful when unlocking on a new or borrowed device without registered biometrics.
The TOTP secret is stored encrypted server-side. It is never included in your QR code and never sent to the client.
TOTP verification is rate-limited and audit-logged. All error messages are generic — the server never reveals whether TOTP is enrolled or whether a code was close to correct.
W2QR Cards — plausible deniability
A W2QR Card contains random bytes that become a wallet only when combined with a password through honey encryption. Every password produces a valid BIP-39 mnemonic — the card itself does not “belong” to any particular wallet until activated.
An attacker who steals a card cannot determine which password was used to activate it. There is no hash, MAC, AEAD tag, or any verifier that reveals the correct password. The only way to identify the real wallet is to derive addresses from each candidate mnemonic and check balances on-chain — economically infeasible at scale.
All errors return the same generic message: “Unable to unlock this W2QR. Check your credentials.” There is no way to distinguish a wrong password from a card that was never activated.
Plastic card activation security
A pre-printed plastic card uses honey encryption. After activation with your password, you can add biometric protection, Google Drive backup, and other optional security layers. The physical card’s QR does not change during activation — it remains usable with the same password.
W2QR also supports a password QR card: print your strong password as a separate QR on a second plastic card. Keep the wallet card and the password card in different locations — together they open your wallet, apart each is useless to an attacker.