Three hundred milliseconds is an operating envelope.

In Practice

10 min read

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.

  1. 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.
  2. Render the complete symbol and quiet zone at controlled widths. Record both displayed and captured pixels per module.
  3. Test several display brightness settings against measured low, normal and strong ambient light. Include glare angles relevant to the installation.
  4. Repeat static, lateral-motion and angular-motion passes. Log exposure time when available so blur can be normalized by module pitch.
  5. 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.
  6. Include the oldest supported devices, not only median and flagship phones. Run cold-camera and warm-camera trials.
  7. 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

  1. DENSO WAVE, Information capacity and versions of the QR Code
  2. DENSO WAVE, QR Code error correction feature
  3. DENSO WAVE, Point for determining the code area
  4. DENSO WAVE, Point for setting the module size
  5. IETF RFC 8439, ChaCha20 and Poly1305 for IETF Protocols
  6. IETF RFC 9180, Hybrid Public Key Encryption
  7. NIST SP 800-38D, Recommendation for Galois/Counter Mode and GMAC
  8. Android Developers, CameraX image analysis

Related Articles

Open rugged credential scanner showing its NFC coil, camera module and printed radio antenna

The payload must fit the channel.

A compact signed object needs one deterministic binary form and three explicit transport profiles. QR, NFC and Bluetooth LE fail in different ways when signature and key material cross their byte budgets.

Glass fiber strands converging through a machined metal optical coupler on a pale workbench

A selective proof is not automatically smaller.

When attributes require independent signatures, BBS can replace N signatures with one multi-message signature, but its selective-disclosure proof grows with every hidden message. The useful crossover depends on what the comparison actually carries.

Close-up of an open hardware security module, loose chip packages, a precision caliper and a fiber lead on a pale metrology bench

The signature is not the key.

A byte-level comparison of RSA, elliptic-curve, pairing-based and post-quantum signatures shows when recurring signature traffic overtakes key provisioning and storage.