FreeThe +45-page Authentication Analytics Whitepaper — measuring real login journeysDownload
Back to Overview

Security Key Capabilities: CTAP Feature Comparison

Which security key supports PRF, credProtect, largeBlob and how many passkeys? A capability reference for 325 FIDO2 keys, built from CTAP getInfo.

Vincent Delitz
Vincent Delitz

Created: August 24, 2026

Updated: August 24, 2026

Security Key Capabilities: CTAP Feature Comparison
Key Facts
  • The capability data for security keys is public. The FIDO Alliance Metadata Service ships the authenticatorGetInfo response of every certified key. All numbers here come from its 325 roaming FIDO2 authenticators.
  • hmac-secret, the basis for WebAuthn PRF, is almost universal at 94%. credProtect sits at 76%, credBlob at 46% and largeBlob at 41%. Only 59% declare CTAP 2.1.
  • Storage capacity is where the field differs most. Discoverable credential slots range from 6 to 662, median 100.
  • bioEnroll: false does not mean the key has no fingerprint sensor. For options a user sets up, false means supported but not configured yet.
  • maxCredentialCountInList caps credential IDs per request, usually at 8. Nine HID Crescendo variants cap it at 1, so 20 credentials mean 20 requests.

1. Datasheets do not tell you which CTAP features a security key supports#

A product page gives you the price, the form factor and the words "FIDO2 certified". It does not tell you whether the key can serve PRF, how many passkeys fit on it or what happens when your allowCredentials list gets long. Those answers decide whether your login works on the hardware your users already carry. So developers keep asking us which manufacturer implements which CTAP and WebAuthn feature.

The answer is public. Every FIDO2 authenticator describes itself in a CTAP command called authenticatorGetInfo: protocol versions, extensions, options, credential capacity, PIN policy and transports. The FIDO Alliance publishes that response for every authenticator listed in its Metadata Service.

This article turns that data into a reference. It covers all 325 roaming authenticators in the BLOB, with a comparison table for the keys that teams deploy most often, the numbers across the whole field and the rules you need to read those numbers correctly.

Debugger Icon

Experiment with passkey flows in the Passkeys Debugger.

Try for Free

If you are choosing hardware rather than building against it, our best FIDO2 hardware security keys article is the better starting point. It sorts keys by price, form factor and protocol support.

2. Where the numbers in this article come from#

2.1 What authenticatorGetInfo returns#

authenticatorGetInfo (command 0x04) is the first thing a client sends to a FIDO2 authenticator. It happens inside the browser or the platform, over USB or NFC, before your navigator.credentials call reaches the key. The answer is a CBOR map that describes the device, and the client uses it to decide what it is allowed to ask for.

Step 5 happens where you cannot see it. The browser knows which key is connected. Your relying party does not. If the key does not list hmac-secret, the browser never asks it for PRF, whatever your code requested, and you get back a credential with no PRF result and no error to log. credMgmt works the same way: a management tool that finds no such option just shows no delete button.

This is also the limit of any capability table, including the ones further down. A table tells you what a model can do. To find out which models your users actually hold, you need the AAGUID from your own ceremonies. Section 9 comes back to that.

Here is such a response, taken from the metadata record of a YubiKey 5 with NFC on firmware 5.8. We left out a few operational fields, but everything this article discusses is in there:

{ "versions": ["U2F_V2", "FIDO_2_0", "FIDO_2_1_PRE", "FIDO_2_1", "FIDO_2_2"], "extensions": [ "credProtect", "hmac-secret", "largeBlobKey", "credBlob", "minPinLength", "hmac-secret-mc", "thirdPartyPayment" ], "aaguid": "f4ce5fc057d346f5a736efb7d5bc63b5", "options": { "plat": false, "rk": true, "clientPin": false, "up": true, "pinUvAuthToken": true, "largeBlobs": true, "credMgmt": true, "setMinPINLength": true, "makeCredUvNotRqd": true, "alwaysUv": false }, "maxMsgSize": 1536, "pinUvAuthProtocols": [2, 1], "maxCredentialCountInList": 8, "maxCredentialIdLength": 128, "transports": ["nfc", "usb", "smart-card"], "algorithms": [ { "type": "public-key", "alg": -7 }, { "type": "public-key", "alg": -8 }, { "type": "public-key", "alg": -35 } ], "maxSerializedLargeBlobArray": 4096, "minPINLength": 4, "firmwareVersion": 329728, "maxCredBlobLength": 32, "remainingDiscoverableCredentials": 100 }

A handful of these values decide how your login behaves:

  • hmac-secret for PRF
  • credProtect for credential privacy
  • largeBlobs and credBlob for extra bytes stored next to a credential
  • remainingDiscoverableCredentials for how many passkeys still fit
  • maxCredentialCountInList for how long your allowCredentials list may be
  • credMgmt for whether a user can delete anything
  • alwaysUv and minPINLength for policy enforced on the key
  • transports for how the key can be reached

The rest of this article goes through them one by one. Vendor datasheets summarise the same response, so we use the response itself.

2.2 FIDO Metadata Service publishes that response for 325 keys#

The FIDO Alliance Metadata Service distributes a signed JWT with one metadata statement per listed authenticator, keyed by AAGUID. For CTAP2 authenticators that statement contains the authenticatorGetInfo response the vendor submitted.

The snapshot used here is BLOB number 276, valid until 2026-09-01:

  • 507 entries in total, covering FIDO2, U2F and UAF authenticators
  • 337 entries contain an authenticatorGetInfo block
  • 12 of those are platform authenticators (plat: true)
  • 325 roaming authenticators remain, each with its own AAGUID

Of those 325, 257 carry a FIDO certification in their status report. 68 do not, and the BLOB lists them anyway with NOT_FIDO_CERTIFIED as their latest status. All Ledger models are in that group, together with several preview firmware entries. We kept them in, because a key that ships and gets deployed affects your integration either way. That is also why this article talks about "325 authenticators in the Metadata Service" and never about "325 certified keys". Dropping the 68 changes very little: hmac-secret goes from 94% to 95%, credProtect from 76% to 79%, CTAP 2.1 from 59% to 61%.

One product family often occupies many AAGUIDs. Yubico, Feitian and others assign a separate AAGUID per firmware generation, per FIPS or CCN variant and per consumer or enterprise profile. Search the BLOB for "YubiKey 5" and "NFC" and you get 24 records, from firmware 5.4.2 up to 5.8.0. That is why the tables in this article collapse a product family into one row and use the record with the highest authenticatorVersion, and why the percentages below count records rather than products sold.

2.3 What this data cannot tell you#

Three limitations apply to every row in the tables below:

  • It is a snapshot from submission. A key that gained largeBlob support in a later firmware keeps its old capability set until the vendor submits a new record. The Nitrokey 3 entry reports largeBlobs: false, which describes the firmware it was submitted with, not the one shipping today.
  • A missing field is not a missing feature. Older records were captured with tooling that left out fields such as transports or remainingDiscoverableCredentials. We mark those as "n/r" for not reported, never as "no".
  • Keys that were never submitted are not in the BLOB. Parts of the Token2 range are missing or show up only with an older model. That says nothing about their quality.

Section 6 collects the models whose record is too thin for the main table.

3. How to read the options map#

3.1 Missing, false and true mean three different things#

The CTAP options map has three states:

  • Option missing: the authenticator does not support the feature
  • Option set to false: depends on the option, see below
  • Option set to true: supported and active

The middle state causes most of the confusion, because CTAP uses it for two different things.

Configuration options describe something the user sets up, so false means "supported, but not configured yet". This covers clientPin, uv, bioEnroll, uvBioEnroll, ep and alwaysUv. A boolean that means "supported, but switched off" is unusual, so most readers treat false as a plain no. The data then becomes wrong in one specific direction: every feature that a user configures looks unsupported across the whole field.

Support-only options have no configuration state, so false means exactly what it looks like: not supported. This covers rk, credMgmt, largeBlobs, pinUvAuthToken, setMinPINLength and makeCredUvNotRqd. It stays rare in the data, because a vendor that does not support a feature usually leaves the option out: 4 records report rk: false, 4 report credMgmt: false and 7 report largeBlobs: false. We count those as no throughout this article.

So for clientPin, uv, bioEnroll, ep and alwaysUv, false means "can, but has not". Everywhere else it means "cannot".

3.2 Example: YubiKey Bio reports bioEnroll false#

Every YubiKey Bio entry in the metadata carries bioEnroll: false together with uv: false and uvModality: 2. Taken at face value that says a fingerprint key has no fingerprint.

The sensor exists, uvModality: 2 identifies it as an internal fingerprint sensor and the sample used for the submission had no fingerprint enrolled. The same pattern appears on clientPin: false, which every YubiKey record carries and which means "PIN supported, none set yet".

Across the 325 keys, 45 report a bioEnroll option and only 9 report it as true. The useful number here is 45.

4. The capabilities one by one#

4.1 CTAP version#

versions lists the protocol versions a key speaks. Almost every key speaks CTAP 2.0 (322 of 325). CTAP 2.1 brought credential management, largeBlob, minPinLength and alwaysUv, and only 193 keys (59%) declare it. Another 170 declare FIDO_2_1_PRE, the pre-standard draft with a smaller command set and different command numbers, so it should not be counted as CTAP 2.1.

CTAP 2.2 has started to arrive. Nine keys declare FIDO_2_2 and 20 declare a FIDO_2_3 string. All of them are Yubico firmware 5.8 records plus one Feitian biometric card, and the same records are the only ones with the newer hmac-secret-mc and thirdPartyPayment extensions.

4.2 hmac-secret and WebAuthn PRF#

WebAuthn PRF lets an application derive a stable symmetric key from a passkey, which is the basis for end-to-end encrypted products. On a roaming authenticator, PRF is served by the CTAP hmac-secret extension.

306 of 325 keys (94%) support hmac-secret, including keys submitted years ago. If your feature needs PRF from a security key, the hardware will rarely be what holds you back. Browser and platform support usually will.

One restriction sits underneath that number. Plain hmac-secret only produces a result during authentication, so a registration ceremony cannot hand you the key material. hmac-secret-mc lifts that restriction, and 20 of 325 keys support it: current Yubico firmware and one Feitian card. An enrollment flow that expects a PRF output at registration time therefore works on roughly 6% of the listed authenticators today.

4.3 credProtect#

credProtect sets a policy per credential for whether the credential may be used without user verification. It is the mechanism that keeps a discoverable credential from revealing that it exists. We described the browser behaviour and Chrome's escalation rules in WebAuthn credProtect on security keys.

247 of 325 keys (76%) support it, and the gap splits cleanly along protocol generations: none of the 78 records without credProtect declares CTAP 2.1. They are all CTAP 2.0-era entries, among them the Ledger models, SoloKeys and OpenSK, the older Security Key by Yubico and several enterprise smartcards. The reverse does not hold, so do not use CTAP 2.0 as a shortcut. The Google Titan v2 record stops at CTAP 2.0 and lists credProtect anyway, which is why the table in section 6 marks it yes.

4.4 largeBlob and credBlob#

Both store additional bytes next to a credential, but they are not interchangeable:

  • credBlob puts a small blob inside the credential, limited by maxCredBlobLength. 150 keys (46%) support it and 122 of them cap it at exactly 32 bytes, which is enough for an identifier and not enough for a certificate.
  • largeBlob stores a compressed per-credential blob in a separate array, sized by maxSerializedLargeBlobArray. 134 keys (41%) declare the largeBlobKey extension and 133 report largeBlobs as true. The array holds 4096 bytes on current Yubico firmware, 2048 bytes on Token2 PIN Plus and Thetis Pro and 1024 bytes on Feitian BioPass Pro and Hyper FIDO Pro.

An SSH certificate that fits into the 4096 bytes on a YubiKey will not fit into a 1024-byte array.

4.5 Capacity for discoverable credentials#

A discoverable credential makes usernameless login possible and occupies a physical slot on the key. remainingDiscoverableCredentials reports how many slots were free on the submitted sample, which for a factory-reset key is the total number.

150 keys report the field. The median is 100, the range goes from 6 to 662, so the largest key holds 110 times as much as the smallest:

The same values as a table:

KeyReported slots
OneSpan DIGIPASS FX1-C662
OneSpan DIGIPASS FX7-C368
Swissbit iShield Key 2300
GoldKey Security Token256
Thetis Pro FIDO2200
Feitian BioPass FIDO2 Pro, Hyper FIDO Pro128
YubiKey 5 (firmware 5.7 and 5.8)100
Token2 PIN Plus, Taglio CTAP2.1 BIO50
HID Crescendo Key V330
YubiKey Bio (records before 5.8)25

Non-discoverable credentials work differently and are practically unlimited, because the credential is wrapped into the credential ID and nothing stays on the key. For a workforce that registers on dozens of relying parties, that design choice usually decides whether users run into a limit at all. We compare both models in resident keys and discoverable credentials.

PasskeysCheatsheet Icon

Passkeys Cheatsheet. Practical guidance, rollout patterns and KPIs for passkey programs.

Get Cheat Sheet

4.6 Credential management on the key#

credMgmt allows a user to list and delete the credentials stored on a key, which is the only way to free a slot without a factory reset. credMgmt is a support-only option, so the count that matters is the 193 keys (59%) that report it as true. Four more carry credMgmt: false, which per section 3.1 means no support. Another 164 expose only the pre-standard credentialMgmtPreview, which most tools handle as well, under different command numbers.

Where credential management is missing, "my key is full" has exactly one answer, and that answer deletes every credential on the key. Our guide on deleting a passkey from a YubiKey shows the supported path.

4.7 Bio enrollment#

46 keys expose a bio option (bioEnroll or uvBioEnroll), which is 14% of the field. Read with the rule from section 3.1, that is how many keys have a fingerprint sensor. uvModality: 2 marks an internal fingerprint sensor and appears on almost all of them.

There are two variants. bioEnroll means enrollment happens on the key itself. uvBioEnroll means that enrollment is allowed through a pinUvAuthToken, which is what most current biometric keys from Feitian, Thales, OneSpan and ACS report.

4.8 PIN policy, enterprise attestation and always-UV#

These are the enterprise controls, and they are the thinnest part of the data:

  • setMinPINLength (enforce a minimum PIN length): 170 keys, 164 of them reporting true. The default minPINLength is 4 on 141 keys, 6 on 33 and 8 on 11.
  • alwaysUv (require user verification for every operation): present on 170 keys, true on only 51, because this is a setting rather than a capability.
  • ep (enterprise attestation, which returns a uniquely identifying attestation to a permitted relying party): present on 51 keys, true on 14. An administrator switches it on per key, so false is the expected value on a factory sample.
  • pinUvAuthProtocols: 193 keys support both protocol versions 1 and 2, 96 support only version 1, 6 support only version 2 and 30 report none.

4.9 Transports#

244 keys report a transports array: USB on 198, NFC on 132, smart-card on 20, BLE on 17 and Lightning on 8. Yubico firmware 5.8 records now also list smart-card, which is how the key presents itself to iOS and Android through the built-in reader path.

For smartcard form factors the transport list decides the rollout, because an NFC-only card cannot be enrolled on a desktop without a reader.

5. Comparison table: current CTAP 2.1 security keys#

5.1 Which keys are in the table and why#

193 records declare CTAP 2.1, but they are not 193 products. They carry 168 distinct product names, and those collapse much further once firmware, FIPS, CCN and profile variants are merged into the model you can actually order. The 16 rows below are that set, picked by three rules:

  • One row per product family, using the entry with the highest authenticatorVersion. Without that step Yubico alone would fill a third of the table.
  • CTAP 2.1 declared, because those are the records that carry the blob, capacity and policy fields at all. The CTAP 2.0 models that are still widely deployed get their own table in section 6.
  • Available to buy today, dropping preview, RC and discontinued records.

"n/r" means the field is not reported, which is not the same as unsupported.

KeyCTAPhmac-secret (PRF)credProtectlargeBlobcredBlobDiscoverable slotsmaxCredentialCountInListTransports
YubiKey 5 with NFC (fw 5.8)2.0 / 2.1 / 2.2yesyesyes, 4096 Byes, 32 B1008USB, NFC, smart-card
Security Key NFC by Yubico (fw 5.8)2.0 / 2.1 / 2.2yesyesyes, 4096 Byes, 32 B1008USB, NFC, smart-card
YubiKey Bio, FIDO Edition (fw 5.8)2.0 / 2.1yesyesyes, 4096 Byes, 32 B1008USB, smart-card
Feitian ePass FIDO2-NFC (CTAP 2.1)2.0 / 2.1yesyesyes, size n/ryes, size n/rn/r6USB, NFC
Feitian BioPass FIDO2 Pro2.0 / 2.1yesyesyes, 1024 Byes, 32 B12810USB
Token2 PIN Plus Series2.0 / 2.1yesyesyes, 2048 Byes, 32 B508USB, NFC
Thetis Pro FIDO22.0 / 2.1yesyesyes, 2048 Byes, 32 B2008USB, NFC
Swissbit iShield Key 22.0 / 2.1yesyesnoyes, 32 B300n/rUSB, NFC
OneSpan DIGIPASS FX72.0 / 2.1yesyesyes, 2008 Byes, 64 B1398USB
Hyper FIDO Pro (CTAP 2.1)2.0 / 2.1yesyesyes, 1024 Byes, 32 B12810USB
GoTrust Idem Key mini2.0 / 2.1yesyesyes, 4096 Byes, 32 B508USB
Nitrokey 3 AM2.0 / 2.1yesyesnonon/r10USB
HID Crescendo Key V32.0 / 2.1yesyesnono301USB, NFC
ACS PocketKey+ Bio2.0 / 2.1yesyesnoyes, 64 Bn/r5USB, NFC
Taglio CTAP2.1 BIO (card)2.0 / 2.1yesyesyes, 2048 Byes, 128 B50n/rNFC
Ensurity AUTH BioPro2.1yesyesnonon/r10USB

The Yubico rows also declare a FIDO_2_3 version string next to CTAP 2.2. That is a draft label and not a published standard version, so the table lists the standardised versions only.

5.2 Reading across the rows#

The metadata gives you these values one AAGUID at a time. Side by side, four things show up that you cannot see in a single record:

  • PRF and credProtect are a solved problem on current hardware. Every row supports hmac-secret and credProtect. The differences start at largeBlob, which five of these models do not report at all, among them the Swissbit iShield Key 2 and the HID Crescendo Key V3.
  • "Supports largeBlob" covers very different sizes. Among CTAP 2.1 keys the reported capacity is 1024, 1978, 2008, 2048, 4056 or 4096 bytes. What fits into 4096 bytes on a YubiKey runs out of room on a Feitian BioPass at 1024. credBlob spreads the same way, from 32 to 256 bytes.
  • Capacity has little to do with price or brand. Inside this table it ranges from 30 to 300 slots, and the two keys at the top, Swissbit and Thetis, are rarely the ones a workforce rollout standardises on.
  • One row needs different client behaviour. The HID Crescendo Key V3 reports a maxCredentialCountInList of 1, so a client has to send one request per credential, see section 7.3.

The Nitrokey 3 row needs a warning in the other direction. Its record is the clearest case of a metadata snapshot lagging behind shipped firmware, so its blob columns mean "not in the submitted record" and not "cannot do this".

Ben Gould Testimonial

Ben Gould

Head of Engineering

I’ve built hundreds of integrations in my time, including quite a few with identity providers and I’ve never been so impressed with a developer experience as I have been with Corbado.

10,000+ devs trust Corbado & make the Internet safer with passkeys. Got questions? We've written 150+ blog posts on passkeys.

Join Passkeys Community

6. Keys whose record stops at CTAP 2.0#

These models are widely deployed, but their metadata entry predates the CTAP 2.1 reporting fields. Each row describes the record the vendor submitted, which can differ from what the key in your drawer does today. Check them with the key in hand, see section 8, before you design against them.

KeyCTAP declaredhmac-secretcredProtectNotes from the record
Google Titan Security Key v22.0yesyesNo CTAP 2.1 options, no transports and no capacity reported
Token2 FIDO2 Security Key2.0 / 2.1-PREyesyesOnly credentialMgmtPreview, newer Token2 models are in the table above
eWBM eFA3202.0 / 2.1-PREyesyesReports uv: true, preview credential management only
Kensington VeriMark Guard2.0 / 2.1-PREyesyesFingerprint key, reports uv: true, list cap 20
uTrust FIDO2 Security Key2.0yesnoMinimal record, no options beyond PIN and RK
SafeNet eToken Fusion2.0yesnoMinimal record, newer eToken Fusion variants report much more
SoloKeys Solo, OpenSK2.0yesnoOpen-source firmware, records are old
Ledger Flex, Ledger Stax2.0yesnoNot FIDO certified, rk: false on both records

rk: false on both Ledger models means the device cannot store a discoverable credential at all, so it will never serve a usernameless login. That is a real limitation, not a reporting gap.

7. The picture across the whole field#

7.1 Extension support across 325 authenticators#

The same numbers with the absolute counts:

CapabilityKeysShare
hmac-secret (PRF)30694%
credProtect24776%
minPinLength15347%
credBlob15046%
largeBlobKey13441%
hmac-secret-mc206%
thirdPartyPayment206%
CTAP 2.0 declared32299%
CTAP 2.1 declared19359%
CTAP 2.2 declared93%
U2F fallback24375%

Teams usually assume PRF is the exotic capability and that credential storage comes with every key. It is the other way round. PRF is the safest thing on this list to build on, while the blob and management features that make an enterprise rollout comfortable sit below 50%.

Signature algorithms show the same concentration: ES256 (COSE -7) on 231 keys, EdDSA (-8) on 93, ES384 (-35) on 78 and RS256 (-257) on 6. Leave -7 out of pubKeyCredParams and you lock out most of the field.

7.2 Capacity varies the most#

Only 150 of 325 keys report their capacity at all. For the other 175 the metadata will not carry a rollout with discoverable credentials and you have to measure. Among the keys that do report, the values cluster tightly around 100:

69 of those 150 report exactly 100 slots, which has become the de facto standard for the mid-range. 8 keys stop below 26 slots and 12 go past 200, so a rollout sized on the median breaks at both ends.

7.3 maxCredentialCountInList and long allowCredentials lists#

maxCredentialCountInList limits how many entries the authenticator accepts in one allowCredentials list. 222 keys report it and the values sit close together, with one group of outliers that causes the trouble:

The nine keys with a limit of 1 are all HID Crescendo variants. 8 is the value for roughly half of the field.

If a relying party sends more credential IDs than the limit allows, the client cuts the list into chunks of that size and sends one authenticatorGetAssertion per chunk. Nothing gets dropped, it simply takes several requests. Over USB nobody notices. Over NFC each request is another tap on the reader, so on a key with a limit of 1 a list of 20 credentials means 20 taps before the user sees any result.

Only a shorter list fixes this. Send an empty allowCredentials and rely on discoverable credentials, or reduce the list on the server to the credentials that plausibly belong to this user and this transport.

Substack Icon

Subscribe to our Passkeys Substack for the latest news.

Subscribe

8. How to check a key yourself#

The metadata tells you what a vendor submitted. Only the key in your hand tells you what is installed on it. Two commands are enough for that.

Start with fido2-token from libfido2, on macOS via brew install libfido2. It speaks plain CTAP over HID and therefore reads any FIDO2 key, whoever made it. First list what is connected. On macOS the device path is an ioreg:// handle, on Linux it is a /dev/hidraw* node:

$ fido2-token -L ioreg://4296123542: vendor=0x1050, product=0x0407 (Yubico YubiKey OTP+FIDO+CCID)

Then read the getInfo response from that path. This is a YubiKey 5 NFC that has been in daily use for a while:

$ fido2-token -I ioreg://4296123542 proto: 0x02 major: 0x05 minor: 0x04 build: 0x03 caps: 0x05 (wink, cbor, msg) version strings: U2F_V2, FIDO_2_0, FIDO_2_1_PRE extension strings: credProtect, hmac-secret transport strings: nfc, usb algorithms: es256 (public-key), eddsa (public-key) aaguid: 2fc0579f811347eab116bb5a8db9202a options: rk, up, noplat, clientPin, credentialMgmtPreview fwversion: 0x50403 maxmsgsiz: 1200 maxcredcntlst: 8 maxcredlen: 128 maxcredblob: 0 maxlargeblob: 0 minpinlen: 4 pin protocols: 2, 1 pin retries: 8

On a YubiKey, ykman adds the state a user cares about:

$ ykman fido info AAGUID: 2fc0579f-8113-47ea-b116-bb5a8db9202a PIN: 8 attempt(s) remaining Minimum PIN length: 4

Note that ykman finds Yubico hardware only, because it filters the USB device list on Yubico's vendor ID. For a Feitian, Token2 or HID key you need fido2-token.

8.1 Comparing that output against the metadata#

Look up the AAGUID 2fc0579f-8113-47ea-b116-bb5a8db9202a in the BLOB and you get "YubiKey 5 Series with NFC". Line by line the two agree: the same two extensions, the same maxCredentialCountInList of 8, the same transports, the same algorithms. Two fields differ, and both differences are the ones this article warned about:

  • firmwareVersion. The record says 328706, the key says 0x50403. Yubico encodes the version as major, minor and patch bytes, so that is 5.4.2 in the metadata against 5.4.3 in the hand. The same encoding makes 329476 firmware 5.7.4 and 329728 firmware 5.8.0.
  • clientPin. The record says false, this key lists clientPin in its options and reports 8 PIN attempts remaining. That is exactly the section 3.1 rule at work: the submitted sample had no PIN set, this one does.

The output also shows where the capability tables run out. This key declares FIDO_2_1_PRE instead of FIDO_2_1, so it reports maxcredblob: 0, maxlargeblob: 0 and no capacity at all. Nothing is broken here. It is a working CTAP 2.0-era key, and it belongs to the 41% that contribute nothing to the largeBlob and remainingDiscoverableCredentials numbers above.

If you cannot plug the key in, the AAGUID from an attestation statement is enough to find its metadata entry. That is also how a relying party identifies hardware in production.

9. What this means for Relying Parties#

Four decisions follow from this data alone, without any vendor preference:

  • Rely on PRF, plan around largeBlob. At 94% against 41%, hmac-secret is a safe dependency while largeBlob needs a graceful fallback. If your enrollment flow needs a PRF result at registration time, treat hmac-secret-mc as a small minority and keep a path that derives the key during authentication.
  • Keep allowCredentials short. The limit is 8 on half of the field and 1 on some enterprise cards, so a long list becomes a latency problem as soon as the wrong hardware shows up.
  • Do not treat capacity as unlimited. 30 slots and 662 slots are both normal values, and a workforce rollout that assumes the upper end produces support tickets that read as "my key stopped working".
  • Choose userVerification deliberately. credProtect behaves differently across browsers, as we documented in the credProtect article. CTAP 2.1 keys let you enforce policy on the key itself with alwaysUv and minPinLength, but only the 59% that declare CTAP 2.1.

A datasheet answers none of these questions and the metadata answers most of them. The last one it cannot answer is which AAGUIDs actually show up in your traffic and which of them fail. You only get that from production.

StateOfPasskeys Icon

See how many people actually use passkeys.

View Adoption Data

10. How Corbado can help#

A capability table tells you what the hardware can do. It says nothing about which hardware your users hold or which of those models fails in your login. The AAGUID data from your own ceremonies answers both, and that is what Corbado Observe, our authentication observability layer, collects.

See Authenticator Inventory in Corbado Observe →
  • See the authenticator behind every ceremony. The inventory resolves the AAGUID to a model, so "our workforce uses YubiKeys" turns into a distribution with the long tail of Feitian, HID and Token2 keys that procurement never mentioned.
  • Find capability mismatches as an error pattern. WebAuthn failures are attributed by authenticator, OS and browser, so a largeBlob or credProtect assumption that only breaks on one model shows up as a cluster instead of as scattered noise.
  • Separate device-bound from synced credentials. The split is reported per segment, which is usually the number a regulated environment asks for.

If you roll out security keys next to platform passkeys, hardware passkey observability describes how the two populations differ in practice.

11. Conclusion#

None of this data was ever hidden. It sits in a signed file that the FIDO Alliance updates every month, one authenticatorGetInfo response per listed key, and it answers most of the questions that teams still answer by guessing or by buying a key and trying it out.

PRF sits at 94%, higher than most teams expect. CTAP 2.1 stops at 59%, credential blobs stay below half and reported capacity spans two orders of magnitude. Build on the 94% and degrade gracefully around the rest.

Two caveats apply to every row above. The metadata is a snapshot from the moment of submission, so firmware moves ahead of it, and roughly half of the records leave out the capacity and transport fields. Read a key in your hand with fido2-token -I before you commit a design to it, and measure which AAGUIDs your users present before you commit a rollout.

Corbado

About Corbado

Corbado is the Passkey Intelligence Platform for large-scale CIAM teams running consumer authentication. We help you see what IDP logs and generic analytics tools can't: where passkeys, passwords, OTP, social login and fallback journeys succeed, stall or fail, which devices and browsers create friction, and when an OS update silently breaks login. Two products: Corbado Observe layers process mining and observability across authentication journeys. Corbado Connect adds managed passkeys with analytics built in alongside your IDP. VicRoads runs passkeys for 5M+ users with Corbado (+80% passkey activation). Talk to a Passkey Expert

Frequently Asked Questions#

Which FIDO2 security keys support the WebAuthn PRF extension?#

PRF on a security key needs the CTAP hmac-secret extension. 306 of the 325 roaming authenticators in the FIDO Metadata Service support it, which is 94% and makes it the most widely implemented CTAP extension. The newer hmac-secret-mc, which lets a key return a PRF result during registration, is much rarer at 20 of 325 keys.

How many passkeys can a FIDO2 security key store?#

The range is wide. Of the 150 keys that report remainingDiscoverableCredentials in their CTAP getInfo response, the median is 100. The OneSpan DIGIPASS FX1-C reports 662, the Swissbit iShield Key 2 reports 300 and the HID Crescendo Key V3 reports 30. Non-discoverable credentials are practically unlimited on almost every key, because nothing is stored on the device.

What does bioEnroll false mean in a CTAP getInfo response?#

It means the key has a fingerprint sensor, but no fingerprint has been enrolled yet. In CTAP an option missing from the options map is unsupported and true means supported and active. false depends on the option: for the ones a user sets up, such as bioEnroll, clientPin, uv, ep and alwaysUv, it means supported but not configured, while for support-only options such as rk, credMgmt and largeBlobs it means not supported. Reading bioEnroll: false as no support is the most common mistake when interpreting getInfo, because it makes every YubiKey Bio look like it has no biometrics.

Why does a security key not accept my whole allowCredentials list at once?#

Every key states a limit in its getInfo response, maxCredentialCountInList, for how many credential IDs it accepts in a single request. The most common limit is 8. If a login sends more IDs than that, the browser has to cut the list into chunks of that size and ask the key once per chunk. Over USB nobody notices. Over NFC every extra request is another tap on the reader, and nine keys in the metadata, all HID Crescendo variants, have a limit of 1, so a list of 20 credentials becomes 20 taps. Keep the list short, or send an empty allowCredentials and let the key use its discoverable credentials.

Where can I look up the capabilities of a specific security key?#

The FIDO Alliance Metadata Service publishes a signed BLOB with the submitted authenticatorGetInfo response for every FIDO2 authenticator it lists, keyed by AAGUID. For a key you can plug in, fido2-token -I from libfido2 prints the same response from the firmware that is actually installed, for any vendor. ykman fido info does the same, but only for YubiKeys.

See how Corbado fits your passkey rollout and existing authentication stack.

Explore the Console

Share this article


LinkedInTwitterFacebook