W2QR

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

In Advanced mode, the server stores only encrypted material (KEK-wrapped secrets) and shares — none of which are useful without your password or a second factor.

Key lifecycle

Creation

Keys are derived in the browser using Argon2id (WASM) and HKDF-SHA-256. Authorization secret S and recovery root R are generated from CSPRNG (crypto.getRandomValues). All key material is held in memory only.

Storage

S is encrypted with the Recovery Code for offline backup and with a device-bound WebAuthn PRF key for quick access. On the server, S and R1 are wrapped under a KEK derived from an environment secret via HKDF.

Zeroization

Derived keys and intermediate buffers are zeroed in memory after use. JavaScript does not guarantee immediate memory clearing, but explicit zeroization defends against heap dumps and inspector tools.

Rotation

After a recovery event, W2QR generates a new S and re-wraps all shares. The old S is revoked server-side. This limits the window of exposure if a factor was compromised.

Trust domains

The system is designed so that no single trust domain can access your wallet:

DomainKnowsCannot access
YouPassword, Recovery Code, QRServer KEK
Google Account / W2QR serverWrapped S, R1 sharePassword, mnemonic, private keys
DevicePRF-encrypted S, R2Server data, Recovery Code
QR thiefCiphertext onlyPassword, S, all shares

Honest trade-offs

vs. Hardware wallets

A hardware wallet stores keys in a secure element — stronger physical security. W2QR stores keys as encrypted QR codes — more portable and no hardware dependency. Neither is strictly better; they serve different needs.

vs. Metal seed plates

A metal plate survives fire and water. An encrypted QR survives being photographed or emailed — the encryption protects it. W2QR is a complement to metal backups, not a replacement.

vs. Cloud wallets (exchanges)

An exchange holds your keys for you — convenient but custodial. W2QR is always non-custodial: your keys are never on any server in usable form.

Rate limiting

Server-side API routes that release encrypted secrets are rate-limited per user, per wallet, and per IP address. This prevents online brute-force attempts against the authorization factor. All access attempts are audit-logged.