Encrypted QR decoding is governed less by cipher choice than by symbol density, module sampling, optics, motion, exposure and the scanner pipeline. A byte budget and a declared test envelope make a sub-second target measurable.
An encrypted QR code can fail before the cipher runs. The camera may not resolve individual modules, exposure may smear an edge across two cells, and the application may queue stale frames while the user moves the phone away.
This is why “decrypts in under 300 milliseconds” is not a property of ChaCha20-Poly1305, AES-GCM or QR Code in isolation. It is a result observed inside a specified operating envelope. That envelope must state the symbol version, error-correction level, payload length, displayed size, quiet zone, brightness, ambient light, distance, motion, camera pipeline and device population.
The task is to declare that envelope and allocate bytes within its tested boundary.
Start with the binary envelope
Both cipher suites considered here are authenticated-encryption schemes. Ciphertext length before the authentication tag is the same as plaintext length. RFC 8439 fixes a 12-byte nonce and a 16-byte tag for the IETF ChaCha20-Poly1305 construction. NIST recommends restricting GCM implementations to 96-bit IVs for interoperability, efficiency and simplicity, while its specification permits several tag sizes. For this comparison, AES-GCM also uses a full 16-byte tag.
Part 1 selected HPKE as the key schedule and encryption framework. HPKE derives the AEAD key and base nonce from the encapsulated shared secret, and the one-message context uses sequence number zero. The 12-byte nonce therefore is not another wire field. Only the 16-byte tag expands the encrypted application data. A standalone ECDH-plus-AEAD protocol that transports an IV would need to add those 12 bytes back into its own budget.
Those 28 bytes are only the cryptographic framing. A deployable offline exchange also needs protocol identifiers and state. Consider this illustrative envelope:
| Field | Bytes | Purpose |
|---|---|---|
| Format version and profile suite code | 2 | One byte each; the suite code maps to the full HPKE tuple |
| Verifier or key identifier | 4 | Locates pre-provisioned context |
| Ephemeral X25519 public key | 32 | Supports per-token key agreement |
| Issued time | 4 | Carries bounded freshness information |
| Random message identifier | 16 | Gives the verifier a replay-cache key |
| Authentication tag | 16 | Expands the HPKE ciphertext and rejects modification |
| Encrypted application data | P | The actual credential or transaction payload |
This planning profile costs 74 bytes, so the QR input is 74 + P bytes. A protocol that derives the key without carrying an ephemeral public key can remove 32 bytes. An optional sender counter, digital signature, certificate chain or verbose identifier must be added explicitly.
Encoding raw binary as Base64 makes the optical problem worse. Base64 expands an input to four characters for every three bytes, rounded to a complete group. The 74-byte envelope becomes 100 ASCII bytes before any application data is added. If the QR encoder accepts byte-mode input, carrying the binary object directly preserves capacity. If a string-only interface is unavoidable, the expansion belongs in the budget.
Compression must precede encryption because proper ciphertext resists compression. Its safety needs separate analysis when secret and attacker-controlled values share a compression context.
Capacity falls as correction rises
QR Code versions run from 1 to 40. Each step adds four modules per side. Versions 4 through 10 therefore range from 33 by 33 to 57 by 57 modules, before the quiet zone. DENSO WAVE’s capacity chart gives the following maximum inputs for binary byte mode:
| QR version | Modules | Level L | Level M | Level Q | Level H |
|---|---|---|---|---|---|
| 4 | 33 x 33 | 78 B | 62 B | 46 B | 34 B |
| 5 | 37 x 37 | 106 B | 84 B | 60 B | 44 B |
| 6 | 41 x 41 | 134 B | 106 B | 74 B | 58 B |
| 7 | 45 x 45 | 154 B | 122 B | 86 B | 64 B |
| 8 | 49 x 49 | 192 B | 152 B | 108 B | 84 B |
| 9 | 53 x 53 | 230 B | 180 B | 130 B | 98 B |
| 10 | 57 x 57 | 271 B | 213 B | 151 B | 119 B |
Levels L, M, Q and H provide increasing Reed-Solomon redundancy. DENSO describes approximate restoration rates of 7, 15, 25 and 30 percent, respectively. More redundancy means less data capacity. It can recover damaged codewords, but it cannot reconstruct a symbol whose modules were never resolved by the camera.
For the 74-byte illustrative envelope, Version 4 fits only at Level L and leaves four application bytes. At Level M, Version 5 leaves 10 application bytes, Version 7 leaves 48, and Version 10 leaves 139. Level Q first leaves application capacity in Version 7 and reaches 77 bytes at Version 10. Level H first fits in Version 8 and reaches 45 application bytes at Version 10.
| Version | Application bytes at L | Application bytes at M | Application bytes at Q | Application bytes at H |
|---|---|---|---|---|
| 4 | 4 | Does not fit | Does not fit | Does not fit |
| 5 | 32 | 10 | Does not fit | Does not fit |
| 6 | 60 | 32 | 0 | Does not fit |
| 7 | 80 | 48 | 12 | Does not fit |
| 8 | 118 | 78 | 34 | 10 |
| 9 | 156 | 106 | 56 | 24 |
| 10 | 197 | 139 | 77 | 45 |
Leaving unused capacity inside a fixed version does not reduce its module count. The useful rule is to select the smallest version that carries the complete envelope at the selected correction level, then test that exact configuration. A smaller object helps only when it permits a lower version or a different correction choice.
Capacity is not optical readability
A phone displays modules as pixels, but the camera receives a projected, filtered and resampled image. The symbol needs a four-module quiet zone on each side. If a square display region of width D pixels includes that margin, its displayed module pitch is:
display pixels per module = D / (symbol modules + 8)
For a 420-pixel region, Version 4 provides about 10.2 displayed pixels per module, Version 7 provides 7.9, and Version 10 provides 6.5. Those are display values, not camera values. Distance, perspective, focus, lens modulation, sensor resolution, stabilization, demosaicing and pipeline scaling can all reduce the effective samples available to the decoder.
DENSO recommends at least four printer dots per module for stable printed operation and making modules as large as the area permits. This helps frame an experiment, but does not promise that four display pixels per module will survive camera capture.
An implementation should log the detected corner coordinates and estimate the symbol width in the analysis frame. Dividing that width by the number of symbol modules gives captured pixels per module. Test bins such as 4, 6, 8 and 10 captured pixels per module create a portable measurement that is more informative than recording only phone distance.
Screen brightness and ambient illumination must also be varied independently. A bright screen in a dark room can clip white modules, bloom into black modules and create reflections. A dim screen in strong ambient light can lose contrast. Automatic exposure and autofocus introduce settling time, so a stationary laboratory frame does not represent a handheld exchange at a gate or counter.
Motion can be expressed in module units. If image motion is v pixels per second, exposure is t seconds, and captured module pitch is m pixels, approximate blur is:
blur in modules = (v x t) / m
This does not model every camera artifact, but it turns “slight movement” into a variable that can be repeated. The test should include static presentation, controlled lateral motion and angular motion, with exposure metadata recorded where the platform makes it available.
Measure the full latency path
AEAD choice rarely changes the QR version in this HPKE profile because both choices use a derived 12-byte nonce and add a 16-byte tag. It may change processing time on a particular processor. AES-GCM often benefits from hardware acceleration; ChaCha20-Poly1305 is designed for efficient software execution. The only defensible selection is a benchmark across the supported device classes using the platform cryptographic implementation.
The measurement must separate five intervals:
| Interval | Start and end |
|---|---|
| Frame acquisition | First frame containing the complete symbol to delivery to the analyzer |
| Detection | Analyzer entry to located finder patterns and perspective transform |
| QR recovery | Transform to successfully corrected byte payload |
| Authentication | Payload parse through AEAD tag verification and plaintext recovery |
| Acceptance | Verified plaintext to application decision rendered or signaled |
Starting the timer when the scanner opens mixes application startup, camera warm-up and human alignment. Report those product metrics separately. For decoding, begin at the first analysis frame containing the complete QR and quiet zone.
The camera pipeline can add avoidable delay. Android CameraX documents a non-blocking mode that retains only the latest frame when analysis falls behind. Processing an old frame adds latency without improving the current view. Release each image promptly and record frame timestamps, queue delay, resolution and pixel format on every supported platform.
Build a declared test envelope
A practical program starts with a capacity sweep, then concentrates environmental testing around the failure boundary.
- Generate byte-mode symbols for every version from 4 through 10 and every correction level L, M, Q and H. Exercise payloads at the exact operational sizes, not random text with different encoding behavior.
- Render the complete symbol and quiet zone at controlled widths. Record both displayed and captured pixels per module.
- Test several display brightness settings against measured low, normal and strong ambient light. Include glare angles relevant to the installation.
- Repeat static, lateral-motion and angular-motion passes. Log exposure time when available so blur can be normalized by module pitch.
- Run both AEAD suites with the same application object and provisioned recipient context. Derive suite-specific keys through HPKE, and record decode and authentication separately.
- Include the oldest supported devices, not only median and flagship phones. Run cold-camera and warm-camera trials.
- Report success probability and latency percentiles. A median below 300 ms is insufficient if the 95th percentile takes a second or if repeated scans fail.
The acceptance statement can then be precise: for example, “at least 95 percent of warm-camera attempts authenticate within 300 ms for Versions 6 through 8 at Level M, when the captured module pitch is at least the measured threshold and blur remains below the tested limit.” The actual values must come from the deployment matrix. They cannot be copied from a QR capacity table.
If the envelope fails, reduce bytes before weakening authentication. Remove repeated field names, use fixed-width identifiers, encode integers directly, move invariant metadata into associated data known to both parties, and avoid Base64. If Version 10 still misses the target, enlarge the code, improve capture geometry, relax the latency objective, or redesign the exchange. Shortening an authentication tag is a security decision, not an image optimization.
The result is not a universal “optimal payload.” It is a controlled maximum for a particular field implementation. That is the number a protocol can safely depend on.
Context and scope
This analysis abstracts optical test design for an offline field implementation. The commissioning organisation, phone and scanner models, deployment location and measured latency results are omitted. The byte and optical calculations are reproducible from the assumptions stated here.
References
- DENSO WAVE, Information capacity and versions of the QR Code
- DENSO WAVE, QR Code error correction feature
- DENSO WAVE, Point for determining the code area
- DENSO WAVE, Point for setting the module size
- IETF RFC 8439, ChaCha20 and Poly1305 for IETF Protocols
- IETF RFC 9180, Hybrid Public Key Encryption
- NIST SP 800-38D, Recommendation for Galois/Counter Mode and GMAC
- Android Developers, CameraX image analysis



