Standards/fido-hybrid-qr
FIDO Hybrid QR
Overview
The FIDO hybrid QR code is the QR Code a computer shows when a user signs in with a passkey held on another device, usually a phone. Its text is a FIDO:/ URI followed by digits, which encode a small CBOR map holding a public key and a shared secret 1 2. The code carries no web address or account data. It only starts the process: the phone must then prove it is physically close over Bluetooth Low Energy (BLE) before the normal CTAP exchange runs 1.
The mechanism was first called caBLE (cloud-assisted Bluetooth Low Energy), was renamed hybrid in 2022 7, and is defined in CTAP 2.2 and 2.3.
History
- 2019. TechTarget reports that Google had offered caBLE since 2019 10.
- 2020. Chromium's
v2_handshake.cc, which builds and parses today's QR payload, carries a 2020 copyright line 4. - June 2021. CTAP 2.1 listed only USB HID, NFC and BLE bindings, with no hybrid section 13.
- 3 September 2021. Adam Langley of Google registered the
fidoURI scheme with IANA for "forthcoming" FIDO Alliance specifications on cross-device authentication 6. - 5 May 2022. Apple, Google and Microsoft jointly committed to letting users approve a sign-in on a phone for a nearby device, even one running a different operating system or browser 11. TechTarget named caBLE as the protocol they would use 10.
- 2022. At WWDC22, Apple described the QR and Bluetooth flow as part of the standards behind passkeys 12.
- 24 June 2022. Langley's WebAuthn change added the transport string
hybrid, noting that FIDO had chosen the name for "the transport formerly known as caBLE". It was merged on 27 July 2022 7 8. - 14 July 2025. CTAP 2.2 reached Proposed Standard with the hybrid transports in section 11.5 1.
- 26 February 2026. CTAP 2.3 added BLE as an optional data channel beside WebSockets 2 14.
Technical specification
Carrier. An ordinary QR Code. The hybrid sections reviewed for this page give no symbol size or error-correction level 1.
Payload
The text is FIDO:/ plus digit-encoded CBOR. The specification writes the scheme in uppercase and requires a single slash, because a double slash would imply an authority, which this scheme does not have 1. Chromium's parser accepts the prefix in either case 4.
The decoded data is a canonical CBOR map with integer keys 1 2:
| Key | Type | Required | Meaning |
|---|---|---|---|
| 0 | 33 bytes | yes | Compressed P-256 public key that authenticates the displaying device |
| 1 | 16 bytes | yes | Random QR secret |
| 2 | integer | yes | Number of assigned tunnel server domains the implementation knows (two are listed) |
| 3 | integer | no | Current time, in seconds since the epoch |
| 4 | boolean | no | true if the displaying device supports state-assisted transactions |
| 5 | text | yes | Flow hint: ga (sign-in), mc (credential creation), dcp (Digital Credentials presentation) or dci (issuance). Unknown values count as ga |
| 6 | array | no | Data channels, from CTAP 2.3: 0 is WebSockets, 1 is BLE. If absent, WebSockets only |
The Required column follows the specification's text. Chromium's parser is looser: it insists only on keys 0 and 1 4. Encoders may add a random GREASE key, 65535, so that parsers stay tolerant of unknown keys 1. libwebauthn leaves key 6 out for legacy peers, and omits key 4 rather than writing false 25.
Digit encoding
The bytes are split into 7-byte chunks. Each chunk is read as a little-endian integer and written as a zero-padded 17-digit decimal number. A trailing 1 to 6 bytes take 3, 5, 8, 10, 13 or 15 digits 1 4. The specification says only that the encoding is "designed to be efficient when expressed in a QR code" 1.
Why digits fit QR well. QR numeric mode stores three digits in 10 bits and two digits in 7 29, so a 17-digit chunk costs 57 bits to carry 56 bits of data (our calculation): about 1.8 % overhead.
Illustrative payload
The CTAP text gives no sample QR string. The string below is structurally illustrative only. It was computed for this page with an all-zero X coordinate, a counting secret and a fixed timestamp, so it is not a working key and belongs to no device:
FIDO:/000000091493500540000000000000000000000000000000000000000000000000000000000000000000000564050807291904025421010491811870057950297627316200231212771312386107096654083332
It decodes to these 69 bytes of CBOR, with keys 0 to 5 in order:
a6 00 5821 02 00…00 01 50 000102…0f 02 02 03 1a 6b49d200 04 f5 05 62 6761
Size in a QR code
The figures here are our calculation, not a specification limit.
With keys 0 to 5, the payload is 69 bytes, or 168 digits, for 174 characters of text. Without the optional keys 3 and 4 it is 61 bytes and 155 characters.
| Encoding of the 174 characters | Bits | Smallest version at L |
|---|---|---|
FIDO:/ in alphanumeric, digits in numeric |
620 | 4 (33 × 33) |
| All alphanumeric | 970 | 6 (41 × 41) |
| All byte | 1,404 | 8 (49 × 49) |
The calculation uses the mode and count-indicator sizes for versions 1 to 9 30, QR's 11 bits per alphanumeric pair 31, and the data-codeword totals 32. Every character of FIDO:/ is in the alphanumeric set, which includes : and / 33. In the mixed form, version 4 fits at level L, version 5 (37 × 37) at M, version 7 at Q and version 8 at H 32. Each version adds four modules per side 34. This page could not establish which modes or levels shipping browsers use.
After the scan
- The phone derives keys from the QR secret with HKDF-SHA256 and broadcasts an encrypted 20-byte BLE advertisement under service UUID
0000fff9-0000-1000-8000-00805f9b34fb1. - The computer, scanning for that UUID, decrypts the advertisement to get a connection nonce, a routing ID and a tunnel server ID 1.
- Both devices join a WebSocket tunnel at
wss://<domain>/cable/connect/<routing ID>/<tunnel ID>. The assigned domains arecable.ua5v.comandcable.auth.com1. A third-party library says Google runs the first and Apple the second 24. - A Noise handshake (KNpsk0, with P-256, SHA-256 and AES-256-GCM) secures the tunnel, and the CTAP messages run inside it 1. Apple says the relay server "can't see anything that's going on" 12.
- With CTAP 2.3, the devices may skip the tunnel and use an L2CAP channel over BLE. WebSockets should stay available as a fallback 2.
The phone can also send linking data, so later sign-ins from the same computer can start with a state-assisted transaction and no QR code 1. Support for this is signalled by key 4.
Use cases
- Passkey sign-in across devices. The core use. On Windows 11 23H2 or later the user picks an iPhone, iPad or Android device, then scans the code. Microsoft requires Bluetooth and internet on both devices 16. Google states that the phone must be near the laptop and the user must approve on the phone 17.
- Creating a passkey from another device. The
mchint covers registration 1, which Thales documents for its Android SDK 18. - Third-party passkey providers. On Android 14 and later, the system camera scans the code and hands the request to the chosen credential provider 18. The Microsoft Authenticator camera scans these codes on Android but not on iOS, where the system camera is required 16.
- Digital credentials. The
dcpanddcihints carry Digital Credentials API presentation and issuance across devices 1. - Enterprise sign-in. Microsoft Entra ID documents the flow for passkeys held in Microsoft Authenticator 16.
Where a screen is missing, the QR step does not work. Meta has described a method for XR headsets that bypasses QR codes while keeping the proximity requirement 19.
Security
The code is not a credential. Its key pair is single-use, and Apple notes that a code sent by email or generated on a fake website "won't work", because a remote attacker cannot receive the Bluetooth advertisement 12. CTAP states that the proximity proof exists "to help prevent attacks" 1.
PoisonSeed (July 2025). Expel reported that attackers had relayed a real QR code to a phished user to get past a FIDO key. It then retracted the claim on 25 July 2025: the logs showed that all later MFA challenges failed, and it accepted that a properly implemented flow without proximity times out 20.
The IETF's draft on cross-device flows, draft 15 of January 2026, says FIDO cross-device authentication proves proximity through BLE advertisements, which greatly reduces exposure to the attacks it catalogues. It recommends the approach where devices support it 21.
Implementations
| Project | Lang | Stars | Last active | Notes |
|---|---|---|---|---|
| chromium/chromium | C++ | ~25.2k | 2026-10 | qr::Encode and qr::Parse in device/fido/cable/v2_handshake.cc 4 28 |
| kanidm/webauthn-rs | Rust | ~0.7k | 2026-10 | webauthn-authenticator-rs implements both roles. Its authors call it incomplete and not crypto-reviewed 24 27 |
| linux-credentials/libwebauthn | Rust | ~0.6k | 2026-10 | Linux platform library that builds the QR code, with caBLE v2 and CTAP 2.3 BLE-only hybrid 25 26 |
No maintained standalone FIDO:/ decoder was found, and no Python implementation turned up in this search. Any general QR reader returns the text, but acting on it needs the full protocol.
Comparison
- Hybrid QR vs SMART Health Cards. Both turn data into digits to use QR numeric mode. SMART Health Cards write each character as two digits, because a JWS character holds about 6 bits 23. FIDO packs raw bytes at 17 digits per 7 bytes 1. A SMART Health Card is the credential itself, while a FIDO code holds only single-use keys 12.
- Hybrid QR vs OAuth device flow (RFC 8628). In the device flow, a user approves a request in a browser on another device, and a QR code can carry the verification link 22. The IETF draft says pairing FIDO cross-device authentication with the Authorization Code Grant and PKCE avoids the device flow's risks 21. Choose hybrid when both devices have BLE and internet access 21.
- Hybrid vs a USB or NFC security key. Those have their own CTAP bindings 13. Hybrid needs no extra hardware when the user already holds a phone with a passkey, but it needs Bluetooth and, usually, internet on both devices 16.
Fun facts
- The
fidoregistration names Adam Langley, and its reference field cites an unrelated-looking draft on SSH URIs,draft-ietf-secsh-scp-sftp-ssh-uri6. The scheme is still only provisional 5. - The old name survives in today's specification: the WebSocket subprotocol is
fido.cable, and the state-assisted header isX-caBLE-Client-Payload1. - The
webauthn-authenticator-rsdocumentation still says no public specification exists and that Chromium's C++ source is the only reference 24, although CTAP 2.2 has since published it 1.
Status
Active, with a rename pending. CTAP 2.3 is the current Proposed Standard 2. WebAuthn Level 3, a W3C Recommendation of 25 August 2026, defines the hybrid transport value 9.
Per passkeys.dev (updated 21 September 2026), Android 9+ and iOS/iPadOS 16+ can act as the scanning authenticator. Clients include Windows 23H2+, macOS 13+ with Chrome or Edge, and Chrome OS 108+. The table's flattened layout makes the row alignment slightly ambiguous 15.
BLE data transfer in CTAP 2.3 needs support on both the initiating platform and the phone 14.
Sources
1 Client to Authenticator Protocol (CTAP) 2.2, Proposed Standard — FIDO Alliance, 2025 2 Client to Authenticator Protocol (CTAP) 2.3, Proposed Standard — FIDO Alliance, 2026 4 device/fido/cable/v2_handshake.cc — The Chromium Authors, accessed 2026 5 Uniform Resource Identifier (URI) Schemes — IANA, accessed 2026 6 Provisional URI scheme registration: fido — IANA, 2021 7 public-webauthn: commit adding the hybrid transport — W3C mailing list archive, 2022 8 public-webauthn: merge of PR #1755 — W3C mailing list archive, 2022 9 Web Authentication Level 3 — W3C, 2026 10 Apple, Microsoft, Google expand FIDO2 passwordless support — TechTarget, 2022 11 Apple, Google and Microsoft commit to expanded support for FIDO standard — FIDO Alliance, 2022 12 Meet passkeys, WWDC22 — Apple Developer, 2022 13 Client to Authenticator Protocol (CTAP) 2.1, Proposed Standard — FIDO Alliance, 2021 14 CTAP 2.3: Protocol Refinements and PIN Complexity Improvements — Yubico, accessed 2026 15 Device Support — passkeys.dev, 2026 16 Sign in with passkeys in Authenticator for Android and iOS devices — Microsoft Learn, 2026 17 Passkeys use cases — Google for Developers, 2025 18 Android hybrid transport — Thales (vendor), accessed 2026 19 No Display? No Problem: Cross-Device Passkey Authentication for XR Devices — Meta Engineering, via FIDO Alliance, 2026 20 Threat actors try to downgrade FIDO2 MFA auth in PoisonSeed phishing attack — BleepingComputer, 2025 21 Cross-Device Flows: Security Best Current Practice, draft 15 — IETF, 2026 22 RFC 8628: OAuth 2.0 Device Authorization Grant — IETF, 2019 23 SMART Health Cards Framework — SMART Health Cards, accessed 2026 24 webauthn_authenticator_rs::cable — Kanidm project, accessed 2026 25 libwebauthn 0.5.0: qr_code_device.rs — docs.rs, accessed 2026 26 linux-credentials/libwebauthn — GitHub, accessed 2026 27 kanidm/webauthn-rs — GitHub, accessed 2026 28 chromium/chromium — GitHub, accessed 2026 29 Numeric Mode Encoding — Thonky.com, accessed 2026 30 Data Encoding — Thonky.com, accessed 2026 31 Alphanumeric Mode Encoding — Thonky.com, accessed 2026 32 Error Correction Code Words and Block Information — Thonky.com, accessed 2026 33 Alphanumeric Table — Thonky.com, accessed 2026 34 Information capacity and versions of QR Code — Denso Wave, accessed 2026
Deployments
No country reports mention this standard by name.
Regions / aggregations not mapped to a single country
- Universal