Format in one sentence
ISQR1 is a URL-safe string containing all parameters a decoder needs to decrypt: version, salt, IV, and ciphertext including the AES-GCM auth tag.
ISQR1:<salt_b64url>:<iv_b64url>:<ciphertext_b64url>
Fields
| Field | Length | Description |
|---|---|---|
ISQR1 |
5 characters | Version and magic prefix. Decoders must reject unknown versions. |
salt_b64url |
16 bytes before encoding | Random salt for PBKDF2. Must be freshly generated per encryption. |
iv_b64url |
12 bytes before encoding | AES-GCM nonce. Must be unique with the same key. |
ciphertext_b64url |
variable | AES-GCM ciphertext including 128-bit authentication tag. |
Cryptographic Parameters
CipherAES-GCM 256-bit
KDFPBKDF2-SHA-256
Iterations250 000
EncodingBase64url without padding
ABNF-like Grammar
payload = "ISQR1:" salt ":" iv ":" ciphertext
salt = 1*( ALPHA / DIGIT / "-" / "_" )
iv = 1*( ALPHA / DIGIT / "-" / "_" )
ciphertext = 1*( ALPHA / DIGIT / "-" / "_" )
Implementations should not only validate the grammar but also check the decoded byte lengths for salt and IV.
Decoder Rules
- Strip whitespace and treat the UTF-8 text as the payload.
- Optionally URL-decode the part after
#from URL fragments. - Check the prefix exactly against
ISQR1. - Decode salt, IV, and ciphertext as Base64url without padding.
- Derive a 256-bit AES-GCM key from the password and salt via PBKDF2-SHA-256.
- Decrypt ciphertext with AES-GCM and IV. Errors indicate wrong password or tampered data.
Security Invariants
No Reuse
Salt and IV are freshly generated for each encryption from crypto.getRandomValues.
No Server Secrets
The standard mode requires neither a database nor a master key. Everything needed is in the QR code.
Authenticity
AES-GCM provides integrity protection. Tampered payloads cannot be decrypted successfully.
Versioning
New formats can be introduced as ISQR2 without silently breaking existing decoders.