<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Parag Mali - tag: fido2</title><description>Posts tagged fido2.</description><link>https://paragmali.com/</link><language>en-US</language><lastBuildDate>Sun, 07 Jun 2026 04:13:17 GMT</lastBuildDate><atom:link href="https://paragmali.com/tags/fido2/rss.xml" rel="self" type="application/rss+xml"/><item><title>The Card That Wasn&apos;t a Card: How Windows Authentication Outgrew the Smart Card Metaphor</title><link>https://paragmali.com/blog/the-card-that-wasnt-a-card-how-windows-authentication-outgre/</link><guid isPermaLink="true">https://paragmali.com/blog/the-card-that-wasnt-a-card-how-windows-authentication-outgre/</guid><description>Smart cards, virtual smart cards, and Windows authentication 1996-2026: from PC/SC and PIV through the 2014 NTLM-secondary defect to WHfB and FIDO2.</description><pubDate>Tue, 26 May 2026 00:00:00 GMT</pubDate><content:encoded>
**The Windows smart card story is the story of a metaphor.** Roland Moreno&apos;s 1974 &quot;card with a secret&quot; became Windows 2000&apos;s `SCardSvr.exe`, then Windows 8&apos;s TPM Virtual Smart Card (a software card with the same PC/SC interface), then Windows Hello for Business (which threw the card edge away and talks to the TPM directly), then FIDO2 (which added the origin binding the card was never designed for). The cryptographic primitive -- a non-exportable asymmetric key under a local gesture -- survives every transition. The 2014 disclosure that smart-card-required accounts still mint a harvestable NTLM hash is closed not by any change to the card but by Microsoft&apos;s 2024-2026 NTLM removal plan. The card was always cryptographically sound; the protection terminated at the act of signing.
&lt;h2&gt;1. A Smart Card Login That Mints an NTLM Hash&lt;/h2&gt;
&lt;p&gt;Picture May 2014. A Department of Defense contractor pushes her Common Access Card into a Windows 7 workstation, types a six-digit PIN, and watches the lock screen melt into her desktop. The RSA-2048 private key that just signed her &lt;a href=&quot;https://paragmali.com/blog/kerberos-in-windows-the-other-half-of-ntlmless/&quot; rel=&quot;noopener&quot;&gt;Kerberos&lt;/a&gt; pre-authentication blob lives inside a tamper-resistant secure element she cannot extract from the card. The cryptography is excellent. Three hours later, an attacker on the same network owns her domain account without ever touching the card [@dirteam-aorato] [@kb-2871997].&lt;/p&gt;
&lt;p&gt;How is that even possible? Hold that question. The answer is the spine of this article.&lt;/p&gt;
&lt;p&gt;The contractor here is a composite figure, not a documented incident. The mechanism (CAC + Windows 7, RSA-2048 signing inside the card, an NT hash recoverable from LSASS three hours later) is the one Aorato disclosed in 2014 [@dirteam-aorato] and Microsoft documented in KB 2871997 [@kb-2871997]. The scenario is faithful to the published attack chain; the person and the office park are illustrative.&lt;/p&gt;
&lt;p&gt;The protocol that ran when she logged in is PKINIT, defined by &lt;a href=&quot;#&quot; rel=&quot;noopener&quot;&gt;RFC 4556&lt;/a&gt; [@rfc-4556] and profiled for Windows in &lt;code&gt;[MS-PKCA]&lt;/code&gt; [@ms-pkca]. PKINIT lets a Kerberos client present an X.509 certificate as pre-authentication for the Authentication Service Request (AS-REQ), with a digital signature proving possession of the matching private key. In a Windows smart card logon the signing happens inside the card. The Microsoft Smart Card Key Storage Provider hands the card a hash; the card returns a signed &lt;code&gt;AuthPack&lt;/code&gt; containing a &lt;code&gt;PKAuthenticator&lt;/code&gt; (timestamp, nonce, paChecksum) and Diffie-Hellman parameters; that signed &lt;code&gt;AuthPack&lt;/code&gt; rides in the &lt;code&gt;PA-PK-AS-REQ&lt;/code&gt; pre-authentication data of the AS-REQ [@rfc-4556] [@ms-pkca].&lt;/p&gt;
&lt;p&gt;So far, so good. The Key Distribution Center (KDC) verifies the signature, validates the certificate chain, mints a Ticket-Granting Ticket (TGT), and returns it. Our contractor sees her desktop.&lt;/p&gt;
&lt;p&gt;But the KDC has a second job she does not know about. Her account is flagged &quot;smart card required for interactive logon,&quot; so she has no password. Windows must still authenticate her to a legacy SMB1 server or any network application that speaks only NTLM. The clean answer would be &quot;it cannot.&quot; The answer Microsoft shipped in Windows 2000 is: the KDC silently maintains an NTLM-equivalent secondary credential for every smart-card-only user, rotating it at logon, so legacy services keep working [@kb-2871997] [@msrc-kb-2871997].&lt;/p&gt;
&lt;p&gt;That secondary credential is an NT hash. Once her session is live, an NT hash sits in the Local Security Authority Subsystem (LSASS) memory of every machine she touches. The smart card never sees it. The card cannot police it. It is sixteen bytes of MD4 output that the OS minted around the cryptographic operation the card refused to delegate.&lt;/p&gt;

A non-NTLM-derived NT hash that Windows maintains for accounts configured to log on with a smart card or other non-password credential, so that legacy NTLM-accepting services (SMB1, pre-Windows-2000 applications, some printers) continue to authenticate the user. The hash is computed from a random secret, not the card key, and is rotated by the KDC. From a pass-the-hash attacker&apos;s perspective, it is indistinguishable from a password-derived hash and equally replayable.
&lt;p&gt;Three hours later, an attacker who has phished a privileged helpdesk account runs &lt;code&gt;sekurlsa::logonpasswords&lt;/code&gt; from a copy of &lt;code&gt;mimikatz&lt;/code&gt; [@mimikatz-gh] against the LSASS process on a server the contractor logged into earlier that day. The output looks like &lt;code&gt;NTLM : a1b2c3...&lt;/code&gt;. The attacker pipes that NT hash into a &lt;code&gt;pass-the-hash&lt;/code&gt; against any NTLM-accepting service in the forest. Because &lt;a href=&quot;#&quot; rel=&quot;noopener&quot;&gt;RFC 4757&lt;/a&gt; [@rfc-4757] makes the RC4-HMAC Kerberos long-term key identical to the NT hash, the attacker can also forge Kerberos pre-authentication for the smart-card-required account and request its TGT. The card sat in a reader the attacker never touched. None of that mattered.&lt;/p&gt;
&lt;p&gt;This is the inversion the article exists to explain. The card protected the key. The card did not, and could not, protect the identity. Microsoft documented the gap on May 13, 2014 as KB 2871997, &quot;Update to improve credentials protection and management&quot; [@kb-2871997]; the Microsoft Security Response Center followed with a blog overview of the threat model and the defence-in-depth response [@msrc-kb-2871997]. The disclosure came from Tal Be&apos;ery and his team at Aorato, a Tel Aviv security startup Microsoft would acquire six months later. The period-accurate operator analysis lives in Sander Berkouwer&apos;s July 15, 2014 writeup, cited here because the original Aorato post is offline [@dirteam-aorato].&lt;/p&gt;
&lt;p&gt;How did Windows arrive at an architecture where a tamper-resistant cryptographic token could leave the user&apos;s identity wide open? To answer that we go back to a 1974 patent in Paris.&lt;/p&gt;
&lt;h2&gt;2. How Cards Got a Chip&lt;/h2&gt;
&lt;p&gt;Roland Moreno was twenty-nine when he filed his first smart-card patent family in 1974. A self-taught Parisian, a former pinball-machine fixer and humorist who had washed out of the Sorbonne, he wired an off-the-shelf microchip to a ring of contacts on a small plastic substrate and walked the result over to INPI, the French patent office. The patent family -- known in the secondary literature as &lt;code&gt;carte a memoire&lt;/code&gt; -- did not invent the integrated circuit, the credit-card form factor, or even the idea of embedding silicon in plastic. What Moreno added was a property: the card holds a secret the cardholder cannot extract [@wp-moreno] [@wp-smart-card].&lt;/p&gt;
&lt;p&gt;That property is the entire story.&lt;/p&gt;
&lt;p&gt;Helmut Groettrup, a West German engineer, got there first. He filed German patents DE1574074 and DE1574075 in February 1967 for a tamper-proof identification switch based on a semiconductor device, and added a joint Austrian filing with Juergen Dethloff in September 1968 [@bmpos-history] [@wp-smart-card]. The standard French historiography credits Moreno with the secured-memory refinement rather than the form factor. The inventor question depends on which property you treat as load-bearing.&lt;/p&gt;
&lt;p&gt;Three other people belong in this section. In 1977 Michel Ugon, an engineer at Honeywell Bull&apos;s CP8 division in France, built the first microprocessor smart card -- a card with a CPU on it, not just memory. In 1978 Bull filed the SPOM patent that collapsed CPU and EEPROM onto one chip, the architectural change that made mass production tractable [@bmpos-history] [@cnam-pdf]. And from 1987 to 1995 the International Organization for Standardization froze the card edge into a vendor-neutral wire format with the four parts of ISO/IEC 7816 [@wp-smart-card]: physical characteristics, electrical and transmission protocols, and -- the part that would matter most for Windows -- the command set.&lt;/p&gt;

The international standard for contact smart cards, in four parts that interest software architects: Part 1 covers physical characteristics, Part 3 covers electrical interface and the T=0 and T=1 transmission protocols, and Part 4 covers the organisation, security, and command set for interchange. ISO/IEC 7816-4:2020 is the current edition of Part 4.

Application Protocol Data Unit. The request/response unit a host application exchanges with a smart card. The command APDU starts with a four-byte header `CLA INS P1 P2` (class, instruction, two parameter bytes), followed by an optional length byte `Lc` and `Lc` bytes of data, and an optional expected-response-length byte `Le`. The response APDU is `[data] SW1 SW2`, where the two status word bytes encode success or a card-side error.
&lt;p&gt;A worked APDU example makes this concrete. To select the PIV application on a smart card, a host sends &lt;code&gt;00 A4 04 00 0B A0 00 00 03 08 00 00 10 00 01 00&lt;/code&gt;. The first byte is &lt;code&gt;CLA = 00&lt;/code&gt; (interindustry class). The second is &lt;code&gt;INS = A4&lt;/code&gt; (SELECT). &lt;code&gt;P1 = 04&lt;/code&gt; indicates that the parameter is an application identifier. &lt;code&gt;P2 = 00&lt;/code&gt; selects the first occurrence. &lt;code&gt;Lc = 0B&lt;/code&gt; says eleven data bytes follow, and those eleven bytes are the full PIV AID per NIST SP 800-73-4 [@sp-800-73-4-upd1]: nine bytes for the registered application identifier (&lt;code&gt;A0 00 00 03 08 00 00 10 00&lt;/code&gt;) followed by the two-byte PIV application version identifier (the PIX, &lt;code&gt;01 00&lt;/code&gt;, per SP 800-73-4 Part 1 §2.2). The card replies with optional file control information and the status word &lt;code&gt;90 00&lt;/code&gt;, which means success. Every operation the Windows smart card stack performs decomposes, eventually, into a sequence of these short frames.&lt;/p&gt;

timeline
    title Card-as-authenticator timeline
    1967-1968 : Groettrup and Dethloff file IC-on-card patent
    1974 : Moreno files carte a memoire family
    1977-1978 : Ugon and Bull build CPU smart card and SPOM
    1987-1995 : ISO/IEC 7816 parts 1, 3, 4 published
    1996 : PC/SC Workgroup founded
    2000 : Windows 2000 ships SCardSvr.exe
    2007 : Microsoft Base Smart Card CSP and minidriver model
    2011 : Windows 7 SP1 inbox PIV/GIDS minidriver
    2012 : Windows 8 ships Virtual Smart Card
    2015 : Windows Hello announced
    2024 : NTLMv1 removed in Windows 11 24H2
&lt;p&gt;By 1996 the card edge was settled. Three thousand-odd APDU specifications and proprietary applets later, the only remaining question was: how does a personal computer talk to a card reader? Smart card readers lived in two operationally incompatible worlds, the bank-teller world and the workstation world, and the workstation world was held back by a vendor-driver swamp. So in 1996 a consortium called the PC/SC Workgroup formed. The contemporary record names Microsoft, IBM, Hewlett-Packard, Sun Microsystems, Siemens Nixdorf, and Bull as founders, with Schlumberger and other card vendors joining shortly after [@wp-pcsc] [@sc-architecture].&lt;/p&gt;
&lt;p&gt;The PC/SC specification series (&quot;Interoperability Specification for ICCs and Personal Computer Systems&quot;) names exactly the right abstractions: a Smart Card Resource Manager that brokers access to attached readers, an Interface Device Handler that abstracts reader hardware, and a Service Provider that exposes a uniform programming surface to applications [@sc-architecture]. A personal computer talks to a smart card by speaking PC/SC, in user-mode, through whatever service the OS provides.&lt;/p&gt;

Personal Computer/Smart Card. The 1996 industry consortium and its specification series that define how a smart card reader is exposed to a desktop operating system. PC/SC factors the stack into reader hardware (Interface Device), an Interface Device Handler driver, a Smart Card Resource Manager (a system service brokering access), and a Service Provider exposing a uniform API to applications.
&lt;p&gt;Microsoft answered the implementation question in February 2000 with &lt;code&gt;SCardSvr.exe&lt;/code&gt;, the Smart Cards for Windows service that shipped in Windows 2000 [@sc-architecture]. And immediately created a new problem: every card vendor still wanted to own the cryptographic provider.&lt;/p&gt;
&lt;h2&gt;3. From SCardSvr to Base CSP: Eleven Years to a Vendor-Neutral Stack&lt;/h2&gt;
&lt;p&gt;Windows 2000 shipped smart card logon as a vendor-neutral primitive. Within months, the operational reality bit. Every card vendor shipped a different CryptoAPI plug-in, every plug-in needed installing per machine, per card, sometimes per user.&lt;/p&gt;
&lt;p&gt;Walk down the stack. At the bottom is the reader, attached over USB or, in early-2000s deployments, an internal serial port. Above the reader is the Interface Device Handler driver supplied by the reader vendor. Above the driver is &lt;code&gt;SCardSvr&lt;/code&gt;, Microsoft&apos;s Smart Card Resource Manager service. &lt;code&gt;SCardSvr&lt;/code&gt; exposes a user-mode API called WinSCard: &lt;code&gt;SCardEstablishContext&lt;/code&gt;, &lt;code&gt;SCardConnect&lt;/code&gt;, &lt;code&gt;SCardTransmit&lt;/code&gt;, &lt;code&gt;SCardDisconnect&lt;/code&gt; [@winscard-api]. WinSCard is the C-level entry into PC/SC; an application that wants to send raw APDUs to a card uses WinSCard directly [@sc-architecture].&lt;/p&gt;

The Windows user-mode API surface for PC/SC. Canonical entry points include `SCardEstablishContext`, `SCardListReaders`, `SCardConnect`, `SCardTransmit`, and `SCardDisconnect`. An application sending raw APDUs to a smart card uses WinSCard; higher-level Windows components (Kerberos client, certificate enrolment, the lock-screen credential provider) reach the card indirectly through the Cryptographic Service Provider or Key Storage Provider layers.
&lt;p&gt;Cryptographic clients do not want to write APDU sequences. They want to call &lt;code&gt;CryptSignHash&lt;/code&gt; or &lt;code&gt;NCryptSignHash&lt;/code&gt; and have a signature appear. Translating those API calls into the card&apos;s APDU command set is the job of a Cryptographic Service Provider in the CryptoAPI 1.0 world and a Key Storage Provider in the &lt;a href=&quot;https://paragmali.com/blog/cng-architecture-bcrypt-ncrypt-ksps/&quot; rel=&quot;noopener&quot;&gt;CNG (Cryptography Next Generation)&lt;/a&gt; world. From 1996 to 2007, almost every card vendor wrote its own CSP. The Schlumberger CSP. The Gemalto CSP. The Axalto CSP. The ActivIdentity CSP. Each was an in-process DLL that talked to the card through WinSCard, applied vendor-specific quirks, and exposed a CSP interface to Windows.&lt;/p&gt;

A plug-in for CryptoAPI 1.0 that provides cryptographic services (key generation, signing, hashing, key storage) to applications. CryptoAPI loads a CSP in-process. For smart cards, the CSP translates CryptoAPI calls into card-specific APDUs through WinSCard. Microsoft Base Smart Card CSP, shipped in 2007, replaced the per-vendor CSP with a single CSP that delegated card-specific behaviour to a much smaller minidriver.

The CNG-era plug-in that provides key storage and asymmetric cryptographic operations. CNG separates algorithm providers (BCrypt: hashing, symmetric, signature primitives) from key storage providers (NCrypt: key lifecycle, key-protected operations). The Microsoft Smart Card Key Storage Provider is the CNG-side path for smart card and Virtual Smart Card keys; the Microsoft Platform Crypto Provider is its sibling that talks to the TPM directly.
&lt;p&gt;The architecture had two problems by 2003. First, an N x M combinatorial. Every new card vendor multiplied integration cost for every cryptographic application, and vice versa. Large enterprises ran two or three CSPs per workstation; subtle bugs in signature padding or PIN caching only surfaced when an application built for vendor A&apos;s CSP met a card configured for vendor B&apos;s. Second, a security problem: each CSP ran in-process with every CryptoAPI client, so a buggy or compromised third-party CSP could reach critical OS components.&lt;/p&gt;
&lt;p&gt;Microsoft&apos;s answer was the Smart Card Minidriver Specification, finalised around the Vista launch in 2006-2007. Microsoft would ship one CSP -- the Microsoft Base Smart Card CSP -- containing the cryptographic state machine common to all PIV-style cards. Per-card behaviour would live in a much smaller DLL called a minidriver, loaded by the Base CSP when it recognised the card. The specification, &lt;code&gt;dn631754&lt;/code&gt;, currently maintained at v7.07, says exactly this: &quot;The Microsoft Smart Card Base CSP and KSP is a refinement of the architecture that separates commonly needed CAPI-based CSP and CNG-based KSP functionality, respectively, from the implementation details that must change for every card vendor&quot; [@sc-minidrivers] [@sc-minidriver-spec].&lt;/p&gt;
&lt;p&gt;The CNG-side sibling, the Microsoft Smart Card Key Storage Provider, plugs into the same minidriver layer. CNG is the post-Vista cryptographic platform: BCrypt for algorithm primitives, NCrypt for key lifecycle and storage [@cng-storage]. The Smart Card KSP supports DH 512-4096, ECDH P256/P384/P521, ECDSA P256/P384/P521, and RSA 512-16384 [@cng-ksp-list]. Both the legacy Base CSP and the modern KSP route through the same minidriver, so a card vendor writes one DLL and gets compatibility with both CryptoAPI 1.0 and CNG applications.&lt;/p&gt;

flowchart TD
    A[Reader hardware] --&amp;gt; B[IFD driver]
    B --&amp;gt; C[SCardSvr Smart Card Resource Manager]
    C --&amp;gt; D[WinSCard user-mode API]
    D --&amp;gt; E[Microsoft Base Smart Card CSP and Smart Card KSP]
    E --&amp;gt; F[Card minidriver DLL]
    F --&amp;gt; G[ISO 7816-4 APDU on the card]
    H[CryptoAPI 1.0 client] --&amp;gt; E
    I[CNG NCrypt client] --&amp;gt; E
&lt;p&gt;CryptoAPI&apos;s &lt;code&gt;CryptSignHash&lt;/code&gt; walks the Base CSP; CNG&apos;s &lt;code&gt;NCryptSignHash&lt;/code&gt; walks the Smart Card KSP; both end up issuing the same APDU sequence through the same minidriver to the same card.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Property&lt;/th&gt;
&lt;th&gt;CryptoAPI Base CSP&lt;/th&gt;
&lt;th&gt;CNG Smart Card KSP&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Era&lt;/td&gt;
&lt;td&gt;CryptoAPI 1.0, pre-Vista to present (legacy support)&lt;/td&gt;
&lt;td&gt;CNG, Vista onward&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Entry point&lt;/td&gt;
&lt;td&gt;&lt;code&gt;CryptAcquireContext&lt;/code&gt;, &lt;code&gt;CryptSignHash&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;NCryptOpenStorageProvider&lt;/code&gt;, &lt;code&gt;NCryptSignHash&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Implementation DLL&lt;/td&gt;
&lt;td&gt;&lt;code&gt;basecsp.dll&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;microsoft smart card key storage provider&lt;/code&gt; registered through &lt;code&gt;ncrypt.dll&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Per-card extension&lt;/td&gt;
&lt;td&gt;Smart card minidriver&lt;/td&gt;
&lt;td&gt;Same smart card minidriver&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Algorithm range&lt;/td&gt;
&lt;td&gt;RSA, basic ECC&lt;/td&gt;
&lt;td&gt;RSA, full Suite B ECC, large key ranges&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;By 2008 the architecture was elegant. But every PIV card still needed a minidriver acquired from somewhere -- a CD, a vendor ftp site, an enterprise distribution share. And in 2004 the US federal government was about to make the smart card mandatory for several million people who could not wait for a vendor disk.&lt;/p&gt;
&lt;h2&gt;4. PIV, GIDS, CAC, and the Inbox Driver That Removed the Last Install Step&lt;/h2&gt;
&lt;p&gt;On August 27, 2004, President George W. Bush signed Homeland Security Presidential Directive 12, a one-page policy with one operational sentence: there shall be &quot;a mandatory, government-wide standard for secure and reliable forms of identification issued by the federal government to its employees and contractors&quot; [@hspd-12]. HSPD-12 did not specify how. It pointed at the National Institute of Standards and Technology and said &quot;make it so.&quot;&lt;/p&gt;
&lt;p&gt;NIST&apos;s response was FIPS 201, the Personal Identity Verification standard, first published in February 2005. The current revision, FIPS 201-3, was published in January 2022, superseding FIPS 201-2 from 2013 [@fips-201-3] [@fips-201-3-pdf]. Where FIPS 201 specifies the credential -- what a PIV card is, biometrically, biographically, visually -- the companion NIST SP 800-73 specifies the card-edge interface: file system, data objects, APDU command set [@sp-800-73-4-upd1].&lt;/p&gt;

The US federal smart card identity credential defined by FIPS 201 and its companion NIST Special Publications. FIPS 201 defines what a PIV credential is; NIST SP 800-73 defines the card-edge interface (file structure, data objects, APDU command set) so any host can talk to any PIV-compliant card; SP 800-78 covers cryptographic algorithms; SP 800-76 covers biometrics; SP 800-79 covers card issuer accreditation.
&lt;p&gt;The numbers are striking. NIST reports &quot;close to five million PIV Cards today provide multifactor authentication to federal IT resources and facilities&quot; [@nist-piv-home]. The largest single cohort is the DoD Common Access Card (CAC), which by 2002 numbers had reached more than one million card readers across more than 1,000 issuance sites in more than 25 countries [@wp-cac].&lt;/p&gt;
&lt;p&gt;Microsoft, watching from Redmond, faced two choices: negotiate a separate minidriver for the GSC-IS card-edge applet some federal agencies were using, or ship an inbox class minidriver that auto-discovered PIV-compliant cards out of the box -- and for completeness, supported a Microsoft-defined alternative called the Generic Identity Device Specification.&lt;/p&gt;
&lt;p&gt;GIDS, Microsoft&apos;s complementary card-edge profile, shipped v1.0 in April 2010 and v2.0 in October 2012 [@gids-spec]. It was a profile for card vendors and TPM integrators who wanted a Microsoft-blessed alternative to PIV, and it would become important to Windows 8&apos;s Virtual Smart Card design.&lt;/p&gt;

The Generic Identity Device Specification, a Microsoft-published smart card profile for identity credentials. GIDS v1.0 published April 2010; v2.0 published October 2012. GIDS coexists with PIV at the inbox minidriver layer: Windows&apos; inbox `msclmd.dll` recognises both, allowing zero-install integration for any card that implements either applet.
&lt;p&gt;The inbox driver shipped in Windows 7 SP1 in February 2011. Microsoft Learn is direct: &quot;Windows provides an inbox generic class minidriver that supports Personal Identity Verification (PIV)-compliant smart cards and cards that implement the Generic Identity Device Specification (GIDS) card edge&quot; [@inbox-minidriver]. The auto-discovery sequence is sequential: &lt;code&gt;msclmd.dll&lt;/code&gt; issues a &lt;code&gt;SELECT&lt;/code&gt; for the PIV AID; if the card returns &lt;code&gt;90 00&lt;/code&gt;, Windows treats it as PIV. If the PIV select fails, the driver tries the GIDS AID; if that succeeds, Windows treats the card as GIDS. If both selects return a &quot;neither-AID-exists&quot; status, Windows still proceeds as if the card were GIDS, and the inbox driver continues to handle it. Only an unknown SELECT error makes the inbox driver decline and Windows fall back to a vendor minidriver [@inbox-minidriver]. The effect: any PIV-compliant card (CAC, Yubico YubiKey 5 [@yubico-piv], any FIPS 201-compliant federal credential) worked on a stock Windows 7 SP1 install with zero additional software.&lt;/p&gt;

Before Windows 7 SP1, deploying a CAC to a workstation required an out-of-band CSP install: a vendor disk, an enterprise distribution share, or a manual download. Some classified networks could not reach the vendor distribution channels at all. The inbox `msclmd.dll` removed that friction. A workstation that had never been online could authenticate a CAC user on first boot, provided it was joined to a domain whose KDC chain it could reach for PKINIT validation. Many DoD operational deployments lived inside the airgap, and many of them only became deployable at scale once the inbox minidriver had landed.
&lt;p&gt;With the card-edge problem solved and the install problem closed, what remained was the protocol Windows logon would use. That protocol is PKINIT.&lt;/p&gt;

Public Key Cryptography for Initial Authentication in Kerberos. Specified by [RFC 4556](#) [@rfc-4556] and profiled for Windows by `[MS-PKCA]` [@ms-pkca]. PKINIT lets a Kerberos client present an X.509 certificate, and prove possession of the private key, as pre-authentication for the Authentication Service Request (AS-REQ), instead of a password-derived shared secret. The Windows AS Exchange remains otherwise unchanged: the client receives a TGT encrypted with a session key established under the public-key exchange.

The PKINIT structure that carries the client&apos;s proof of possession. It contains a `PKAuthenticator` (cusec, ctime, nonce, paChecksum) and Diffie-Hellman parameters. The client signs the `AuthPack` with the private key corresponding to its certificate, then embeds the signed structure in the `PA-PK-AS-REQ` pre-authentication data of the Kerberos AS-REQ. The granularity matters: the signature covers the `AuthPack`, not the AS-REQ as a whole.
&lt;p&gt;In a Windows smart card logon the path from PIN to TGT runs through eight named components. Walk it once and the rest of the article becomes legible.&lt;/p&gt;

sequenceDiagram
    participant U as User at lock screen
    participant CP as Credential Provider
    participant LSA as LSASS Kerberos client
    participant KSP as Microsoft Smart Card KSP
    participant MD as Minidriver
    participant CARD as Smart card
    participant KDC as Domain Controller KDC&lt;pre&gt;&lt;code&gt;U-&amp;gt;&amp;gt;CP: Insert card, type PIN
CP-&amp;gt;&amp;gt;LSA: Logon attempt with PIV credential
LSA-&amp;gt;&amp;gt;KSP: NCryptSignHash on AuthPack hash
KSP-&amp;gt;&amp;gt;MD: Card-specific sign request
MD-&amp;gt;&amp;gt;CARD: VERIFY PIN, then SIGN APDU
CARD--&amp;gt;&amp;gt;MD: Signed AuthPack bytes, SW=9000
MD--&amp;gt;&amp;gt;KSP: Signed AuthPack
KSP--&amp;gt;&amp;gt;LSA: Signed AuthPack
LSA-&amp;gt;&amp;gt;KDC: AS-REQ with PA-PK-AS-REQ pre-auth
KDC-&amp;gt;&amp;gt;KDC: Verify signature, cert chain, freshness
KDC--&amp;gt;&amp;gt;LSA: AS-REP with TGT
LSA--&amp;gt;&amp;gt;CP: Logon success, session keys cached
CP--&amp;gt;&amp;gt;U: Desktop
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Notice what the card sees and what it does not. It sees a hash to sign and a PIN to verify. It does not see &quot;I am authenticating to KDC &lt;code&gt;DC01.contoso.local&lt;/code&gt; for user &lt;code&gt;jdoe&lt;/code&gt;.&quot; A PIV card is a signing oracle. The relying party identity, the freshness, the replay window, the binding of signature to context: all of that lives in the protocol above the card, not in the card itself. We come back to this in section 8.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; The cryptographic primitive at the centre of the smart card metaphor -- a non-exportable asymmetric key, bound to a tamper-resistant element, gated by a local gesture -- is the longest-lived object in this lineage. The interface around the primitive (PC/SC, CryptoAPI, CNG, NCrypt-direct, WebAuthn) is what changes every generation.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;By 2013 the cryptographic story was excellent. PKINIT was a clean Kerberos AS exchange. The card protected the key. The KDC issued a TGT. Then, in a few months in 2014, one researcher in Tel Aviv showed that the protection ended at the very moment of signing.&lt;/p&gt;
&lt;h2&gt;5. KB2871997 and the NTLM Secondary Credential&lt;/h2&gt;
&lt;p&gt;Tal Be&apos;ery, then Vice President of Research at Aorato, sat down in early 2014 with a question that should have had a boring answer. If an Active Directory account is flagged &quot;smart card required for interactive logon,&quot; and the user has no password, is the account immune to pass-the-hash?&lt;/p&gt;
&lt;p&gt;The answer is no. Aorato&apos;s original disclosure post is offline; Microsoft acquired Aorato in November 2014 and the research became the foundation of what is now Microsoft Defender for Identity. The period-accurate operator analysis that survives in public is Sander Berkouwer&apos;s July 15, 2014 dirteam.com writeup, cited here in lieu of the dead original [@dirteam-aorato].&lt;/p&gt;
&lt;p&gt;The attack is built from three off-the-shelf parts. The first is the NTLM secondary credential we met in section 1: every smart-card-only account in Active Directory has a usable NT hash on the KDC, maintained for legacy compatibility. The second is the harvesting tool. Benjamin Delpy&apos;s &lt;code&gt;mimikatz&lt;/code&gt; had reached its 2.0-alpha milestone in April 2014; the README documents &lt;code&gt;sekurlsa::logonpasswords&lt;/code&gt; extracting NT hashes from LSASS, plus &lt;code&gt;sekurlsa::pth&lt;/code&gt; and golden-ticket forgery for replay [@mimikatz-gh]. The third is the cryptographic identity that makes hashes Kerberos-relevant. &lt;a href=&quot;#&quot; rel=&quot;noopener&quot;&gt;RFC 4757&lt;/a&gt; section 2 establishes that the RC4-HMAC long-term key in Kerberos is the NT hash itself, &quot;for compatibility reasons&quot; [@rfc-4757] [@dirteam-aorato].&lt;/p&gt;
&lt;p&gt;Compose those three parts. An attacker with administrative footing on any machine the user has touched runs &lt;code&gt;sekurlsa::logonpasswords&lt;/code&gt; against LSASS and gets the NT hash. By RFC 4757 the hash is a usable Kerberos RC4-HMAC pre-authentication key for the user; pre-auth is a function of the long-term key, so the attacker can request a TGT. Or they replay the hash directly via SMB. The card sits, intact, in the user&apos;s reader. Nothing about it has changed.&lt;/p&gt;

The smart card&apos;s tamper-resistance was real. But the cryptographic guarantee terminated at the act of signing -- not at the authentication outcome.
&lt;p&gt;This is the article&apos;s central inversion. The card was right. The system was wrong. The card protected the &lt;em&gt;key&lt;/em&gt;; the OS minted &lt;em&gt;credentials around&lt;/em&gt; that key the card could not police; the protection terminated at the signing operation; the identity did not.&lt;/p&gt;

Given an interactive shell as Local System or a debug-privileged user, the harvest is two commands:&lt;pre&gt;&lt;code&gt;privilege::debug
sekurlsa::logonpasswords
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;sekurlsa::logonpasswords&lt;/code&gt; walks LSASS sessions and prints any cached NT hashes, including the rotated secondary credential for smart-card-required users. The pass-the-hash replay is one more:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sekurlsa::pth /user:JaneDoe /domain:CONTOSO /ntlm:a1b2c3...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This launches a process whose Kerberos ticket cache accepts the supplied NT hash as the RC4-HMAC pre-auth key for the named principal. Any tool spawned from that process can request service tickets for the user. The smart card need not be in any reader on any machine on the network. KB 2871997 and the Pass-the-Hash mitigations (KB 2984972, 2984976, 2984981) addressed this defence-in-depth; NTLM removal addresses it structurally.
&lt;/p&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Microsoft&apos;s response shipped on May 13, 2014 as Security Advisory KB 2871997, &quot;Update to improve credentials protection and management.&quot; It is mostly a registry change and a recommended Group Policy: set &lt;code&gt;HKLM\SYSTEM\CurrentControlSet\Control\Lsa\TokenLeakDetectDelaySecs&lt;/code&gt; to 30 seconds [@kb-2871997]. The June 2014 MSRC blog added more context, especially around a new security group called &lt;a href=&quot;https://paragmali.com/blog/who-is-allowed-to-log-in-where-the-kdc-side-answer-to-creden/&quot; rel=&quot;noopener&quot;&gt;Protected Users&lt;/a&gt; [@msrc-kb-2871997].&lt;/p&gt;
&lt;p&gt;Protected Users, added to Windows Server 2012 R2 domains and Windows 8.1 clients, blocks NTLM, blocks DES and RC4 in Kerberos pre-authentication, blocks both forms of delegation, and prevents offline sign-in caching [@protected-users]. Add a privileged account to Protected Users and you force it off the RC4-HMAC code path. An attacker who steals the NT hash no longer has a usable Kerberos pre-auth key, even though the hash itself is still recoverable.&lt;/p&gt;
&lt;p&gt;Microsoft&apos;s later response was &lt;a href=&quot;https://paragmali.com/blog/the-empty-hash-credential-guard-the-lsaiso-trustlet-and-the-/&quot; rel=&quot;noopener&quot;&gt;Credential Guard&lt;/a&gt;, which isolates credential material in a Virtualization-Based Security (VBS) container called LSAISO, separated from LSASS by a Hyper-V trust boundary. On Windows 11 22H2 and Server 2025, Credential Guard is enabled by default on domain-joined, non-DC systems that meet hardware requirements, protecting NTLM hashes, Kerberos TGTs, and stored domain credentials [@credential-guard].&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The KB 2871997 family (TokenLeakDetectDelaySecs, Protected Users, LSA Protection / RunAsPPL, Credential Guard later) is defence-in-depth. It makes hash theft harder, the harvested hash less universally useful, and lateral movement more visible. None of those measures removes the secondary NT hash itself. The structural fix is to &lt;a href=&quot;https://paragmali.com/blog/ntlmless-the-death-of-ntlm-in-windows/&quot; rel=&quot;noopener&quot;&gt;remove NTLM&lt;/a&gt;. That work began in earnest with the 2023 &quot;evolution of Windows authentication&quot; announcement and reached its first hard milestone with the NTLMv1 removal in Windows 11 24H2 and Windows Server 2025 [@evolution-windows-auth] [@ntlmv1-removal].&lt;/p&gt;
&lt;/blockquote&gt;

Two sentences look identical but mean very different things: &quot;the card protected the key&quot; and &quot;the system protected the user.&quot; The first is a statement about a piece of hardware and the cryptographic discipline of its operation; it was true in 1996, true in 2014, true today. The second is a statement about the authentication subsystem that uses the card. In 2014 it was false, and the falsehood had been present for fourteen years, hidden under the assumption that strong cryptography at the card edge guaranteed a corresponding strength of identity assertion. The 2014 disclosure was a forcing function for distinguishing the two. Every subsequent design (VSC, WHfB, FIDO2) can be evaluated by where it draws that line.
&lt;p&gt;If the card alone could not deliver the protection, perhaps the right move was to throw away the &lt;em&gt;physical&lt;/em&gt; card entirely. Microsoft had shipped exactly that experiment eighteen months earlier.&lt;/p&gt;
&lt;h2&gt;6. Virtual Smart Cards in Windows 8&lt;/h2&gt;
&lt;p&gt;On October 26, 2012, Microsoft shipped Windows 8. Buried in the new features, alongside the Start screen redesign and the Hyper-V client, was a command-line tool named &lt;code&gt;tpmvscmgr.exe&lt;/code&gt; that created a smart card without any plastic. The tool is still there. Open an elevated prompt on a current Windows installation and type &lt;code&gt;tpmvscmgr create /name vsc1 /AdminKey DEFAULT /PIN PROMPT&lt;/code&gt;, and the system manufactures a new entry under &lt;code&gt;ROOT\SMARTCARDREADER\&lt;/code&gt; that any PC/SC client sees as a freshly inserted card [@tpmvscmgr].&lt;/p&gt;
&lt;p&gt;The pitch is mechanical. Every Windows 8+ device with a &lt;a href=&quot;https://paragmali.com/blog/the-tpm-in-windows-one-primitive-twenty-five-years-and-the-c/&quot; rel=&quot;noopener&quot;&gt;Trusted Platform Module&lt;/a&gt; already has the cryptographic substrate of a smart card on the motherboard: a tamper-resistant chip, a non-exportable key store, dictionary-attack resistance, an isolated execution environment for crypto. Why not implement the smart card abstraction in software, with the TPM as the backing chip [@vsc-overview] [@vsc-understanding]?&lt;/p&gt;
&lt;p&gt;The Microsoft Learn &quot;Virtual Smart Card Overview&quot; makes the framing crisp. The three core properties of a smart card -- non-exportability, isolated cryptography, anti-hammering -- map directly onto TPM capabilities. Non-exportability becomes TPM key wrapping. Isolated cryptography becomes signing inside the TPM. Anti-hammering becomes the TPM&apos;s dictionary-attack counter [@vsc-overview] [@vsc-understanding].&lt;/p&gt;

A TPM-backed software smart card introduced in Windows 8 (October 2012). A VSC exposes the same PC/SC card edge as a physical card -- the same WinSCard API, the same Base CSP, the same Microsoft Smart Card KSP, the same minidriver model. The chip backing the card is the TPM, soldered to the motherboard, rather than a removable IC on a plastic substrate. From the perspective of any application using the WinSCard API, a VSC is indistinguishable from a permanently-inserted physical smart card.
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Windows 8 shipped Virtual Smart Cards in October 2012. The Trusted Computing Group did not ratify TPM 2.0 until 2014. VSCs are therefore a &lt;em&gt;TPM-binding policy&lt;/em&gt; technology, not a TPM-2.0-bound technology; Microsoft Learn lists TPM 1.2 as the documented minimum. TPM 2.0 works and is the practical choice on modern Windows 11 installations, but the architecture predates it [@vsc-overview] [@vsc-understanding].&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The beauty of the design is that nothing above the chip changed. Applications still call &lt;code&gt;CryptSignHash&lt;/code&gt; or &lt;code&gt;NCryptSignHash&lt;/code&gt;. The Base CSP and Smart Card KSP still route through a minidriver. The minidriver still sends APDUs through WinSCard to a reader. The only differences: the reader is a software pseudo-device named &lt;code&gt;Microsoft Virtual Smart Card&lt;/code&gt;, and the card behind it is the TPM dressed up as an ISO 7816-4 applet.&lt;/p&gt;

flowchart LR
    subgraph Physical [Physical smart card]
        A1[Application] --&amp;gt; B1[CSP/KSP]
        B1 --&amp;gt; C1[Minidriver]
        C1 --&amp;gt; D1[WinSCard]
        D1 --&amp;gt; E1[USB reader]
        E1 --&amp;gt; F1[Plastic card IC]
    end
    subgraph Virtual [Virtual smart card]
        A2[Application] --&amp;gt; B2[CSP/KSP]
        B2 --&amp;gt; C2[Minidriver]
        C2 --&amp;gt; D2[WinSCard]
        D2 --&amp;gt; E2[Virtual reader]
        E2 --&amp;gt; F2[TPM on motherboard]
    end
&lt;p&gt;The cryptographic substrate underneath the abstraction is the TPM, and the binding policy is per-device. The Microsoft Learn &quot;Understanding and Evaluating Virtual Smart Cards&quot; article is precise: &quot;Non-exportability: Because all private information on the virtual smart card is encrypted by using the TPM on the host computer, it can&apos;t be used on a different computer with a different TPM&quot; [@vsc-understanding]. The property that makes a VSC tamper-resistant also makes it un-migratable. A TPM clear destroys the keys irrecoverably. We return to that in section 8.&lt;/p&gt;
&lt;p&gt;The canonical primary source for the architecture is the &quot;Understanding and Evaluating Virtual Smart Cards&quot; whitepaper on the Microsoft Download Center. The download page reports &lt;code&gt;Version: July 2014, Date Published: 7/15/2024&lt;/code&gt; [@vsc-whitepaper]. The 2014 revision is canonical.&lt;/p&gt;

The card was a metaphor. Microsoft kept the byte-for-byte PC/SC interface and put the TPM behind it.
&lt;p&gt;A worked provisioning example brings the design to ground. The &lt;code&gt;tpmvscmgr create&lt;/code&gt; command takes four arguments that matter for security policy: the administrative key (&lt;code&gt;/AdminKey {DEFAULT | PROMPT | RANDOM}&lt;/code&gt;), the PIN policy (&lt;code&gt;/PIN PROMPT&lt;/code&gt; or &lt;code&gt;/PIN DEFAULT&lt;/code&gt;), the attestation mode (&lt;code&gt;/attestation {AIK_AND_CERT | AIK_ONLY}&lt;/code&gt;), and the card&apos;s reader instance, surfaced under &lt;code&gt;ROOT\SMARTCARDREADER\000n&lt;/code&gt; in Device Manager [@tpmvscmgr].&lt;/p&gt;
&lt;p&gt;{`
function provisionVSC(opts) {
  const adminKeyMap = {
    DEFAULT: &apos;0102030405060708&apos; + &apos;0102030405060708&apos; + &apos;0102030405060708&apos;,
    PROMPT: &apos;[user-supplied 48 hex chars]&apos;,
    RANDOM: &apos;[random 24-byte key the admin must record]&apos;,
  };
  const attestationNote = {
    AIK_ONLY: &apos;Identity-binding only; no platform certificate chain stored on the card.&apos;,
    AIK_AND_CERT: &apos;Full AIK-and-EK-cert chain stored; supports federated re-enrolment.&apos;,
    NONE: &apos;No attestation; the card is identity-only.&apos;,
  };
  return {
    cardName: opts.name,
    adminKey: adminKeyMap[opts.adminKey] || &apos;invalid&apos;,
    pin: opts.pin === &apos;PROMPT&apos; ? &apos;[user-typed PIN, min 8 chars, alphanumeric+special allowed]&apos; : &apos;12345678&apos;,
    attestation: attestationNote[opts.attestation || &apos;NONE&apos;],
    advice: opts.adminKey === &apos;DEFAULT&apos;
      ? &apos;WARN: default admin key is documented; treat as factory-default.&apos;
      : &apos;OK: admin key not factory-default.&apos;,
  };
}&lt;/p&gt;
&lt;p&gt;console.log(provisionVSC({
  name: &apos;vsc-jdoe&apos;,
  adminKey: &apos;RANDOM&apos;,
  pin: &apos;PROMPT&apos;,
  attestation: &apos;AIK_AND_CERT&apos;,
}));
`}&lt;/p&gt;
&lt;p&gt;The default administrative key &lt;code&gt;010203040506070801020304050607080102030405060708&lt;/code&gt; is documented in the public &lt;code&gt;tpmvscmgr&lt;/code&gt; page [@tpmvscmgr]. Any VSC provisioned with &lt;code&gt;/AdminKey DEFAULT&lt;/code&gt; should be treated as factory-default; in production, supply (&lt;code&gt;PROMPT&lt;/code&gt;) or randomise (&lt;code&gt;RANDOM&lt;/code&gt;) the admin key and store it separately.&lt;/p&gt;
&lt;p&gt;The provisioning chain has four hard-to-script steps: run &lt;code&gt;tpmvscmgr create&lt;/code&gt; as administrator; request and install an authentication certificate from a PKI the domain trusts (typically Microsoft Certificate Services with an enterprise CA and a smart card auto-enrolment template); set the user PIN; log the user out and back in. Each step is a place an enterprise rollout can stall.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; Microsoft kept the PC/SC card edge byte-for-byte and put the TPM behind it. The Virtual Smart Card was, technically, exactly that: a software smart card whose chip happened to be soldered to the board. The cryptographic primitive at the centre did not change; only the form factor of the chip carrying it did.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;VSCs solved the physical-distribution problem. They did not solve the user-experience problem -- and they introduced a new one no Windows feature had ever produced quite this way: a credential a hardware reset could permanently destroy.&lt;/p&gt;
&lt;h2&gt;7. WHfB, FIDO2, and the Card Edge That Got Discarded&lt;/h2&gt;
&lt;p&gt;On March 17, 2015, Joe Belfiore announced &lt;a href=&quot;https://paragmali.com/blog/your-face-is-not-your-password-inside-windows-hellos-hardwar/&quot; rel=&quot;noopener&quot;&gt;Windows Hello&lt;/a&gt; on the Windows Experience Blog: &quot;I&apos;d like to introduce you to Windows Hello -- biometric authentication which can provide instant access to your Windows 10 devices&quot; [@windows-hello-blog]. The consumer pitch was face and fingerprint. The mechanism underneath, in the enterprise variant called Windows Hello for Business (WHfB), was the same TPM-bound asymmetric key the Virtual Smart Card had used -- except there was no virtual reader, no virtual minidriver, and no virtual APDU.&lt;/p&gt;
&lt;p&gt;WHfB talks to the TPM directly through the Microsoft Platform Crypto Provider, a CNG Key Storage Provider that calls into the TPM rather than into a smart card minidriver [@whfb-overview] [@whfb-how-it-works]. The PC/SC card edge had been removed from the path entirely. The cryptographic primitive (non-exportable TPM-bound asymmetric key, gated by a local gesture, used to sign an authentication request) survived; the interface around the primitive simplified.&lt;/p&gt;
&lt;p&gt;Microsoft Learn describes WHfB in five phases: device registration, provisioning, key synchronisation, certificate enrolment (cert-trust only), authentication. The public key is registered with the identity provider and mapped to the user account; the private key never leaves the device [@whfb-how-it-works]. WHfB ships in three deployment models -- cloud-only, hybrid, on-premises -- and two trust types: key-trust and cert-trust [@whfb-deploy].&lt;/p&gt;
&lt;p&gt;Key-trust is cloud-first. The TPM-bound public key is registered with Microsoft Entra ID; authentication is a public-key proof of possession to Entra, which mints whatever downstream artifacts a federated service needs (PRT, refresh token, optional Kerberos TGT via the cloud Kerberos service). No X.509 certificate sits in the user&apos;s path. Cert-trust adds an X.509 wrapper for downstream services that require one: an enterprise PKI issues a smart-card-logon-style certificate bound to the TPM key, and the WHfB authentication produces a Kerberos PKINIT exchange against an on-premises DC, just as a physical smart card would. The certificate is the adapter to brownfield infrastructure that still expects a smart-card-shaped credential [@whfb-deploy].&lt;/p&gt;
&lt;p&gt;So far the lineage has been Windows-specific. &lt;a href=&quot;https://paragmali.com/blog/webauthn-and-passkeys-on-windows-from-ctap-to-the-credential/&quot; rel=&quot;noopener&quot;&gt;FIDO2&lt;/a&gt; is not. WebAuthn 2 is a W3C Recommendation; CTAP 2.1 is a FIDO Alliance specification [@webauthn-2] [@ctap-2-1]. Together they specify a cross-vendor protocol for public-key authentication to web relying parties, with one load-bearing property the smart card lineage never had: origin binding.&lt;/p&gt;

The property that a WebAuthn credential is scoped to a specific relying party identifier (the RP ID, typically a domain name) and the authenticator will refuse to sign an assertion for any other RP ID. The W3C WebAuthn 2 specification states: &quot;the public key credential can only be accessed by origins belonging to that Relying Party. This scoping is enforced jointly by conforming User Agents and authenticators&quot; [@webauthn-2]. A PIV smart card has no equivalent property; it will sign whatever the host hands it.
&lt;p&gt;Origin binding is the structural fix to a class of relay attacks. A PIV smart card cannot tell whether it is signing a Kerberos AuthPack for the legitimate KDC or a maliciously crafted blob for an attacker-controlled relay; the card has no notion of &quot;what is this signature for.&quot; A WebAuthn authenticator does. It hashes the RP ID into the signed assertion, the relying party verifies the RP ID matches its own origin, and a phishing site cannot trick the authenticator into producing a signature it will accept.&lt;/p&gt;
&lt;p&gt;Microsoft Entra ID supports FIDO2 in two flavours. &lt;em&gt;Device-bound passkeys&lt;/em&gt; live on a FIDO2 security key (a YubiKey 5 [@yubico-piv]) or in Microsoft Authenticator and cannot be extracted. &lt;em&gt;Synced passkeys&lt;/em&gt; are credentials a platform synchronises across the user&apos;s devices through a cloud passkey provider [@entra-passkeys-howto] [@entra-passwordless]. The trade-off is sharp: device-bound passkeys support attestation (the relying party can verify authenticator hardware at registration); synced passkeys do not.&lt;/p&gt;
&lt;p&gt;For workforce identity, Microsoft&apos;s passwordless strategy describes a four-step journey: deploy a password-replacement option, reduce user-visible password surface, transition to passwordless, eliminate passwords [@passwordless-strategy]. WHfB and FIDO2 are the two recommended replacements.&lt;/p&gt;
&lt;p&gt;What about smart cards? The Microsoft Learn Virtual Smart Card Overview now opens with a Warning box that reads, in full: &quot;Windows Hello for Business and FIDO2 security keys are modern, two-factor authentication methods for Windows. Customers using virtual smart cards are encouraged to move to Windows Hello for Business or FIDO2. For new Windows installations, we recommend Windows Hello for Business or FIDO2 security keys&quot; [@vsc-overview]. The deprecation signal could not be more explicit. Physical PIV and CAC cards are not deprecated -- the federal government is not switching off PIV -- but the structural recommendation for greenfield is now WHfB or FIDO2.&lt;/p&gt;
&lt;p&gt;Why did Virtual Smart Cards not survive into the WHfB era? Three reasons.&lt;/p&gt;
&lt;p&gt;The first is provisioning UX. A VSC requires four steps (&lt;code&gt;tpmvscmgr create&lt;/code&gt;, certificate enrolment, PIN set, logon round-trip) where WHfB requires one (a setup wizard the user runs at first sign-in). Each VSC step can fail in idiosyncratic ways: the enterprise CA template not configured for VSCs, the user&apos;s certificate request rejected, the PIN policy mismatched between the GPO and the card. Even when every step succeeds, the user sees a &quot;smart card&quot; UI -- card reader prompts, PIN entries -- that does not match the device they are holding.&lt;/p&gt;
&lt;p&gt;The second is recovery. A TPM clear destroys VSC keys irrecoverably. Microsoft Learn states the constraint plainly [@vsc-understanding]: &quot;all private information on the virtual smart card is encrypted by using the TPM on the host computer.&quot; Recovery would have to be re-enrolment under a federated attestation chain. The AIK-and-EK-cert attestation mode in &lt;code&gt;tpmvscmgr&lt;/code&gt; exists [@tpmvscmgr], but it never grew into a productised re-enrolment story; the practical answer was always &quot;issue a new card.&quot;&lt;/p&gt;
&lt;p&gt;The third is the multi-device world. VSCs bind one credential to one device. By 2017 most enterprise users had at least two devices: a laptop and a phone. By 2022 most had three. A credential metaphor borrowed from the era of one workstation per user could not stretch.&lt;/p&gt;
&lt;p&gt;Where do physical smart cards still belong in 2026? Three places. First, federal PIV / DoD CAC: the badge IS the credential, the issuance lifecycle is owned by an external organisation, and the cards have to work cross-platform and cross-application in a way a Windows-only credential cannot. Second, high-assurance regulated industries (banking, healthcare imaging, court systems) where existing PKI investment and signed-document workflows make the card the institutional artifact, not just an authentication factor. Third, &quot;smart card removal locks workstation&quot; cases (operating-room PCs, trading-floor terminals) where the physical act of pulling the card out of the reader is the security control.&lt;/p&gt;
&lt;p&gt;Where does Entra Certificate-Based Authentication fit? Entra CBA is the cloud-native PIV/CAC path. A federal user logs into Entra ID directly with their PIV/CAC card, bypassing the on-premises ADFS infrastructure that was the traditional cloud-bridge for federal organisations. Entra CBA preserves the PIV credential while replacing the on-premises STS, and is the practical answer to &quot;we have to keep PIV, but also we are migrating to cloud.&quot;&lt;/p&gt;
&lt;p&gt;The table below condenses the comparison.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Where the key lives&lt;/th&gt;
&lt;th&gt;Origin binding&lt;/th&gt;
&lt;th&gt;NTLM secondary&lt;/th&gt;
&lt;th&gt;Provisioning steps&lt;/th&gt;
&lt;th&gt;Multi-device&lt;/th&gt;
&lt;th&gt;Phishing resistance&lt;/th&gt;
&lt;th&gt;Recovery&lt;/th&gt;
&lt;th&gt;Suitable for new deployments&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Physical PIV / CAC&lt;/td&gt;
&lt;td&gt;Removable IC&lt;/td&gt;
&lt;td&gt;No (relay possible)&lt;/td&gt;
&lt;td&gt;Yes (until NTLM removed)&lt;/td&gt;
&lt;td&gt;High (PKI + issuance)&lt;/td&gt;
&lt;td&gt;Yes (cross-device by physical movement)&lt;/td&gt;
&lt;td&gt;Conditional&lt;/td&gt;
&lt;td&gt;Re-issue card&lt;/td&gt;
&lt;td&gt;Federal/DoD only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TPM Virtual Smart Card&lt;/td&gt;
&lt;td&gt;On-device TPM&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes (until NTLM removed)&lt;/td&gt;
&lt;td&gt;High (4-step)&lt;/td&gt;
&lt;td&gt;No (bound to one TPM)&lt;/td&gt;
&lt;td&gt;Conditional&lt;/td&gt;
&lt;td&gt;Re-enrol&lt;/td&gt;
&lt;td&gt;Not recommended (deprecation Warning)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WHfB key-trust&lt;/td&gt;
&lt;td&gt;On-device TPM&lt;/td&gt;
&lt;td&gt;Limited (RP=Entra)&lt;/td&gt;
&lt;td&gt;Reduced (cloud Kerberos)&lt;/td&gt;
&lt;td&gt;Low (in-OS wizard)&lt;/td&gt;
&lt;td&gt;Per-device enrolment&lt;/td&gt;
&lt;td&gt;Yes (relative)&lt;/td&gt;
&lt;td&gt;Re-enrol via device registration&lt;/td&gt;
&lt;td&gt;Yes (cloud/hybrid)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WHfB cert-trust&lt;/td&gt;
&lt;td&gt;On-device TPM&lt;/td&gt;
&lt;td&gt;Limited (RP=AD)&lt;/td&gt;
&lt;td&gt;Yes (until NTLM removed)&lt;/td&gt;
&lt;td&gt;Medium (PKI required)&lt;/td&gt;
&lt;td&gt;Per-device enrolment&lt;/td&gt;
&lt;td&gt;Conditional&lt;/td&gt;
&lt;td&gt;Re-enrol; CA-issued cert&lt;/td&gt;
&lt;td&gt;Yes (brownfield PKI)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FIDO2 security key&lt;/td&gt;
&lt;td&gt;External authenticator (e.g., YubiKey)&lt;/td&gt;
&lt;td&gt;Yes (WebAuthn RP ID)&lt;/td&gt;
&lt;td&gt;Not applicable (no Kerberos)&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;Yes (key is portable)&lt;/td&gt;
&lt;td&gt;Yes (origin-bound)&lt;/td&gt;
&lt;td&gt;Spare key or backup credential&lt;/td&gt;
&lt;td&gt;Yes (high-assurance)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Entra device-bound passkey&lt;/td&gt;
&lt;td&gt;TPM or external authenticator&lt;/td&gt;
&lt;td&gt;Yes (WebAuthn RP ID)&lt;/td&gt;
&lt;td&gt;Not applicable&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;Per-device&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Re-enrol&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Entra synced passkey&lt;/td&gt;
&lt;td&gt;Cloud-synced (no attestation)&lt;/td&gt;
&lt;td&gt;Yes (WebAuthn RP ID)&lt;/td&gt;
&lt;td&gt;Not applicable&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;Yes (cloud-synced)&lt;/td&gt;
&lt;td&gt;Yes (origin-bound)&lt;/td&gt;
&lt;td&gt;Cloud provider recovery&lt;/td&gt;
&lt;td&gt;Yes (consumer, low-friction)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The architecture is now mature. But the lineage has a hard ceiling no architecture can cross: a signing oracle cannot tell you what it signed &lt;em&gt;for&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;8. What a Card Edge Can and Cannot Mediate&lt;/h2&gt;
&lt;p&gt;Set aside provisioning UX. Set aside NTLM legacy. Set aside everything Windows-specific. What are the &lt;em&gt;structural&lt;/em&gt; limits any card-edge-or-equivalent design must accept? Six, by my count, and each one is anchored to a primary source.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The card edge is a signing oracle, not a transcript witness.&lt;/strong&gt; A PIV card receives a hash and returns a signature. It does not know what protocol the signature is for, what relying party requested it, or whether the same hash has been requested two minutes ago by an attacker on a wireless network. PKINIT&apos;s vulnerability to relay was open from 2006 (RFC 4556) until 2017 (RFC 8070, which added a freshness token to the AS exchange) [@rfc-4556] [@rfc-8070]. The fix had to live in the &lt;em&gt;protocol&lt;/em&gt;, not in the card. The card cannot prove what it signed &lt;em&gt;for&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The card has no notion of relying-party identity.&lt;/strong&gt; This is the structural defect WebAuthn fixes. A WebAuthn authenticator includes the RP ID in the signed assertion and refuses to release a signature for the wrong RP. The W3C specification states this property explicitly [@webauthn-2]. A PIV card does not. To add an equivalent property to the smart card lineage would have meant changing the SP 800-73 command set; it was easier to throw the PC/SC card edge away and start over with FIDO2.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cryptographic protection at the card edge cannot reach downstream OS-minted credentials.&lt;/strong&gt; This is the 2014 NTLM-secondary lesson at its most general. The card protects a key; the OS may mint credentials around that key the card cannot police. Microsoft KB 2871997 closed the leak with defence-in-depth retrofits (TokenLeakDetectDelaySecs, Protected Users, RunAsPPL, eventually Credential Guard) [@kb-2871997] [@msrc-kb-2871997] [@protected-users] [@credential-guard]; the structural close had to wait for the 2024-2026 NTLM removal programme [@ntlmv1-removal]. Any future credential the OS mints around the card&apos;s key is, by construction, outside the card&apos;s authority.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Revocation must be reachable, and the card cannot tell you when it is not.&lt;/strong&gt; A PIV card&apos;s certificate is a relying-party-side concept; revocation status is a property of the issuing PKI, not the card. CRL distribution points and OCSP responders are the relying party&apos;s problem to reach. When a domain controller cannot reach the CRL, the policy choice is to fail open or fail closed; either policy carries risk. The &lt;code&gt;[MS-PKCA]&lt;/code&gt; Windows profile specifies server-side certificate-validation processing -- including revocation checking -- as a property of the KDC, not the credential the card presented [@ms-pkca]. The card signed correctly either way.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Certificate-to-user mapping must be strongly bound, and again the card cannot help.&lt;/strong&gt; When a domain controller receives a PKINIT request, it must map the presented certificate to an Active Directory account. The Certifried CVE class disclosed in May 2022 (CVE-2022-26923, CVE-2022-26931, CVE-2022-34691) showed that weak mapping -- by Subject Alternative Name UPN without a strong identifier bound into the certificate -- lets an attacker who can enrol against an over-permissive template impersonate any account [@kb-5014754]. The card signed exactly what it was asked to sign; the structural defect was at the KDC&apos;s mapping step. Microsoft KB 5014754 closed the mapping defect by requiring strong certificate-to-account binding; we return to its multi-year deployment timeline in §9 [@kb-5014754].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Hardware-bound keys cannot be teleported -- and this is both feature and limit.&lt;/strong&gt; Non-exportability is the central promise of the entire lineage. It is also the bound. A TPM clear or a hardware replacement destroys the key. The recovery story has to be re-enrolment, not restore. Microsoft Learn states the constraint for VSCs and the same constraint applies, structurally, to every TPM-bound or external-authenticator credential -- including FIDO2 device-bound passkeys [@vsc-understanding]. Synced passkeys recover this property by giving up attestation; you cannot have both.&lt;/p&gt;

Non-exportability is the property. It is also the bound.
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; An ideal card-lineage authenticator refuses to sign without RP-issued freshness, refuses to release a signature outside its RP scope, leaves no downstream-cacheable credential material, attests to its hardware at registration, and supports identity portability via re-enrolment-under-attestation rather than key portability. No shipping authenticator delivers all five of these authenticator-side properties in a workforce-grade product today; the two RP-side limits (revocation reachability, certificate-to-user mapping) are necessarily closed at the relying party, not the authenticator. The combination is the work of the next decade.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Limit&lt;/th&gt;
&lt;th&gt;What it forbids&lt;/th&gt;
&lt;th&gt;Primary source&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Signing oracle, not transcript witness&lt;/td&gt;
&lt;td&gt;Card cannot prove signature was for the intended protocol context&lt;/td&gt;
&lt;td&gt;RFC 4556 / RFC 8070 [@rfc-4556] [@rfc-8070]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;No RP identity&lt;/td&gt;
&lt;td&gt;Card cannot refuse a relay; relay window must close in protocol&lt;/td&gt;
&lt;td&gt;WebAuthn 2 [@webauthn-2]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;No reach to downstream OS credentials&lt;/td&gt;
&lt;td&gt;Card protects key, not identity around the key&lt;/td&gt;
&lt;td&gt;KB 2871997, MSRC [@kb-2871997] [@msrc-kb-2871997]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Revocation is not self-asserting&lt;/td&gt;
&lt;td&gt;Card cannot vouch for its own validity; KDC must reach the PKI&lt;/td&gt;
&lt;td&gt;[MS-PKCA] [@ms-pkca]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Strong cert-to-user mapping is not card-asserted&lt;/td&gt;
&lt;td&gt;Relying party must bind certificate to AD account; card has no view of the mapping&lt;/td&gt;
&lt;td&gt;KB 5014754 [@kb-5014754]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Non-exportability bounds portability&lt;/td&gt;
&lt;td&gt;Key dies with the chip; recovery must be re-enrolment&lt;/td&gt;
&lt;td&gt;VSC Understanding [@vsc-understanding]&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Some limits are being closed. The signing-oracle limit is mitigated by RFC 8070 freshness tokens; the RP-identity limit is closed for new credentials by WebAuthn; the downstream-credential limit is being closed by NTLM removal; the strong-mapping limit was closed by KB 5014754 on shipping AD infrastructure between February and September 2025. Others are inherent: a non-exportable key is, by definition, not portable. The next decade of smart-card-lineage work is being shaped by which is which.&lt;/p&gt;
&lt;h2&gt;9. Open Problems for the Next Decade&lt;/h2&gt;
&lt;p&gt;Five problems are still open in 2026. Each has a candidate fix in flight; none has shipped to general availability for the workforce case.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;PIV / CAC in a post-NTLM Windows estate.&lt;/strong&gt; NTLMv1 was removed from Windows 11 24H2 and Windows Server 2025 [@ntlmv1-removal]; NTLMv2 is on the deprecation track [@deprecated-features]. What does &quot;smart card required for interactive logon&quot; &lt;em&gt;mean&lt;/em&gt; in a forest with no NTLMv1 secondary credential? The historical answer was &quot;the KDC mints an NT hash so legacy services keep working.&quot; The new answer must be either &quot;no NT hash; legacy services break&quot; or &quot;an NT hash for NTLMv2 only, restricted by SCRIL rotation and Protected Users membership.&quot; Microsoft has not yet published a complete blueprint for what federal PIV deployments look like after NTLMv2 also retires. Credential Guard&apos;s role in the transition is to make any residual secondary credential harder to harvest [@credential-guard] [@protected-users].&lt;/p&gt;

Three concrete questions a federal IT shop should be asking. First: does our forest have any domain controllers still serving NTLMv1 to legacy clients? After 24H2 / Server 2025, the answer should be no [@ntlmv1-removal]. Second: are our privileged accounts in Protected Users? The group blocks NTLM, DES, RC4 pre-auth, and constrained or unconstrained delegation [@protected-users]; for a smart-card-required account, membership effectively removes the RC4-HMAC-via-NTLM-hash attack surface even before NTLMv2 retirement. Third: is Credential Guard enabled on every member system? On Windows 11 22H2 and Server 2025, it is on by default for hardware-eligible domain-joined non-DC systems [@credential-guard]. These three measures are the practical answer to &quot;what does smart-card-required mean today.&quot; The full structural answer waits on NTLMv2 retirement.
&lt;p&gt;&lt;strong&gt;The recovery primitive that never shipped.&lt;/strong&gt; TPM-clear or device replacement destroys TPM-bound keys; this is the cost of non-exportability. AIK-and-EK-cert attestation in &lt;code&gt;tpmvscmgr&lt;/code&gt; could in principle support federated re-enrolment with strong proof of platform identity [@tpmvscmgr], and the Entra passkey enrolment flow supports attestation-required policies [@entra-passkeys-howto], but neither path matured into a &quot;your VSC died; here is how the help desk restores you in fifteen seconds&quot; story. Synced passkeys recover this property by giving up attestation. Workforce-grade attestation &lt;em&gt;and&lt;/em&gt; easy recovery, together, is still not shipping.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The certificate-based-authentication hardening lag.&lt;/strong&gt; Microsoft&apos;s KB 5014754 hardens certificate-based authentication on Windows domain controllers against the Certifried CVE class (CVE-2022-26923, CVE-2022-26931, CVE-2022-34691) by requiring strong certificate-to-user mapping at the KDC. The CVE class was disclosed on May 10, 2022. The mitigation moved DCs to Enforcement mode by default on February 11, 2025, with a fallback to Compatibility mode still available; the override was finally retired on September 9, 2025 [@kb-5014754]. The KB&apos;s own change log records several intermediate slips of the Full-Enforcement target (the original commitment was a 2023 milestone, slipping to February 2025 and then to September 2025) [@kb-5014754]. That is roughly three years from CVE disclosure to default Enforcement and a further seven months to end-of-override on shipping infrastructure -- and the gap from the &lt;em&gt;first published&lt;/em&gt; Full-Enforcement target to the actual end-of-override stretches the slip to a multi-year story in its own right. The lesson is sobering: in a brownfield estate, the time from &quot;CVE disclosed&quot; to &quot;hardening fully enforced on every domain controller&quot; is measured in &lt;em&gt;years&lt;/em&gt;, not weeks. Separately, RFC 8070 PKINIT freshness tokens (February 2017) are a &lt;em&gt;different&lt;/em&gt; hardening programme [@rfc-8070]; Windows has not deployed RFC 8070 freshness as the default in the broad estate, and the article&apos;s RunnableCode in §10 illustrates the freshness exchange rather than documenting deployed Windows behaviour. Any protocol-level fix to the smart-card lineage in 2026 will, on the KB 5014754 evidence, take three to four years to land -- and longer if the standards process itself slips, as RFC 8070&apos;s still-undeployed status (over nine years since publication) suggests.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cross-platform card-edge longevity.&lt;/strong&gt; OpenSC and pcsc-lite still implement NIST SP 800-73 on macOS and Linux; the cross-platform PIV story works for basic logon. But the modern features Windows keeps adding -- attestation chains, device-bound credential extensions, integration with the Entra passkey APIs -- lag on the open-source side. Whether PC/SC outlives the platforms that built it is genuinely uncertain. Some federal organisations will keep PIV alive cross-platform as policy; many private-sector deployments will quietly move off.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Post-quantum signature algorithms on smart cards.&lt;/strong&gt; PIV&apos;s current baseline is RSA-2048 and ECDSA P-256 -- not post-quantum resistant. NIST&apos;s post-quantum standardisation selected ML-DSA (Module Lattice DSA, formerly Dilithium) and SLH-DSA (Stateless Hash-Based DSA, formerly SPHINCS+); both have key and signature sizes substantially larger than RSA-2048 or ECDSA P-256, and both will stress the storage and bandwidth budgets of a typical PIV card. SP 800-73-4 has no slots for post-quantum keys today [@sp-800-73-4-upd1] [@fips-201-3]. A future revision will have to accommodate them, and the existing population of $\approx$ five million PIV cards [@nist-piv-home] will not all be PQ-capable at once. The transition runs on a card-issuance cycle: roughly $T_{\text{transition}} \approx T_{\text{issuance}} + T_{\text{rollout}}$, each term in the multi-year range.&lt;/p&gt;
&lt;p&gt;Architecture is a question about which problems your design &lt;em&gt;cannot&lt;/em&gt; solve. The next section is for the architect who has to choose right now, with all five problems still open.&lt;/p&gt;
&lt;h2&gt;10. Choosing Between PIV, VSC, WHfB, and FIDO2 in 2026&lt;/h2&gt;
&lt;p&gt;Four operator-grade callouts. Pick the one that matches your context.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Stay on PIV / CAC for the foreseeable future. FIPS 201-3 is the current standard and SP 800-73 the current card-edge interface; policy mandates are not changing on a tactical timeline [@fips-201-3] [@nist-piv-home]. Add Entra Certificate-Based Authentication for cloud workloads so the same PIV card authenticates to Microsoft 365 and Azure resources without going through on-premises ADFS. For the three operational controls -- Credential Guard, Protected Users membership for privileged accounts, and NTLMv1-removal status -- see the federal-IT checklist in the §9 Aside. Do not rely on the smart card alone to defeat NTLM-secondary-credential abuse until NTLM removal has reached your environment.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Pick WHfB key-trust if you are cloud-first or hybrid, cert-trust if you have an existing on-premises PKI you need to honour [@whfb-deploy] [@whfb-how-it-works]. Add FIDO2 security keys for the populations that need cross-device portability or strict phishing resistance: contractors, executives, IT administrators, anyone whose credential theft would be catastrophic [@webauthn-2] [@passwordless-strategy]. Do not pick Virtual Smart Cards for new deployments; the Microsoft Learn VSC Overview deprecation Warning quoted verbatim in §7 applies [@vsc-overview].&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Continue to operate it but plan migration to WHfB. Audit your recovery and re-enrolment process: a TPM clear destroys VSC keys irrecoverably, so any disaster-recovery plan that assumes you can move a credential between devices is wrong [@vsc-understanding]. Do not assume your VSC deployment is &quot;supported&quot; the way it was in 2014; the deprecation Warning quoted in §7 applies here [@vsc-overview]. The cleanest exit path is to enrol the same users into WHfB cert-trust against your existing PKI, then retire the VSC layer once the WHfB credential is operational.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; FIDO2 security keys with attested device-bound credentials [@webauthn-2] [@ctap-2-1], paired with Microsoft Entra ID passkeys. Use attestation-required profiles for high-assurance populations (so the relying party can verify the authenticator hardware) and attestation-optional profiles for less sensitive populations who benefit from synced-passkey recovery [@entra-passkeys-howto] [@entra-passwordless]. The trade-off remains: device-bound passkeys are attestable but not portable; synced passkeys are portable but not attestable. Match the profile to the population, not the population to the profile.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;For the architect who wants to see how PKINIT freshness enforcement would work if the RFC 8070 extension were enforced, the JavaScript below simulates the nonce check. The KDC issues a freshness token; the client includes it in the signed &lt;code&gt;PKAuthenticator&lt;/code&gt;; the KDC verifies that the token in the signed structure matches the one it issued. This is illustrative protocol behaviour, not the Windows default today.&lt;/p&gt;
&lt;p&gt;{`
function kdcIssueFreshness() {
  const token = Math.random().toString(16).slice(2, 18);
  return { token, issuedAt: Date.now() };
}&lt;/p&gt;
&lt;p&gt;function clientSignAuthPack({ freshness, cardSign }) {
  const pkAuthenticator = {
    cusec: 0,
    ctime: Date.now(),
    nonce: Math.floor(Math.random() * 1e9),
    freshness: freshness.token,
    paChecksum: &apos;sha256-of-paData&apos;,
  };
  const signature = cardSign(JSON.stringify(pkAuthenticator));
  return { pkAuthenticator, signature };
}&lt;/p&gt;
&lt;p&gt;function kdcVerify({ pkAuthenticator, signature }, issued) {
  const tooOld = Date.now() - issued.issuedAt &amp;gt; 5 * 60 * 1000;
  if (tooOld) return { ok: false, reason: &apos;freshness token too old&apos; };
  if (pkAuthenticator.freshness !== issued.token) {
    return { ok: false, reason: &apos;freshness token does not match&apos; };
  }
  return { ok: true };
}&lt;/p&gt;
&lt;p&gt;const issued = kdcIssueFreshness();
const cardSign = (msg) =&amp;gt; &apos;sig(&apos; + msg.length + &apos;)&apos;;
const signed = clientSignAuthPack({ freshness: issued, cardSign });&lt;/p&gt;
&lt;p&gt;console.log(&apos;Honest client:&apos;, kdcVerify(signed, issued));&lt;/p&gt;
&lt;p&gt;const replayed = { ...signed, pkAuthenticator: { ...signed.pkAuthenticator, freshness: &apos;stale-token-1234&apos; } };
console.log(&apos;Replayed with stale token:&apos;, kdcVerify(replayed, issued));
`}&lt;/p&gt;
&lt;p&gt;Whichever method you choose, no method alone defeats the legacy compatibility surfaces the card was never designed to police. The structural fix lives in the protocol-removal programme finishing through 2026 and beyond.&lt;/p&gt;
&lt;h2&gt;11. Frequently Asked Questions&lt;/h2&gt;

Yes functionally and cryptographically; no physically. A VSC exposes the same PC/SC card edge, Microsoft Smart Card KSP, and minidriver model as a physical card. Above the minidriver layer, every Windows component sees it as a smart card. Tamper-resistance comes from the host TPM rather than a removable IC; Microsoft Learn lists TPM 1.2 as the documented minimum -- VSCs predate TPM 2.0 [@vsc-overview] [@vsc-understanding].

No, by construction. The card signs internally and returns the signature. The only material that leaves during normal operation is the signed output (or, for key exchange, an unwrapped symmetric session key the card has decrypted with the wrapping key). The private key is generated on-card during enrolment and cannot be extracted; that property is the load-bearing security claim of the entire lineage.

Legacy NTLM compatibility. Many pre-Windows-2000 services speak only NTLM, and accounts flagged &quot;smart card required for interactive logon&quot; must still authenticate to them. KB 2871997 (May 13, 2014) added auto-rotation of the secondary credential at logon, reducing but not eliminating the attack surface [@kb-2871997]. The structural fix is NTLM removal: NTLMv1 has now been removed in Windows 11 24H2 and Windows Server 2025 [@ntlmv1-removal].

Yes. The YubiKey 5 series exposes a PIV applet that the inbox `msclmd.dll` minidriver recognises out of the box [@yubico-piv] [@inbox-minidriver]. Insert the YubiKey and Windows treats it as a PIV-compliant smart card; the same enrolment, PKINIT, and lock-screen workflows apply. The YubiKey 5 can act as a FIDO2 authenticator concurrently, which is the practical way to bridge smart-card and origin-bound passkey workflows on the same device.

Conditionally. PKINIT signs an `AuthPack` containing a nonce and a paChecksum; with the RFC 8070 freshness extension and a correctly validated KDC certificate, an attacker cannot trivially replay or relay an `AuthPack` signed by the client&apos;s smart card [@rfc-4556] [@rfc-8070]. But PKINIT is not origin-bound in the WebAuthn sense -- the card has no notion of which KDC the signature is for. If a trust assumption fails (an attacker plants a certificate in the client&apos;s NTAuth store, for example), the card will happily sign for the wrong KDC. WebAuthn&apos;s RP-ID-bound assertion is a stronger guarantee [@webauthn-2].

See the §6 Callout &quot;VSCs predate TPM 2.0&quot; for the full timeline. TPM 1.2 is the documented minimum; TPM 2.0 is the practical choice on Windows 11, which itself requires TPM 2.0 for the OS [@vsc-overview].

Three reasons, all expanded in §7: provisioning UX, TPM-clear recovery, and the multi-device world. Windows Hello for Business delivered the same TPM-bound-key benefits without the PC/SC abstraction cost (no virtual reader, no virtual minidriver, no APDU layer); FIDO2 then added cross-device portability and origin binding, neither of which the VSC architecture could deliver. The Microsoft Learn VSC Overview deprecation Warning quoted verbatim in §7 makes the recommendation explicit [@vsc-overview] [@passwordless-strategy].

Both are CNG Key Storage Providers. The Smart Card KSP routes calls through the minidriver to either a physical card or a TPM VSC; the cryptographic operation is APDU-encoded and sent to the card. The Platform Crypto Provider routes calls directly to the TPM via TPM Base Services; there is no card abstraction in the path. Windows Hello for Business uses the Platform Crypto Provider for TPM-bound key operations [@cng-ksp-list] [@whfb-how-it-works].
&lt;p&gt;The card was always a metaphor. The cryptographic primitive at its centre -- a non-exportable asymmetric key, bound to a tamper-resistant element, gated by a local gesture -- is the longest-lived object in this lineage. Every generation transition (PC/SC -&amp;gt; CryptoAPI/CNG -&amp;gt; inbox PIV/GIDS -&amp;gt; Virtual Smart Card -&amp;gt; WHfB -&amp;gt; FIDO2) was a transition of the &lt;em&gt;interface around&lt;/em&gt; that primitive, not of the primitive itself. The May 2014 contractor whose CAC signed the right blob and lost her account anyway was the canary; the fix she needed was not on her card but in a decade-long programme to remove the OS-minted secondary credentials that lived outside the card&apos;s authority. Windows is most of the way through that programme now. The card that wasn&apos;t a card outgrew its metaphor -- and the protection it always promised is, finally, arriving at the authentication outcome.&lt;/p&gt;
&lt;p&gt;&amp;lt;StudyGuide slug=&quot;smart-cards-and-virtual-smart-cards-in-windows-the-card-centric-auth-lineage&quot; keyTerms={[
  { term: &quot;APDU&quot;, definition: &quot;Application Protocol Data Unit. The request/response unit a host application exchanges with a smart card; header CLA INS P1 P2, optional Lc/data/Le, response SW1 SW2.&quot; },
  { term: &quot;PC/SC&quot;, definition: &quot;Personal Computer/Smart Card. The 1996 industry consortium and its specification series for how a smart card reader is exposed to a desktop OS.&quot; },
  { term: &quot;PKINIT&quot;, definition: &quot;Public Key Cryptography for Initial Authentication in Kerberos. Lets a client present an X.509 certificate as Kerberos pre-authentication instead of a password-derived shared secret.&quot; },
  { term: &quot;AuthPack&quot;, definition: &quot;The PKINIT structure containing PKAuthenticator and Diffie-Hellman parameters that the client signs and embeds in the PA-PK-AS-REQ pre-authentication data of the Kerberos AS-REQ.&quot; },
  { term: &quot;CSP&quot;, definition: &quot;Cryptographic Service Provider. A CryptoAPI 1.0 plug-in providing cryptographic services to applications, loaded in-process.&quot; },
  { term: &quot;KSP&quot;, definition: &quot;Key Storage Provider. The CNG-era plug-in for key storage and asymmetric cryptographic operations, with Microsoft Smart Card KSP for cards and VSCs and Microsoft Platform Crypto Provider for direct TPM access.&quot; },
  { term: &quot;Minidriver&quot;, definition: &quot;A small per-card DLL loaded by the Microsoft Base Smart Card CSP and Smart Card KSP that contains card-specific behaviour; the inbox msclmd.dll covers PIV and GIDS cards out of the box.&quot; },
  { term: &quot;Virtual Smart Card&quot;, definition: &quot;A TPM-backed software smart card introduced in Windows 8 in October 2012; exposes the same PC/SC card edge as a physical card with the TPM as backing chip.&quot; },
  { term: &quot;NTLM secondary credential&quot;, definition: &quot;The NT hash Windows maintains for smart-card-only accounts so legacy NTLM-accepting services continue to authenticate the user; harvestable from LSASS and replayable in pass-the-hash attacks.&quot; },
  { term: &quot;KB 2871997&quot;, definition: &quot;Microsoft Security Advisory of May 13, 2014; added TokenLeakDetectDelaySecs, the Protected Users group, and LSA Protection / RunAsPPL to mitigate the credential leakage class disclosed in 2014.&quot; },
  { term: &quot;Protected Users&quot;, definition: &quot;A Windows Server 2012 R2 security group whose members cannot use NTLM, DES, or RC4 in Kerberos pre-auth and cannot delegate.&quot; },
  { term: &quot;Credential Guard&quot;, definition: &quot;VBS-based isolation of LSA credential material in the LSAISO container; enabled by default on Windows 11 22H2 and Windows Server 2025 hardware-eligible domain-joined systems.&quot; },
  { term: &quot;RFC 8070&quot;, definition: &quot;PKINIT Freshness Extension, February 2017. Adds a KDC-issued freshness token to the signed PKAuthenticator, closing the relay window present in RFC 4556.&quot; },
  { term: &quot;WHfB key-trust&quot;, definition: &quot;Windows Hello for Business deployment in which the TPM-bound public key is registered directly with the identity provider (Microsoft Entra ID); no X.509 certificate is required.&quot; },
  { term: &quot;WHfB cert-trust&quot;, definition: &quot;Windows Hello for Business deployment in which an X.509 certificate is issued for the TPM-bound key by an enterprise PKI, allowing PKINIT-style authentication to downstream services.&quot; },
  { term: &quot;Microsoft Platform Crypto Provider&quot;, definition: &quot;A CNG KSP that talks directly to the TPM, used by Windows Hello for Business and by other modern Windows components that want TPM-bound keys without the smart card abstraction layer.&quot; },
  { term: &quot;FIDO2&quot;, definition: &quot;The FIDO Alliance and W3C specifications (WebAuthn and CTAP) for public-key authentication to relying parties, with origin binding to the RP ID.&quot; },
  { term: &quot;WebAuthn&quot;, definition: &quot;The W3C Web Authentication API; the relying-party-facing part of FIDO2.&quot; },
  { term: &quot;RP ID&quot;, definition: &quot;Relying Party Identifier. In WebAuthn, the domain name or registrable suffix to which a credential is scoped; the authenticator refuses to sign assertions for any other RP ID.&quot; }
]} /&amp;gt;&lt;/p&gt;
</content:encoded><category>smart-cards</category><category>virtual-smart-cards</category><category>pkinit</category><category>kerberos</category><category>windows-security</category><category>tpm</category><category>windows-hello-for-business</category><category>fido2</category><author>noreply@paragmali.com (Parag Mali)</author></item><item><title>WebAuthn and Passkeys on Windows: From CTAP to the Credential Provider Model</title><link>https://paragmali.com/blog/webauthn-and-passkeys-on-windows-from-ctap-to-the-credential/</link><guid isPermaLink="true">https://paragmali.com/blog/webauthn-and-passkeys-on-windows-from-ctap-to-the-credential/</guid><description>The know/have/are taxonomy collapses against modern phishing kits. Passkeys, WebAuthn Level 3, CTAP 2.x, and Windows 11 24H2 third-party providers score against the criteria that actually matter -- and recovery is the load-bearing column.</description><pubDate>Mon, 11 May 2026 00:00:00 GMT</pubDate><content:encoded>
**Password plus push-notification MFA is no longer a strong authenticator.** 2024-2026 adversary-in-the-middle phishing kits walk straight through it. WebAuthn and passkeys are strong -- but only if you score them against the right axes (phishing resistance, verifier-compromise resistance, replay/relay resistance, step-up, recovery), not the inherited know/have/are taxonomy. This article walks the five-axis criteria framework, the WebAuthn Level 3 plus CTAP 2.x protocol layer, and the Windows-specific stack: `webauthn.dll`, Windows Hello as the user-verification gesture, the Windows 11 24H2 third-party passkey provider plug-in model, hybrid transport from a phone, and the seven attestation conveyance formats. The thesis the article lands on: every passkey deployment in production is exactly as strong as the weakest path back into the account, and that path is universally weaker than the authentication ceremony itself.
&lt;h2&gt;1. Two factors, no security&lt;/h2&gt;
&lt;p&gt;A junior engineer at a mid-size firm types her Microsoft 365 credentials into what looks exactly like the real &lt;code&gt;login.microsoftonline&lt;/code&gt; page, approves the push notification on her phone, and an hour later the security team is reading her inbox -- because the attacker was, too. The kit is Tycoon 2FA, the technique is reverse-proxy adversary-in-the-middle, and the marketing claim that &quot;password plus MFA is two factors&quot; just lost to a commodity off-the-shelf service. The same class of phishing-as-a-service kit (Evilginx, Caffeine, EvilProxy, Tycoon 2FA) is the dominant phishing toolset in 2024-2026; the kit sits between the user and the real Microsoft login page, captures the credentials and the post-MFA session cookie in flight, and hands a live session to the attacker [@sekoia-tycoon-2fa].&lt;/p&gt;
&lt;p&gt;Replay the exact same attack against a colleague whose only authenticator is a WebAuthn passkey. The kit serves the look-alike page; the page hands the browser a WebAuthn &lt;code&gt;PublicKeyCredentialRequestOptions&lt;/code&gt; blob with a fresh challenge. The browser builds &lt;code&gt;clientDataJSON&lt;/code&gt; with &lt;code&gt;type: &quot;webauthn.get&quot;&lt;/code&gt;, the actual origin the user is on (the look-alike domain &lt;code&gt;login-microsoft0nline.example&lt;/code&gt;, protocol scheme included), and the challenge. The authenticator computes the RP-ID hash from that origin, looks up its stored credential, and finds nothing -- it never registered a passkey for that domain. There is no signature to relay. The kit gets bytes that the real Microsoft server will reject on the first verification step. Microsoft&apos;s own documentation puts it bluntly: passkeys &quot;use origin-bound public key cryptography, ensuring credentials can&apos;t be replayed or shared with malicious actors&quot; [@ms-entra-passwordless].&lt;/p&gt;
&lt;p&gt;The know/have/are taxonomy ranks these two ceremonies as the same. Password plus push is &quot;something you know&quot; plus &quot;something you have,&quot; and so is password plus a passkey on a YubiKey. The taxonomy predicts that both ceremonies are roughly twice as strong as one factor alone. The phishing kit demolishes one and bounces off the other. &lt;em&gt;The taxonomy is wrong.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The right question is not &quot;how many factors did the user produce?&quot; It is &quot;what does the attacker have to defeat?&quot; The know/have/are buckets group authenticators by what the user &lt;em&gt;feels&lt;/em&gt; they are producing. The criteria framework groups them by &lt;em&gt;what an attacker has to defeat&lt;/em&gt;. Only the second taxonomy predicts the outcome of a real-world attack. The phishing kit walks through password plus push because nothing in that ceremony binds the user&apos;s secret to a specific origin. It bounces off the passkey because the passkey signs over the origin the browser is actually on, and no amount of reverse proxying changes that string.&lt;/p&gt;
&lt;p&gt;If the taxonomy is wrong, what is the right one? That is the question §2 answers.&lt;/p&gt;
&lt;h2&gt;2. The criteria framework: five axes that actually predict outcomes&lt;/h2&gt;
&lt;p&gt;The replacement for know/have/are is a five-row table. The rows are &lt;em&gt;what an attacker has to defeat&lt;/em&gt;, not &lt;em&gt;what the user thinks they are producing&lt;/em&gt;. The spine of the table is taken from NIST SP 800-63-4 (final, August 2025) [@sp80063-4-final], NIST SP 800-63B-4 [@sp80063b4-html], the FIDO Alliance Authenticator Certification Levels [@fido-certification-levels], and the IETF channel-binding lineage that runs from RFC 5056 (Williams, November 2007) [@rfc5056] through RFC 9266 (Whited, July 2022) [@rfc9266].&lt;/p&gt;

An authenticator whose protocol prevents a relying party impersonator (an adversary-in-the-middle) from inducing the authenticator to release a usable credential value. NIST SP 800-63B-4 formalises the requirement as *verifier-impersonation resistance*. The practitioner formulation, courtesy of Yubico, is verbatim: an authenticator is phishing-resistant if it binds its output to a communication channel or a verifier name [@yubico-nist-guidance].
&lt;h3&gt;Axis 1: phishing resistance&lt;/h3&gt;
&lt;p&gt;The criterion: can a look-alike domain induce the user (or the user&apos;s authenticator) to release a credential value that the look-alike then replays to the real verifier? Password plus any unbound second factor (SMS-OTP, TOTP, push) fails the criterion -- the kit just forwards every value the user produces. WebAuthn passes it by construction: the authenticator signs over &lt;code&gt;clientDataJSON&lt;/code&gt;, which the &lt;em&gt;browser&lt;/em&gt; fills in with the actual origin the user is on, and the signature is computed jointly over a hash of the RP identifier derived from that origin. The RP refuses any signature whose RP-ID hash does not match the registered &lt;code&gt;rpId&lt;/code&gt;.&lt;/p&gt;

The mechanism by which WebAuthn enforces phishing resistance: the browser writes the user&apos;s actual origin into `clientDataJSON.origin`, the authenticator signs over the SHA-256 hash of the canonical RP identifier (`rpIdHash` in `authenticatorData`), and the relying party validates that `rpIdHash` matches the RP identifier under which the credential was registered. The cryptography is trivial. The value is in the binding.
&lt;p&gt;Microsoft&apos;s Entra documentation states the criterion verbatim: passkeys &quot;provide verifier impersonation resistance, which ensures an authenticator only releases secrets to the Relying Party (RP) the passkey was registered with and not an attacker pretending to be that RP&quot; [@ms-entra-passwordless].&lt;/p&gt;
&lt;h3&gt;Axis 2: verifier-compromise resistance&lt;/h3&gt;
&lt;p&gt;The criterion: if the relying party&apos;s authentication database is exfiltrated, can the attacker use the stolen material to log in? Passwords fail this criterion in the worst possible way -- a salted hash is replayable after offline cracking, and a billion-row password dump is the standard primary input to credential stuffing. The public-key model passes the criterion definitionally. The relying party stores only the credential&apos;s public key; no signature is ever made by the relying party. Even a complete database leak gives the attacker zero authenticators.&lt;/p&gt;
&lt;p&gt;This criterion is older than WebAuthn by half a century. Morris and Thompson&apos;s 1979 password paper made the verifier-compromise case for hashing passwords on a multi-user UNIX system [@morris-thompson-1979]; the WebAuthn move is the realisation that even bcrypt&apos;d password databases lose this criterion eventually, because the work factor that protects them today is one Moore&apos;s-law decade away from being trivial.&lt;/p&gt;
&lt;h3&gt;Axis 3: replay and relay resistance&lt;/h3&gt;
&lt;p&gt;The criterion: can an attacker who observes one successful authentication replay it later, or relay it to a different verifier? OTP-based ceremonies (HOTP [@rfc4226], TOTP [@rfc6238]) provide partial replay resistance via a per-instance counter or timestamp, but they offer almost no relay resistance: the AitM kit forwards the OTP through its proxy within the OTP&apos;s validity window.&lt;/p&gt;
&lt;p&gt;WebAuthn passes the criterion with three layered mechanisms. The first is a fresh challenge issued by the RP for every ceremony, which the authenticator signs over. The second is a per-credential signature counter included in &lt;code&gt;authenticatorData&lt;/code&gt;, monotonically increasing on each use (the relying party rejects any assertion whose counter is not strictly greater than the previous one, modulo the synced-passkey carve-out we will reach in §7). The third is channel binding -- the structurally correct answer to relay attacks, which sits at the TLS layer rather than the application layer.The IETF Token Binding stack (RFC 8471, RFC 8473, both October 2018) [@rfc8471] [@rfc8473] was the most ambitious attempt at the channel-binding criterion at the application layer. Both RFCs remain Proposed Standard at the IETF -- the datatracker history pages record no Historic reclassification event for either [@rfc8471-history] [@rfc8473-history] -- but Chromium removed support in version 70 in October 2018, the same month the RFCs were published, and no major browser has implemented them since [@wiki-token-binding]. The &lt;code&gt;clientDataJSON.tokenBinding&lt;/code&gt; field is therefore a no-op in 2026 production. WebAuthn solves the criterion above the channel by signing the origin into the assertion itself.&lt;/p&gt;
&lt;p&gt;The cleaner channel-binding answer is RFC 9266 &lt;code&gt;tls-exporter&lt;/code&gt; for TLS 1.3 (Whited, July 2022) [@rfc9266], which extends RFC 5056&apos;s channel-binding framework into the TLS 1.3 world -- but no major browser wires &lt;code&gt;tls-exporter&lt;/code&gt; into WebAuthn out of the box as of January 2026. The current WebAuthn deployment treats the origin string in &lt;code&gt;clientDataJSON&lt;/code&gt; as the primary channel binding, with HTTPS itself providing the underlying TLS guarantee.&lt;/p&gt;
&lt;h3&gt;Axis 4: step-up and session continuity&lt;/h3&gt;
&lt;p&gt;The criterion: can the relying party demand a &lt;em&gt;fresh&lt;/em&gt; authentication for a high-value action (transfer money, change password, invite a user), and can it tell the difference between a session that was authenticated with strong factors and one that was authenticated with weak factors? WebAuthn answers this with two flag bits in &lt;code&gt;authenticatorData&lt;/code&gt;. &lt;code&gt;UP&lt;/code&gt; (user present) is set when the authenticator detected a presence test -- a touch, a click, an NFC tap. &lt;code&gt;UV&lt;/code&gt; (user verified) is set when the authenticator additionally verified the user via PIN, biometric, or other gesture. A relying party that demands &lt;code&gt;userVerification: &quot;required&quot;&lt;/code&gt; can force &lt;code&gt;UV=1&lt;/code&gt; on the assertion; an RP that issues a fresh challenge for a high-value action gets a fresh signature tied to that challenge.&lt;/p&gt;
&lt;p&gt;Generic transactional confirmation -- &quot;sign a description of &lt;em&gt;this specific transaction&lt;/em&gt;&quot; -- was attempted in WebAuthn&apos;s earliest drafts via the &lt;code&gt;txAuthSimple&lt;/code&gt; and &lt;code&gt;txAuthGeneric&lt;/code&gt; extensions [@webauthn-fpwd]. Neither extension was ever implemented by browsers, and both are absent from the Level 3 specification surface as of January 2026 [@webauthn-l3-cr-dated]. The Secure Payment Confirmation flow in WebAuthn Level 3 [@webauthn-l3-cr] is the productised replacement for payment transactions; general transactional authorisation remains an open problem.&lt;/p&gt;
&lt;h3&gt;Axis 5: recovery and lifecycle&lt;/h3&gt;
&lt;p&gt;The heretical thesis: this is the only axis that matters in production, and it is the axis on which every modern platform still bottoms out at a single-factor primitive. We will foreshadow it here and land on it in §17. A passkey ceremony that scores AAL3 phishing-resistant at the authentication moment can be a single-factor SMS-OTP at the recovery moment -- and the &lt;em&gt;system&apos;s&lt;/em&gt; AAL is the recovery flow&apos;s AAL, not the authentication ceremony&apos;s. Microsoft&apos;s Entra documentation already flags account recovery as a load-bearing deployment cost: FIDO2 keys &quot;can increase costs for equipment, training, and helpdesk support -- especially when users lose their physical keys and need account recovery&quot; [@ms-entra-passwordless].&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The single most predictive question about an authentication system is not &quot;what factor does the user produce at sign-in?&quot; but &quot;what factor produces the credential when the user has lost the original one?&quot; We come back to this in §17.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;The criteria table as a spine&lt;/h3&gt;
&lt;p&gt;The five axes give the article its spine. Every later section fills in a row of the same five-column table. The columns are the strongest authenticators we have shipped: password, password plus SMS-OTP, password plus TOTP, password plus push with number matching, device-bound FIDO2 hardware key, synced passkey, and a hypothetical &quot;recovery-flow-aware&quot; composite. The criteria-aware ranking (§13) re-orders that table in a way the know/have/are taxonomy cannot.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; The know/have/are taxonomy groups authenticators by what the user feels they are producing. The criteria framework groups them by what an attacker has to defeat. Only the second taxonomy predicts the outcome of a real-world attack.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If these are the right axes, when did we figure that out?&lt;/p&gt;
&lt;h2&gt;3. Where the taxonomy came from&lt;/h2&gt;
&lt;p&gt;The know/have/are taxonomy did not appear all at once. The 1970s and 1980s operating-systems literature already grouped authentication factors into &quot;something the user knows,&quot; &quot;something the user has,&quot; and &quot;something the user is&quot; -- it was a way of talking about the design space, not a regulatory criterion. The taxonomy entered U.S. federal procurement via the Department of Defense&apos;s &lt;em&gt;Trusted Computer System Evaluation Criteria&lt;/em&gt; in December 1985 -- the Orange Book, DOD 5200.28-STD [@wiki-orange-book] -- which required identification and authentication at every assurance class above D and made passwords the canonical &lt;em&gt;something you know&lt;/em&gt; in federal IT. The Orange Book did not invent the taxonomy; it codified it.&lt;/p&gt;
&lt;p&gt;Two decades later, in June 2004, NIST canonised the same taxonomy as the U.S. federal regulatory framework. NIST SP 800-63 &lt;em&gt;Electronic Authentication Guideline&lt;/em&gt; -- by William Burr, Donna Dodson, and W. Timothy Polk -- defined four assurance levels and tied each to a combination of authenticator categories that the levels could accept [@sp80063-2004-v1] [@sp80063-2004-pdf]. Burr&apos;s framework absorbed two decades of accumulated practice with hardware OTP tokens. The canonical commercial OTP product, RSA SecurID, had shipped in 1986 -- a key fob that produced a fresh code each minute using a built-in clock and a factory-encoded seed [@wiki-rsa-securid] -- and SP 800-63 explicitly accepted SecurID-class authenticators at the higher assurance levels. The four-level structure (later AAL1 through AAL3 in the post-2017 redesign) lasted through SP 800-63-1 (2011), -2 (2013), -3 (2017), and -4 (2025); every revision is recognisably the same shape [@nist-sp80063-3-final].The CSRC bibliographic page for the 2004 first edition renders the leading author as a blank entry preceded by a stray comma, an artefact of Burr&apos;s retirement from NIST after publication. The actual cover-page authorship is Burr, Dodson, and Polk -- the citation in the references list above uses the correct three-name form.&lt;/p&gt;
&lt;p&gt;In parallel, the cryptographic protocol literature was building the &lt;em&gt;criteria&lt;/em&gt; taxonomy that would eventually displace know/have/are. Bellcore&apos;s Neil Haller published RFC 1760 in February 1995 -- the S/KEY one-time password system, a Lamport hash chain that produced a fresh login secret each time and that an eavesdropper could not replay [@rfc1760]. Haller&apos;s text already says the technique was first suggested by Leslie Lamport, which makes 1995 the first IETF standardisation of replay-resistance as a design criterion. RFC 4226 (HOTP, December 2005) [@rfc4226] and RFC 6238 (TOTP, May 2011) [@rfc6238] generalised the same idea into the synchronised counter and time-based variants the world now calls &quot;authenticator app&quot; codes.&lt;/p&gt;
&lt;p&gt;The verifier-impersonation criterion got its first IETF expression in November 2007. Nico Williams&apos; RFC 5056 &lt;em&gt;On the Use of Channel Bindings to Secure Channels&lt;/em&gt; defined the concept that &quot;the two end-points of a secure channel at one network layer are the same as at a higher layer,&quot; and bound authentication at the higher layer to the channel at the lower layer [@rfc5056]. RFC 5056 was the protocol-literature acknowledgement that authentication needed to be tied to &lt;em&gt;something the network attacker could not change&lt;/em&gt; -- the channel itself, not just the user&apos;s typing.&lt;/p&gt;
&lt;p&gt;Kim Cameron&apos;s &lt;em&gt;The Laws of Identity&lt;/em&gt;, published on identityblog.com in May 2005, captured the same idea from a higher-level perspective. The seven Laws are a framework for federated identity on the open Internet; Laws 2 (&quot;minimal disclosure for a constrained use&quot;) and 4 (&quot;directed identity&quot;) are the conceptual ancestors of WebAuthn&apos;s &lt;em&gt;origin binding&lt;/em&gt; and &lt;em&gt;per-RP key pair&lt;/em&gt; design [@identityblog-laws]. Cameron was Microsoft&apos;s Chief Architect of Identity through this period, and the Laws shaped a generation of Microsoft thinking on identity. The Laws preceded the consortium that would actually ship the protocol by eight years.&lt;/p&gt;

The criteria framework was *available* in the literature by 2007: replay resistance from S/KEY (1995), channel binding from RFC 5056 (2007), origin binding from Cameron&apos;s Laws of Identity (2005). It did not displace know/have/are in regulatory documents until NIST SP 800-63-3 in 2017 (which introduced the &quot;phishing-resistant authenticator&quot; term) and SP 800-63-4 in 2025 (which made verifier-impersonation resistance a first-class criterion). Why the gap? The know/have/are taxonomy is *legible to procurement* -- it produces neat checkboxes. The criteria taxonomy is *cryptographically meaningful* but produces fewer neat checkboxes. Regulation prefers checkboxes until breach data forces a change.

gantt
    title Authentication standards lineage, 1985-2026
    dateFormat YYYY
    axisFormat %Y
    section Regulatory codification
    Orange Book DOD 5200.28-STD :1985, 5y
    NIST SP 800-63 v1 :2004, 7y
    NIST SP 800-63-3 (phishing-resistant) :2017, 8y
    NIST SP 800-63-4 final :2025, 2y
    section Criteria origin (IETF/W3C)
    RFC 1760 S/KEY :1995, 10y
    RFC 4226 HOTP :2005, 6y
    RFC 5056 Channel binding :2007, 4y
    RFC 6238 TOTP :2011, 7y
    RFC 8471 Token Binding :2018, 1y
    RFC 9266 tls-exporter :2022, 4y
    section Identity literature
    Cameron Laws of Identity :2005, 8y
    section FIDO and W3C
    FIDO Alliance launch :2013, 1y
    FIDO U2F 1.0 :2014, 5y
    WebAuthn FPWD :2016, 3y
    WebAuthn L1 + CTAP 2.0 :2019, 2y
    WebAuthn L2 + CTAP 2.1 :2021, 1y
    Passkey commitment May 2022 :2022, 1y
    WebAuthn L3 CR :2023, 3y
    CTAP 2.2 PS :2025, 1y
    section Windows
    Windows 10 1903 webauthn.dll :2019, 3y
    Windows 11 22H2 ECC :2022, 2y
    Windows 11 24H2 plug-in model :2024, 2y
&lt;p&gt;By 2007 the criteria framework was on paper. By 2013 there was a consortium for it: the FIDO Alliance launched on 12 February 2013 [@fido-launch-pdf], with six founding members [@wiki-fido-alliance]. Earlier identity-layer attempts -- Mozilla Persona / BrowserID, launched July 2011, with decommissioning announced January 2016 and the service shut down on 30 November 2016 [@wiki-mozilla-persona] -- had tried to build a browser-mediated identity layer at the HTTP level and failed to achieve traction. The FIDO consortium took a different bet: solve the authentication ceremony first, leave the identity-layer above it to OIDC and SAML. What happened first in a browser?&lt;/p&gt;
&lt;h2&gt;4. U2F: the first browser ceremony designed against phishing&lt;/h2&gt;
&lt;p&gt;December 2014. Yubico, Google, and NXP Semiconductors publish FIDO 1.0 / Universal 2nd Factor (U2F) [@fido-u2f-overview]; U2F 1.0 reached Proposed Standard status on 9 October 2014, with the broader FIDO 1.0 announcement window running through December [@wiki-u2f]. The Universal 2nd Factor Wikipedia article catalogues the design tradeoffs explicitly: U2F&apos;s challenge-response is &quot;signed (encoding originating domain/website) to prevent interception and reuse&quot; [@wiki-u2f]. This was the first time a browser ceremony was designed against the phishing-resistance criterion as a &lt;em&gt;primary&lt;/em&gt; goal rather than as an afterthought.&lt;/p&gt;
&lt;p&gt;The U2F ceremony has five field-level moving parts. An &lt;em&gt;AppID&lt;/em&gt; string identifies the relying party, derived from the page&apos;s origin so a phisher&apos;s domain cannot produce a U2F signature for the real bank. A &lt;em&gt;challenge&lt;/em&gt; is a per-ceremony nonce the relying party generates. A &lt;em&gt;key handle&lt;/em&gt; is an opaque blob the authenticator returns at registration and supplies on every later assertion; the relying party uses it to address the right credential on the next challenge. A &lt;em&gt;signature counter&lt;/em&gt; increments monotonically on every assertion, letting the relying party detect simple cloning. And the &lt;em&gt;signature&lt;/em&gt; itself is an ECDSA P-256 signature over the AppID hash, the challenge, the counter, and a presence flag.&lt;/p&gt;
&lt;p&gt;The AppID rule is the load-bearing piece. The browser computes the AppID from the actual origin the user is on; the authenticator signs over its hash; the relying party compares it to the AppID under which the credential was registered. A look-alike domain produces a different AppID, which produces a different signature, which the real verifier rejects. This is the same trick WebAuthn will later generalise as &lt;code&gt;rpId&lt;/code&gt; binding -- and it is the trick that makes U2F structurally immune to the AitM kits that will demolish password plus push a decade later.&lt;/p&gt;
&lt;p&gt;The canonical deployment paper is &lt;em&gt;Security Keys: Practical Cryptographic Second Factors for the Modern Web&lt;/em&gt;, by Juan Lang, Alexei Czeskis, Dirk Balfanz, Marius Schilder, and Sampath Srinivas, in the Financial Cryptography 2016 preproceedings [@lang-fc2016-pdf]. The paper documents Google&apos;s internal rollout: a hardware second factor for every employee, replacing the company&apos;s previous OTP-based MFA. The empirical scoreboard for the criteria framework gets its first data point here -- after the rollout, Google reported zero phishing-related account takeovers on employee accounts during the deployment period. This is not a controlled study; it is the largest natural experiment in deployed phishing resistance the industry had seen.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; U2F is the moment the authentication community made a structural design choice: phishing resistance is a property of the &lt;em&gt;protocol&lt;/em&gt;, not of &lt;em&gt;user training&lt;/em&gt;. No amount of &quot;look for the lock icon&quot; advice closes the phishing gap; a protocol that signs over the origin closes it by construction.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;U2F&apos;s limitation is that it is, by design, a &lt;em&gt;second&lt;/em&gt; factor. The password under it remains the load-bearing weak link: a credential-stuffer can reuse the password against a service that does not require U2F, and a phisher can still capture the password even if they cannot capture the U2F signature. The AppID idea was correct; what was missing was the willingness to make the strong factor &lt;em&gt;the&lt;/em&gt; factor, not a layer on top of a weak one. The bridge from U2F to FIDO2 is exactly that move.&lt;/p&gt;
&lt;p&gt;The other piece U2F got right and FIDO2 inherited is the principle that the credential is &lt;em&gt;device-bound&lt;/em&gt; by default. The U2F Wikipedia summary captures the consequence: &quot;no recovery of the key is possible&quot; if the device is lost [@wiki-u2f]. This is the same property that makes synced passkeys, when they arrive in May 2022, a &lt;em&gt;productisation&lt;/em&gt; rather than a &lt;em&gt;cryptographic&lt;/em&gt; move. The bytes are the same. The lifecycle is different.&lt;/p&gt;
&lt;p&gt;If the second factor is doing all the work, why not make it &lt;em&gt;the&lt;/em&gt; factor?&lt;/p&gt;
&lt;h2&gt;5. FIDO2 + CTAP 2.0 + WebAuthn Level 1: the spec lands&lt;/h2&gt;
&lt;p&gt;March 4, 2019. The World Wide Web Consortium and the FIDO Alliance announced that the Web Authentication specification was an official W3C Recommendation [@w3c-fido-press-release]; the dated Recommendation slug is &lt;code&gt;REC-webauthn-1-20190304&lt;/code&gt; [@webauthn-l1-rec]. Same day, with January 30, 2019 as the underlying CTAP 2.0 Proposed Standard date [@ctap-2-0-ps]. The pair is what the industry markets as &lt;em&gt;FIDO2&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;The reframe was decisive. A &lt;em&gt;platform authenticator&lt;/em&gt; -- Windows Hello on Windows, Touch ID on macOS, the Android Keystore on Android -- was now a first-class FIDO authenticator. The user&apos;s laptop or phone could be the authenticator. The browser did not need a separate USB device; it could call into the OS instead. This is the move that made FIDO2 a consumer technology, not just a security-team technology.&lt;/p&gt;

The *relying party* is the web service that owns the user&apos;s account. The *rpId* is a string identifying that party for credential scoping; it must be a registrable suffix of the page&apos;s origin (so `login.bank.com` may use `bank.com` as its `rpId`, but `evil.com` may not). All WebAuthn signatures are made over the SHA-256 hash of the `rpId`, which the browser derives from the actual origin and writes into `clientDataJSON`. The relying party validates the signature against the public key registered for that `rpId`. Phishing resistance is `rpId` binding, full stop [@webauthn-l3-cr].
&lt;p&gt;The Web IDL surface that WebAuthn Level 1 standardised is small. &lt;code&gt;navigator.credentials.create({publicKey: ...})&lt;/code&gt; registers a new credential; &lt;code&gt;navigator.credentials.get({publicKey: ...})&lt;/code&gt; produces an assertion. Both return &lt;code&gt;PublicKeyCredential&lt;/code&gt; objects. The complexity is not in the API; it is in the byte-level structures the API exchanges.&lt;/p&gt;
&lt;p&gt;A registration ceremony looks like this. The relying party generates a &lt;code&gt;PublicKeyCredentialCreationOptions&lt;/code&gt; blob containing a fresh challenge, the &lt;code&gt;rpId&lt;/code&gt;, the user&apos;s account identifier, the list of algorithms the RP supports, the desired user verification, and an optional list of credentials the user already has. The browser passes this to the authenticator and gets back two byte blobs. The first is &lt;code&gt;clientDataJSON&lt;/code&gt; -- a UTF-8 JSON blob containing &lt;code&gt;type: &quot;webauthn.create&quot;&lt;/code&gt;, the origin the browser was actually on, and the challenge. The second is &lt;code&gt;authenticatorData&lt;/code&gt; -- a binary blob containing the &lt;code&gt;rpIdHash&lt;/code&gt; (SHA-256 of the canonical &lt;code&gt;rpId&lt;/code&gt;), the flags byte (with &lt;code&gt;UP&lt;/code&gt;, &lt;code&gt;UV&lt;/code&gt;, &lt;code&gt;AT&lt;/code&gt;, &lt;code&gt;ED&lt;/code&gt; bits), the signature counter (initially zero, sometimes non-zero), the new credential&apos;s identifier, the AAGUID identifying the authenticator model, and the credential&apos;s public key in COSE_Key format. An optional &lt;em&gt;attestation statement&lt;/em&gt; binds those bytes to a hardware root of trust.&lt;/p&gt;

A 16-byte identifier the authenticator includes in `authenticatorData` to identify its make and model. Some authenticators emit an all-zeros AAGUID for privacy. Microsoft&apos;s Entra ID hardware-vendor matrix lists dozens of FIDO2 keys with their AAGUIDs and supported transports [@ms-entra-fido2-hardware]; the FIDO Metadata Service is the authoritative directory.

sequenceDiagram
    participant U as User
    participant B as Browser
    participant A as Authenticator
    participant R as Relying Party
    R-&amp;gt;&amp;gt;B: PublicKeyCredentialCreationOptions {challenge, rpId, user, pubKeyAlgs}
    B-&amp;gt;&amp;gt;B: build clientDataJSON {type:create, origin, challenge}
    B-&amp;gt;&amp;gt;A: authenticatorMakeCredential(clientDataHash, rpId, user, ...)
    A-&amp;gt;&amp;gt;U: prompt for user gesture (UV)
    U-&amp;gt;&amp;gt;A: present gesture (PIN, fingerprint, face)
    A-&amp;gt;&amp;gt;A: generate (pubKey, privKey) and sign attestation
    A-&amp;gt;&amp;gt;B: clientDataJSON, authenticatorData, attestationStatement
    B-&amp;gt;&amp;gt;R: attestationResponse {clientDataJSON, attestationObject}
    R-&amp;gt;&amp;gt;R: verify origin, rpIdHash, signature, then store pubKey, credentialId
    R-&amp;gt;&amp;gt;U: account created
&lt;p&gt;An authentication ceremony is the same shape with one structural change: the RP supplies &lt;code&gt;PublicKeyCredentialRequestOptions&lt;/code&gt; with a fresh challenge, the authenticator finds the credential matching the &lt;code&gt;rpId&lt;/code&gt;, prompts the user for a gesture (if &lt;code&gt;userVerification&lt;/code&gt; is requested), and produces an &lt;em&gt;assertion&lt;/em&gt; -- a signature over &lt;code&gt;authenticatorData || SHA-256(clientDataJSON)&lt;/code&gt; with the credential&apos;s private key. The relying party verifies the signature against the stored public key.&lt;/p&gt;
&lt;p&gt;The Windows-side surface debuts in the same window. Microsoft Learn states verbatim that Microsoft &quot;introduced the W3C/Fast IDentity Online 2 (FIDO2) Win32 WebAuthn platform APIs in Windows 10 (version 1903)&quot; [@ms-learn-webauthn-apis]. May 2019. &lt;code&gt;webauthn.dll&lt;/code&gt; ships. From that moment on, every browser on Windows -- Edge, Chrome, Firefox, Brave -- talks WebAuthn through one Win32 surface. The Microsoft Learn passkey overview makes the underlying architecture explicit: &quot;When these APIs are in use, Windows 10 browsers or applications don&apos;t have direct access to the FIDO2 transports for FIDO-related messaging&quot; [@ms-learn-webauthn-apis]. The OS is the dispatcher.&lt;/p&gt;
&lt;p&gt;The W3C/FIDO press release named the launch implementations: Windows 10, Android, Chrome, Firefox, Edge, and Safari (in preview) [@w3c-fido-press-release]. Microsoft, Google, Mozilla, and Apple all shipped within the same year. WebAuthn became the most-implemented strong-authentication standard on the consumer web inside eighteen months.&lt;/p&gt;
&lt;p&gt;{`
// A reader can paste in their own clientDataJSON and authenticatorData
// (base64url-encoded as Microsoft returns them) to see how the parser
// walks the bytes. Origin binding is one SHA-256 invocation away from
// being a one-liner; the value is in the binding, not the cryptography.&lt;/p&gt;
&lt;p&gt;const clientDataB64 = &quot;eyJ0eXBlIjoid2ViYXV0aG4uZ2V0Iiwib3JpZ2luIjoiaHR0cHM6Ly9sb2dpbi5taWNyb3NvZnRvbmxpbmUuY29tIiwiY2hhbGxlbmdlIjoiUk5KU2V6NjFqdyJ9&quot;;
const authDataB64 = &quot;Y9JZsAcVeQOLgxs9Ux7QYZpyTaB-OkpdyPwQk7P9YsoFAAAAFw&quot;;&lt;/p&gt;
&lt;p&gt;function b64urlDecode(s) {
  s = s.replace(/-/g,&apos;+&apos;).replace(/_/g,&apos;/&apos;);
  while (s.length % 4) s += &apos;=&apos;;
  return Uint8Array.from(atob(s), c =&amp;gt; c.charCodeAt(0));
}&lt;/p&gt;
&lt;p&gt;const clientDataBytes = b64urlDecode(clientDataB64);
const clientData = JSON.parse(new TextDecoder().decode(clientDataBytes));
console.log(&quot;clientDataJSON.type     =&quot;, clientData.type);
console.log(&quot;clientDataJSON.origin   =&quot;, clientData.origin);
console.log(&quot;clientDataJSON.challenge=&quot;, clientData.challenge);&lt;/p&gt;
&lt;p&gt;const authData = b64urlDecode(authDataB64);
const rpIdHash = authData.slice(0, 32);
const flags = authData[32];
const signCount = (authData[33]&amp;lt;&amp;lt;24) | (authData[34]&amp;lt;&amp;lt;16) | (authData[35]&amp;lt;&amp;lt;8) | authData[36];
console.log(&quot;authenticatorData rpIdHash =&quot;, Array.from(rpIdHash).map(b=&amp;gt;b.toString(16).padStart(2,&apos;0&apos;)).join(&apos;&apos;));
console.log(&quot;authenticatorData flags    = 0x&quot; + flags.toString(16),
            &quot;UP=&quot;+(flags&amp;amp;1), &quot;UV=&quot;+((flags&amp;gt;&amp;gt;2)&amp;amp;1), &quot;BE=&quot;+((flags&amp;gt;&amp;gt;3)&amp;amp;1), &quot;BS=&quot;+((flags&amp;gt;&amp;gt;4)&amp;amp;1), &quot;AT=&quot;+((flags&amp;gt;&amp;gt;6)&amp;amp;1));
console.log(&quot;authenticatorData signCount=&quot;, signCount);
`}&lt;/p&gt;
&lt;p&gt;The credential&apos;s public key is encoded as a COSE_Key map -- a CBOR object whose algorithm identifier is one of the entries in the IANA COSE Algorithms registry [@iana-cose-registry]. As of the registry&apos;s 2026-03-04 update, no post-quantum algorithm is in WebAuthn-recommended status; ECDSA P-256 and EdDSA Ed25519 remain the workhorses. The companion &lt;em&gt;Post-Quantum Cryptography on Windows&lt;/em&gt; article walks the algorithm-side rollout.&lt;/p&gt;
&lt;p&gt;Level 1 settled the field-level shape. What did the next two years sharpen?&lt;/p&gt;
&lt;h2&gt;6. CTAP 2.1: the wire protocol every security key is speaking&lt;/h2&gt;
&lt;p&gt;15 June 2021. The FIDO Alliance published CTAP 2.1 as a Proposed Standard [@ctap-2-1-ps]. CTAP 2.1 is the CBOR-on-the-wire version most security keys in 2024-2026 are running; CTAP 2.2 (Proposed Standard, 14 July 2025) [@ctap-2-2-ps] refines a few corners, and CTAP 2.3 is the Proposed Standard the FIDO Alliance lists alongside it [@fido-specs-download]. Each version adds capability without breaking the previous one&apos;s commands.&lt;/p&gt;

The Client-to-Authenticator Protocol -- the wire format the browser speaks to a roaming authenticator over USB-HID, NFC, or BLE. CTAP1 (the original U2F messages) carries APDU-style binary structures; CTAP2 carries CBOR-encoded commands. A *CTAP2 authenticator* (also called a FIDO2 or WebAuthn authenticator) implements the CTAP2 command set; modern keys also implement CTAP1 for backwards compatibility [@ctap-2-0-ps].
&lt;p&gt;The CTAP2 command-byte table is the surface a browser actually dispatches to. Each command is a single byte followed by a CBOR-encoded request map. The table below names the commands in order and the criterion-table cell each one strengthens.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Command byte&lt;/th&gt;
&lt;th&gt;Command name&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;th&gt;Criterion strengthened&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;0x01&lt;/td&gt;
&lt;td&gt;&lt;code&gt;authenticatorMakeCredential&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Registration: generate a fresh keypair bound to &lt;code&gt;(rpId, user.id)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Phishing resistance (origin binding)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0x02&lt;/td&gt;
&lt;td&gt;&lt;code&gt;authenticatorGetAssertion&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Authentication: sign the challenge with the credential&apos;s private key&lt;/td&gt;
&lt;td&gt;Phishing + replay + verifier-compromise&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0x04&lt;/td&gt;
&lt;td&gt;&lt;code&gt;authenticatorGetInfo&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Capability discovery: list supported algorithms, extensions, transports, &lt;code&gt;UV&lt;/code&gt; modes&lt;/td&gt;
&lt;td&gt;Step-up (lets RP know what&apos;s available)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0x06&lt;/td&gt;
&lt;td&gt;&lt;code&gt;authenticatorClientPIN&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Manage the PIN, issue &lt;code&gt;pinUvAuthToken&lt;/code&gt; with permissions bitmap and &lt;code&gt;rpId&lt;/code&gt; scoping&lt;/td&gt;
&lt;td&gt;Step-up + replay&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0x07&lt;/td&gt;
&lt;td&gt;&lt;code&gt;authenticatorReset&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Wipe all resident credentials on the device&lt;/td&gt;
&lt;td&gt;Lifecycle&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0x09&lt;/td&gt;
&lt;td&gt;&lt;code&gt;authenticatorBioEnrollment&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;On-token fingerprint enrolment (CTAP 2.1)&lt;/td&gt;
&lt;td&gt;Step-up (&lt;code&gt;UV=1&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0x0A&lt;/td&gt;
&lt;td&gt;&lt;code&gt;authenticatorCredentialManagement&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;List, enumerate, and delete resident credentials per RP&lt;/td&gt;
&lt;td&gt;Lifecycle / recovery&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0x0B&lt;/td&gt;
&lt;td&gt;&lt;code&gt;authenticatorSelection&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&quot;Pick this device&quot; prompt when multiple authenticators are present&lt;/td&gt;
&lt;td&gt;UX (no criterion change)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0x0C&lt;/td&gt;
&lt;td&gt;&lt;code&gt;authenticatorLargeBlobs&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Per-credential blob store under the credential&lt;/td&gt;
&lt;td&gt;Step-up (extension data)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0x0D&lt;/td&gt;
&lt;td&gt;&lt;code&gt;authenticatorConfig&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Enable enterprise attestation, toggle &lt;code&gt;alwaysUv&lt;/code&gt;, set minimum PIN length&lt;/td&gt;
&lt;td&gt;Verifier-compromise + lifecycle&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Three pieces of CTAP 2.1 are worth pulling out because they meaningfully change the criteria-table cells.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;pinUvAuthToken&lt;/code&gt; and permissions.&lt;/strong&gt; CTAP 2.0&apos;s PIN-protocol let the browser obtain a &lt;code&gt;pinAuthToken&lt;/code&gt; and use it across any command. CTAP 2.1 introduced a &lt;em&gt;permissions bitmap&lt;/em&gt; and &lt;em&gt;rpId scoping&lt;/em&gt; on the token so that a token issued for &lt;em&gt;one&lt;/em&gt; relying party&apos;s ceremony cannot be replayed against a different relying party&apos;s ceremony on the same authenticator [@ctap-2-1-ps]. This closes a class of host-side mischief: an attacker who got the PIN out of one ceremony could not previously be stopped from spending it on a different &lt;code&gt;rpId&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;credProtect&lt;/code&gt;.&lt;/strong&gt; A new extension that lets the RP request a higher protection level on the resident credential -- specifically, that the authenticator should refuse to list the credential without a &lt;code&gt;UV=1&lt;/code&gt; gesture. The first generation of WebAuthn discoverable credentials were enumerable by any host that could speak CTAP2 to the connected key; &lt;code&gt;credProtect&lt;/code&gt; lets the RP say &quot;don&apos;t show this credential&apos;s existence to anything that doesn&apos;t pass user verification first.&quot;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Enterprise attestation.&lt;/strong&gt; CTAP 2.1 added an explicit &lt;em&gt;enterprise attestation&lt;/em&gt; mode in which the authenticator binds its attestation statement to a list of relying parties the device&apos;s enrolling organisation has pre-approved. This is the bridge that makes vendor attestation useful in managed enterprises without leaking the user&apos;s specific device identity to every relying party.The largeBlob extension (CTAP 2.1, command 0x0C) gives each credential a small per-credential blob store. RPs use it for things like cached short-lived tokens or per-user policy. The 2024 release notes for the Windows &lt;code&gt;webauthn.dll&lt;/code&gt; API surface flagged largeBlob support as one of the additions in Windows 11 22H2 [@ms-learn-webauthn-apis]; a March 2023 Review Draft [@ctap-2-2-rd] foreshadowed the 2.2 refinements that landed in July 2025.&lt;/p&gt;
&lt;p&gt;All of this is for experts. When did this stop being a security-team conversation and start being a consumer product? What changed in May 2022?&lt;/p&gt;
&lt;h2&gt;7. Passkeys: the productisation moment&lt;/h2&gt;
&lt;p&gt;5 May 2022. Apple, Google, and Microsoft jointly committed at the FIDO Alliance to a common passwordless sign-in standard [@fido-aav-passkey-commitment]. The press release is short on protocol detail and long on user-facing language. The headline commitment, verbatim: &quot;Allow users to automatically access their FIDO sign-in credentials (referred to by some as a &apos;passkey&apos;) on many of their devices, even new ones, without having to reenroll every account&quot; [@fido-aav-passkey-commitment]. &lt;em&gt;Passkey&lt;/em&gt; entered the public lexicon. Andrew Shikiar, the FIDO Alliance&apos;s executive director and CMO at the time, named it in the press call.&lt;/p&gt;

Allow users to automatically access their FIDO sign-in credentials (referred to by some as a &apos;passkey&apos;) on many of their devices, even new ones, without having to reenroll every account. -- Apple, Google, and Microsoft, joint FIDO Alliance announcement, 5 May 2022 [@fido-aav-passkey-commitment]
&lt;p&gt;The &lt;em&gt;cryptographic&lt;/em&gt; move in May 2022 was small. The protocol bytes are the same FIDO2 / WebAuthn / CTAP2 bytes that shipped in March 2019. What changed was twofold: (a) the three platform vendors aligned their sync fabrics so that a passkey created on a user&apos;s phone would appear on the user&apos;s laptop, and (b) the user-facing terminology consolidated from a confusing menagerie (&quot;discoverable credential,&quot; &quot;resident key,&quot; &quot;client-side discoverable credential&quot;) onto a single product term -- &lt;em&gt;passkey&lt;/em&gt;.&lt;/p&gt;

A WebAuthn credential whose `user.id` and account metadata are stored *on the authenticator*, so the authenticator can produce an assertion without the relying party first supplying a credential identifier. The CTAP 2.0 spec calls these *resident keys* [@ctap-2-0-ps]; the WebAuthn Level 2 spec calls them *client-side discoverable credentials* [@webauthn-l2-latest]; the May 2022 vendor commitment rebranded them as *passkeys* [@fido-aav-passkey-commitment]. All three terms refer to the same on-the-wire object.
&lt;p&gt;Discoverable credentials unlock &lt;em&gt;usernameless&lt;/em&gt; sign-in. The relying party does not need to tell the authenticator which credential to use; the authenticator looks up its own resident credentials for the supplied &lt;code&gt;rpId&lt;/code&gt;, shows the user the matching account, and asks for the user-verification gesture. This is the UX primitive every consumer-passkey flow leans on.&lt;/p&gt;
&lt;p&gt;WebAuthn Level 3 (W3C Candidate Recommendation, latest snapshot dated 13 January 2026 [@webauthn-l3-cr] [@webauthn-l3-cr-dated]) is the spec generation that productises passkeys. Level 3 standardises:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;hybrid transport&lt;/strong&gt; (formerly known as caBLE), §6.3.3 of the L3 spec, which lets a phone act as a roaming authenticator for a nearby laptop via QR code plus ephemeral ECDH plus BLE proximity. We cover hybrid in §12.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;JSON-serialisation helpers&lt;/strong&gt; -- &lt;code&gt;PublicKeyCredentialCreationOptionsJSON&lt;/code&gt; and &lt;code&gt;PublicKeyCredentialRequestOptionsJSON&lt;/code&gt; -- that make WebAuthn easier to drive from a server SDK without manual base64url juggling.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;getClientCapabilities()&lt;/code&gt;&lt;/strong&gt; so the relying party can probe what the client supports before issuing the ceremony.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;&lt;code&gt;credProps&lt;/code&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;code&gt;prf&lt;/code&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;code&gt;largeBlob&lt;/code&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;code&gt;credProtect&lt;/code&gt;&lt;/strong&gt;, and &lt;strong&gt;Secure Payment Confirmation&lt;/strong&gt; extensions, each of which sharpens one cell of the criteria table.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The mid-2025 cadence picked up: CTAP 2.2 Proposed Standard on 14 July 2025 [@ctap-2-2-ps] refined hybrid-transport semantics and tightened &lt;code&gt;credProtect&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The synced-vs-bound distinction is the structural new thing about passkeys. Before May 2022 a FIDO2 credential lived in one secure element; lose the YubiKey, lose the credential. Synced passkeys put the private key into a sync fabric -- Apple iCloud Keychain (originally 2013) [@wiki-icloud], Google Password Manager (Chrome password sync, late 2000s onward), Microsoft Authenticator (originally 2015) [@wiki-ms-authenticator], and Microsoft Account passkey sync (general availability for consumer accounts on 2 May 2024) [@ms-security-passkeys-consumer] -- and let it appear on every device the user signs into. The mechanism is end-to-end encryption against a sync-fabric key that the platform vendor cannot read; Apple&apos;s Advanced Data Protection model is the strongest current public realisation [@apple-adp-kb].&lt;/p&gt;
&lt;p&gt;The price: the long-term private key has &lt;em&gt;left&lt;/em&gt; the original authenticator. NIST is unambiguous about the consequence. The April 2024 supplement &lt;em&gt;Incorporating Syncable Authenticators into NIST SP 800-63B&lt;/em&gt; [@sp80063sup1] -- since absorbed into NIST SP 800-63B-4 final, July 2025 [@sp80063b4-html] -- classifies synced passkeys at AAL2, not AAL3, because the key is no longer pinned to a single tamper-resistant element. Yubico&apos;s commentary captures the dichotomy verbatim: &quot;FIDO passkeys that are not synced -- device-bound passkeys like YubiKeys -- and are properly stored in dedicated hardware have an AAL3 rating&quot; [@yubico-nist-guidance].&lt;/p&gt;
&lt;p&gt;The WebAuthn spec made the distinction &lt;em&gt;observable&lt;/em&gt;. Two new flag bits in &lt;code&gt;authenticatorData&lt;/code&gt; -- &lt;code&gt;BE&lt;/code&gt; (Backup Eligible) and &lt;code&gt;BS&lt;/code&gt; (Backup State) -- tell the relying party whether the credential is in principle syncable (&lt;code&gt;BE=1&lt;/code&gt;) and whether it is currently backed up (&lt;code&gt;BS=1&lt;/code&gt;) [@webauthn-l3-cr]. The RP can decide policy from those flags: a banking RP can require &lt;code&gt;BE=0&lt;/code&gt; (device-bound) credentials for AAL3 transactions, while accepting &lt;code&gt;BS=1&lt;/code&gt; (synced) credentials for AAL2 sign-in.&lt;/p&gt;
&lt;p&gt;Microsoft&apos;s own numbers tell the productisation story in raw counts. The May 2024 Microsoft Security blog announcing passkey support for consumer accounts notes that Microsoft was &quot;detecting around 115 password attacks per second&quot; when Windows Hello first shipped in 2015; &quot;less than a decade later, that number has surged 3,378% to more than 4,000 password attacks per second&quot; [@ms-security-passkeys-consumer]. The 1 May 2025 World Passkey Day post escalates again: &quot;we observed a staggering 7,000 password attacks per second (more than double the rate from 2023). [...] now we see nearly a million passkeys registered every day.&quot; It also reports that &quot;passkey sign-ins are eight times faster than a password and multifactor authentication,&quot; and that &quot;more than 99% of people who sign into their Windows devices with their Microsoft account do so using Windows Hello&quot; [@ms-security-world-passkey-day].&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; Passkeys are not a new cryptographic primitive. They are a productisation moment in which discoverable credentials became consumer-grade UX. The protocol moves were two years earlier; the product move is what changed the criteria-table scoreboard.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Passkeys are a &lt;em&gt;productisation&lt;/em&gt; moment. On Windows specifically, what does the platform actually do between &lt;code&gt;navigator.credentials.create&lt;/code&gt; and the TPM?&lt;/p&gt;
&lt;h2&gt;8. The Windows platform authenticator: &lt;code&gt;webauthn.dll&lt;/code&gt; end-to-end&lt;/h2&gt;
&lt;p&gt;May 2019. Windows 10 version 1903. The Win32 platform WebAuthn API shipped, and from that moment on every browser and every native application on Windows that wants to do WebAuthn calls &lt;code&gt;webauthn.dll&lt;/code&gt;. The header file &lt;code&gt;webauthn.h&lt;/code&gt; is in the Windows SDK and is also published on GitHub at &lt;code&gt;github.com/microsoft/webauthn&lt;/code&gt; [@github-ms-webauthn]. The reference page on Microsoft Learn enumerates every function the API surfaces [@ms-learn-win32-webauthn]. The 1903 ship date and the subsequent feature additions are documented verbatim by Microsoft Learn: &quot;Microsoft has long been a proponent of passwordless authentication, and has introduced the W3C/Fast IDentity Online 2 (FIDO2) Win32 WebAuthn platform APIs in Windows 10 (version 1903). Starting in &lt;strong&gt;Windows 11, version 22H2&lt;/strong&gt;, WebAuthn APIs support ECC algorithms and starting in &lt;strong&gt;Windows 11 version 24H2&lt;/strong&gt; WebAuthn APIs support plugin passkey managers&quot; [@ms-learn-webauthn-apis].&lt;/p&gt;

When these APIs are in use, Windows 10 browsers or applications don&apos;t have direct access to the FIDO2 transports for FIDO-related messaging. -- Microsoft Learn, *WebAuthn APIs for password-less authentication on Windows* [@ms-learn-webauthn-apis]
&lt;p&gt;That sentence is the entire architectural premise. The OS dispatches FIDO2 ceremonies. The browser does not own the CTAP2 stack, the USB-HID transport, the NFC reader, the BLE pairing, or the Hello UV gesture. It hands &lt;code&gt;webauthn.dll&lt;/code&gt; a request and gets back an assertion.&lt;/p&gt;
&lt;p&gt;The API surface is a small set of functions. The ceremony surface is two functions, the management surface is the remainder.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;WebAuthNAuthenticatorMakeCredential&lt;/code&gt;&lt;/strong&gt; -- the registration entry point. Caller supplies origin / &lt;code&gt;rpId&lt;/code&gt; / user / algorithms / attestation preference / authenticator-selection criteria. Returns an attestation object.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;WebAuthNAuthenticatorGetAssertion&lt;/code&gt;&lt;/strong&gt; -- the authentication entry point. Caller supplies origin / &lt;code&gt;rpId&lt;/code&gt; / allowed credential IDs (or empty for usernameless) / user-verification preference / mediation (Conditional UI, see §9). Returns an assertion.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;WebAuthNGetApiVersionNumber&lt;/code&gt;&lt;/strong&gt; -- a monotonically increasing integer that lets callers feature-detect. Version 1 is Windows 10 1903; versions step up as Windows adds ECC algorithms (22H2), the plugin model (24H2), and the EXPERIMENTAL_*2 surface (Insider builds via KB5072046 [@github-ms-webauthn]).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;WebAuthNGetCancellationId&lt;/code&gt;&lt;/strong&gt; / &lt;strong&gt;&lt;code&gt;WebAuthNCancelCurrentOperation&lt;/code&gt;&lt;/strong&gt; -- cooperative cancellation; the browser asks &lt;code&gt;webauthn.dll&lt;/code&gt; to drop the active ceremony.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;WebAuthNGetPlatformCredentialList&lt;/code&gt;&lt;/strong&gt; / &lt;strong&gt;&lt;code&gt;WebAuthNDeletePlatformCredential&lt;/code&gt;&lt;/strong&gt; -- resident-credential management for synced passkeys held by the OS provider.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;WebAuthNIsUserVerifyingPlatformAuthenticatorAvailable&lt;/code&gt;&lt;/strong&gt; -- the &lt;code&gt;isUVPAA&lt;/code&gt; capability probe; the RP uses this to decide whether to offer a passkey enrolment flow at all.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;WebAuthNFreeAssertion&lt;/code&gt;&lt;/strong&gt; / &lt;strong&gt;&lt;code&gt;WebAuthNFreeCredentialAttestation&lt;/code&gt;&lt;/strong&gt; / &lt;strong&gt;&lt;code&gt;WebAuthNFreePlatformCredentialList&lt;/code&gt;&lt;/strong&gt; -- caller-side memory release; the OS allocates on the heap and the caller is responsible for &lt;code&gt;Free&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;WebAuthNGetErrorName&lt;/code&gt;&lt;/strong&gt; / &lt;strong&gt;&lt;code&gt;WebAuthNGetW3CExceptionDOMError&lt;/code&gt;&lt;/strong&gt; -- translate the Win32 &lt;code&gt;HRESULT&lt;/code&gt; into a WebAuthn-spec error string.&lt;/li&gt;
&lt;/ul&gt;

flowchart TD
    A[Browser or native app] --&amp;gt; B[webauthn.dll: WebAuthNAuthenticatorMakeCredential]
    B --&amp;gt; C[Windows Hello UI: prompt for PIN, fingerprint, or face]
    C --&amp;gt; D[Windows Hello / Hello for Business: verify gesture]
    D --&amp;gt; E[CNG NCRYPT: keypair generation request]
    E --&amp;gt; F[TPM 2.0: generate keypair inside the TPM]
    F --&amp;gt; G[TPM 2.0: TPM2_Certify over the new credential public key]
    G --&amp;gt; H[webauthn.dll: build attestation object with packed or tpm format]
    H --&amp;gt; B
    B --&amp;gt; A
    A --&amp;gt; I[Relying party: verify attestation, store credential public key]
&lt;p&gt;The criteria-framework consequence of that call graph is that &lt;em&gt;the private key never leaves the TPM&lt;/em&gt;. Microsoft Learn states the property verbatim: &quot;The private keys can only be used after they&apos;re unlocked by the user using the Windows Hello unlock factor (biometrics or PIN)&quot; [@ms-learn-passkeys]. The TPM enforces use through its own access-control rules; even kernel malware on the host cannot exfiltrate the raw private key, only request operations gated on the user&apos;s gesture. This is what gets a Windows-platform-bound passkey on a TPM to AAL3 even when synced passkeys are bounded at AAL2.&lt;/p&gt;
&lt;p&gt;The API version sentinel tells a clean feature-evolution story.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Windows release&lt;/th&gt;
&lt;th&gt;API version (approx.)&lt;/th&gt;
&lt;th&gt;Notable additions&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Windows 10 1903 (May 2019)&lt;/td&gt;
&lt;td&gt;v1&lt;/td&gt;
&lt;td&gt;Initial Win32 surface: make/get credential, isUVPAA&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Windows 10 1909 / 20H1&lt;/td&gt;
&lt;td&gt;v2&lt;/td&gt;
&lt;td&gt;UV preference, signal-handling refinements&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Windows 11 21H2 (Oct 2021)&lt;/td&gt;
&lt;td&gt;v3&lt;/td&gt;
&lt;td&gt;Hybrid transport (caBLE) entrypoints&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Windows 11 22H2 (Sep 2022)&lt;/td&gt;
&lt;td&gt;v4-v5&lt;/td&gt;
&lt;td&gt;ECC algorithms (ECDSA P-256 platform credentials), Conditional UI mediation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Windows 11 23H2 (Oct 2023)&lt;/td&gt;
&lt;td&gt;v6&lt;/td&gt;
&lt;td&gt;largeBlob, credProps, refined cancellation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Windows 11 24H2 (Oct 2024)&lt;/td&gt;
&lt;td&gt;v7&lt;/td&gt;
&lt;td&gt;Plug-in passkey managers (&lt;code&gt;WebAuthNPlugin*&lt;/code&gt;), redesigned Hello UX&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Insider builds (KB5072046)&lt;/td&gt;
&lt;td&gt;v7+&lt;/td&gt;
&lt;td&gt;EXPERIMENTAL_WebAuthNPluginAddAuthenticator2, EXPERIMENTAL_WebAuthNPluginPerformUserVerification2, EXPERIMENTAL_WebAuthNPluginUpdateAuthenticatorDetails2 [@github-ms-webauthn]&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The three &lt;code&gt;EXPERIMENTAL_*2&lt;/code&gt; APIs in &lt;code&gt;github.com/microsoft/webauthn&lt;/code&gt; are Insider-only and will lose the &lt;code&gt;EXPERIMENTAL_&lt;/code&gt; prefix as they stabilise. The naming convention is the standard Windows SDK signal for &quot;we want feedback before this becomes load-bearing public API.&quot;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; On Windows, do not roll your own CTAP2 stack. &lt;code&gt;webauthn.dll&lt;/code&gt; handles USB-HID, NFC, BLE, hybrid transport, Conditional UI, plug-in dispatch, and Windows Hello user verification in a single call. The Win32 reference at &lt;code&gt;learn.microsoft.com/en-us/windows/win32/api/webauthn/&lt;/code&gt; is the source of truth, the header file is at &lt;code&gt;github.com/microsoft/webauthn&lt;/code&gt;, and the YubiKey 5 series [@yubikey5-overview] plus the Entra-listed FIDO2 vendors [@ms-entra-fido2-hardware] are the supported keys.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The criterion-table consequence of dispatching FIDO2 through one OS surface is that &lt;em&gt;every browser is automatically as strong as the OS&lt;/em&gt;. Edge does not need its own attestation logic; neither does Chrome, Firefox, or Brave. They all call the same &lt;code&gt;webauthn.dll&lt;/code&gt;, which routes the registration to the TPM (for platform-bound passkeys), to USB-HID (for roaming security keys), or to a plug-in (for Windows 11 24H2 third-party providers, §10).&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;webauthn.dll&lt;/code&gt; surface answers one half of the question. The other half is: what does the user actually &lt;em&gt;see&lt;/em&gt;?&lt;/p&gt;
&lt;p&gt;{`
// Origin binding is computationally trivial. The value is in the binding,
// not the cryptography. This snippet computes SHA-256 of an origin&apos;s
// effective rpId and compares against the rpIdHash a real authenticator
// would have signed. Paste in a clientDataJSON.origin and the
// authenticatorData.rpIdHash from the earlier snippet to verify.&lt;/p&gt;
&lt;p&gt;async function rpIdHash(rpId) {
  const enc = new TextEncoder().encode(rpId);
  const hash = await crypto.subtle.digest(&quot;SHA-256&quot;, enc);
  return Array.from(new Uint8Array(hash)).map(b =&amp;gt; b.toString(16).padStart(2,&apos;0&apos;)).join(&apos;&apos;);
}&lt;/p&gt;
&lt;p&gt;(async () =&amp;gt; {
  const goodOrigin = &quot;login.microsoftonline.example&quot;;
  const badOrigin  = &quot;login-microsoft0nline.example&quot;;
  const goodRpId   = &quot;login.microsoftonline.example&quot;;
  const badRpId    = &quot;login-microsoft0nline.example&quot;;
  console.log(&quot;rpIdHash(&quot;, goodRpId, &quot;) =&quot;, await rpIdHash(goodRpId));
  console.log(&quot;rpIdHash(&quot;, badRpId,  &quot;) =&quot;, await rpIdHash(badRpId));
  // The two hashes differ in every byte. A passkey registered against
  // login.microsoftonline.example cannot be induced to sign for the look-alike
  // because the authenticator computes the second hash from clientDataJSON.origin
  // and refuses to use the credential bound to the first one.&lt;/p&gt;
&lt;p&gt;  // Replay resistance illustration: a signCount of 0x10 followed by 0x0F
  // is illegal (counter regressed). RPs reject this for BS=0 credentials.
  const oldCount = 0x10, newCount = 0x0F;
  console.log(&quot;signCount regression (BS=0)?&quot;, newCount &amp;lt;= oldCount ? &quot;REJECT&quot; : &quot;ACCEPT&quot;);
})();
`}&lt;/p&gt;
&lt;h2&gt;9. Conditional UI: passkey autofill that looks like password autofill&lt;/h2&gt;
&lt;p&gt;The bridge between users&apos; password-trained mental model and the new asymmetric-crypto reality is a UX primitive called Conditional Mediation -- the spec name -- or &lt;em&gt;Conditional UI&lt;/em&gt; in informal use. The relying party renders a normal-looking username field. The browser sees that the page has called &lt;code&gt;navigator.credentials.get({mediation: &quot;conditional&quot;, publicKey: {...}})&lt;/code&gt; and quietly offers the user&apos;s passkey as one of the autofill suggestions, alongside whatever the user has typed and whatever the password manager remembers. The user clicks the passkey suggestion, completes a Windows Hello gesture, and they are signed in. No popup. No modal. No &quot;do you want to use a passkey?&quot; dialog.&lt;/p&gt;

A WebAuthn invocation mode in which the browser offers the user&apos;s discoverable credentials *inside* the same autofill UI it uses for saved passwords, rather than via a modal credential picker. The relying party calls `navigator.credentials.get({mediation: &quot;conditional&quot;, publicKey: {...}})`; the browser silently consults the platform authenticator (and, on Windows 11 24H2, the plug-in passkey providers) for credentials matching the `rpId`. The capability is probed via `PublicKeyCredential.isConditionalMediationAvailable()` [@webauthn-l3-cr].
&lt;p&gt;The canonical engineer-perspective walkthrough is Adam Langley&apos;s &lt;em&gt;Passkeys&lt;/em&gt; post on imperialviolet.org, dated 22 September 2022 [@imperialviolet-passkeys]. Langley walks the flag-page invocation needed on early Chrome Canary builds -- &lt;code&gt;chrome://flags#webauthn-conditional-ui&lt;/code&gt; -- and the capability surface: &lt;code&gt;isUserVerifyingPlatformAuthenticatorAvailable()&lt;/code&gt; to decide whether to offer enrolment, &lt;code&gt;isConditionalMediationAvailable()&lt;/code&gt; to decide whether to render the autofill hint at all. The post is the first time most working engineers saw what passkeys would actually look like at the page level.&lt;/p&gt;
&lt;p&gt;On Windows the browser calls &lt;code&gt;WebAuthNAuthenticatorGetAssertion&lt;/code&gt; with the Conditional mediation flag set; &lt;code&gt;webauthn.dll&lt;/code&gt; consults its resident credential store, finds passkeys matching the &lt;code&gt;rpId&lt;/code&gt;, and surfaces a small in-line affordance for each. The full-screen Windows Hello modal becomes a small in-place gesture acquisition. From the user&apos;s perspective the password-manager metaphor is unchanged; from the cryptography&apos;s perspective the work product is a public-key signature over an origin-bound challenge.&lt;/p&gt;
&lt;p&gt;The L3 spec section 5.1.4 is the normative reference for the mediation modes [@webauthn-l3-cr]. The four modes are: &lt;code&gt;silent&lt;/code&gt; (no user interaction), &lt;code&gt;optional&lt;/code&gt; (browser decides), &lt;code&gt;conditional&lt;/code&gt; (autofill), and &lt;code&gt;required&lt;/code&gt; (modal). Conditional is the one that makes passkeys feel like passwords -- and that is precisely why it took the consumer-passkey rollout off the security-team conversation and into product reviews.&lt;/p&gt;
&lt;p&gt;The Microsoft Learn passkey overview ties the UX to the Windows ship vehicle: &quot;Starting in Windows 11, version 22H2 with KB5030310, Windows provides a native experience for passkey management&quot; [@ms-learn-passkeys]. The Settings -&amp;gt; Accounts -&amp;gt; Passkeys page is the management UI; Conditional Mediation surfaces those passkeys at sign-in time. The passkeys.dev developer directory [@passkeys-dev] is the FIDO Alliance&apos;s collected resource for relying parties implementing the flow.&lt;/p&gt;
&lt;p&gt;The UX implication is the one Adam Langley underlined in the September 2022 post: the password-autofill metaphor is the load-bearing UX primitive that makes passkeys consumer-ready. The cryptography was solved in 2014. The UX took eight more years.&lt;/p&gt;
&lt;p&gt;But what if the user&apos;s passkey lives in 1Password or Bitwarden, not in Windows itself?&lt;/p&gt;
&lt;h2&gt;10. The Windows 11 24H2 third-party passkey provider model&lt;/h2&gt;
&lt;p&gt;8 October 2024. Microsoft published the Windows Developer Blog post &lt;em&gt;Passkeys on Windows: authenticate seamlessly with passkey providers&lt;/em&gt; [@ms-windev-passkeys-blog] as a pre-conference announcement ahead of the FIDO Alliance&apos;s Authenticate 2024 conference (14-16 October 2024 in Carlsbad, California). The post announced three deliverables: &quot;1. A plug-in model for third-party passkey providers. 2. Enhanced native UX for passkeys. 3. A Microsoft synced passkey provider.&quot; 1Password and Bitwarden were the named launch partners; Dashlane joined the roster shortly thereafter. The post says verbatim: &quot;Microsoft is partnering closely with 1Password, Bitwarden and others on integrating this capability&quot; [@ms-windev-passkeys-blog].&lt;/p&gt;
&lt;p&gt;The plug-in model is the first OS-level passkey-provider API on a major desktop platform. macOS Sonoma and iOS 17 had shipped a parallel design (&lt;code&gt;ASCredentialIdentityStore&lt;/code&gt; plus &lt;code&gt;ASCredentialProviderExtension&lt;/code&gt;) [@apple-ascredentialprovider]; Android 14 had added Credential Manager support [@android-credman]; Windows 11 24H2 is the desktop OS that matches the mobile platforms. The mechanism is a COM interface called &lt;code&gt;IPluginAuthenticator&lt;/code&gt;, declared in &lt;code&gt;pluginauthenticator.idl&lt;/code&gt; [@github-ms-webauthn]. A passkey-manager vendor ships a packaged Windows app that registers a COM object implementing the interface, supplies an AAGUID and a friendly name, and lets the OS dispatch ceremonies to it.&lt;/p&gt;
&lt;p&gt;The Plugin API surface is six functions on the OS side and one COM interface on the vendor side. From &lt;code&gt;webauthnplugin.h&lt;/code&gt; and the Microsoft Learn reference [@ms-learn-webauthn-apis]:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;WebAuthNPluginAddAuthenticator&lt;/code&gt;&lt;/strong&gt; -- register the plug-in with the OS. The vendor app calls this on first run.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;WebAuthNPluginAuthenticatorAddCredentials&lt;/code&gt;&lt;/strong&gt; -- supply the OS with the credentials the plug-in currently has, so the OS can render them in pickers.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;WebAuthNPluginAuthenticatorRemoveCredentials&lt;/code&gt;&lt;/strong&gt; -- the inverse; remove credentials the plug-in no longer holds.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;WebAuthNPluginPerformUserVerification&lt;/code&gt;&lt;/strong&gt; -- request Windows Hello UV on behalf of the plug-in. The plug-in does &lt;em&gt;not&lt;/em&gt; take the UV gesture itself; Windows Hello does, so the gesture-to-credential trust path is OS-mediated.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;WebAuthNPluginRemoveAuthenticator&lt;/code&gt;&lt;/strong&gt; -- the vendor&apos;s uninstall path.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;WebAuthNPluginGetAuthenticatorList&lt;/code&gt;&lt;/strong&gt; -- enumerate which plug-ins the OS knows about.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Three additional &lt;code&gt;EXPERIMENTAL_*2&lt;/code&gt; functions ship in Insider build KB5072046 and refine the registration, UV, and update flows. The list, verbatim from the &lt;code&gt;github.com/microsoft/webauthn&lt;/code&gt; README: &lt;code&gt;EXPERIMENTAL_WebAuthNPluginAddAuthenticator2&lt;/code&gt;, &lt;code&gt;EXPERIMENTAL_WebAuthNPluginPerformUserVerification2&lt;/code&gt;, &lt;code&gt;EXPERIMENTAL_WebAuthNPluginUpdateAuthenticatorDetails2&lt;/code&gt; [@github-ms-webauthn].&lt;/p&gt;
&lt;p&gt;The Microsoft-authored reference implementation is the Contoso Passkey Manager sample in &lt;code&gt;microsoft/Windows-classic-samples&lt;/code&gt; [@github-ms-passkey-sample]. The sample&apos;s build manifest is explicit: &quot;Windows SDK version 10.0.26100.7175 or higher. Operating system requirements: Windows 11 version 25H2. Build Major Version = 26200 and Minor Version &amp;gt;= 6725. Windows 11 version 24H2. Build Major Version = 26100 and Minor Version &amp;gt;= 6725&quot; [@github-ms-passkey-sample]. The Microsoft Learn tutorial &lt;em&gt;Third-party passkey providers on Windows&lt;/em&gt; walks the same sample step by step [@ms-learn-thirdparty].&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The Microsoft Learn third-party tutorial carries an explicit disclaimer: &quot;Contoso Passkey Manager is designed for passkey creation and usage testing only. Don&apos;t use the app for production passkeys&quot; [@ms-learn-thirdparty]. The sample illustrates the COM contract; it does not replace a vetted vendor&apos;s credential vault.&lt;/p&gt;
&lt;/blockquote&gt;

flowchart TD
    A[Browser or native app] --&amp;gt; B[webauthn.dll]
    B --&amp;gt; C{&quot;Provider picker&quot;}
    C --&amp;gt;|Windows Hello / platform| D[CNG + TPM 2.0]
    C --&amp;gt;|Roaming hardware| E[USB-HID / NFC / BLE]
    C --&amp;gt;|Third-party plug-in| F[COM: IPluginAuthenticator]
    F --&amp;gt; G[1Password / Bitwarden / Dashlane vault]
    F --&amp;gt; H[WebAuthNPluginPerformUserVerification]
    H --&amp;gt; I[Windows Hello UI]
    I --&amp;gt; H
    G --&amp;gt; F
    F --&amp;gt; B
    B --&amp;gt; A
&lt;p&gt;The user-facing flow follows the same logic as the macOS / iOS / Android equivalents. The user installs 1Password or Bitwarden from the Microsoft Store. The vendor app calls &lt;code&gt;WebAuthNPluginAddAuthenticator&lt;/code&gt; on first launch. The user enables the provider in Settings -&amp;gt; Accounts -&amp;gt; Passkeys -&amp;gt; Advanced options [@ms-windev-passkeys-blog]. From that point on, when any browser or native app on Windows starts a WebAuthn ceremony, &lt;code&gt;webauthn.dll&lt;/code&gt; presents the user with a picker -- &quot;use a passkey from Windows Hello, from 1Password, from Bitwarden, from a hardware security key, or from your phone&quot; -- and routes the ceremony to the selected provider. The plug-in itself returns an attestation object and an assertion; Windows Hello handles user verification on the plug-in&apos;s behalf via &lt;code&gt;WebAuthNPluginPerformUserVerification&lt;/code&gt;. The Windows trust boundary still owns the gesture acquisition.&lt;/p&gt;

The plug-in model adds credential-store choice; it does not change the lock-screen credential. The plug-in cannot replace Windows Hello at the lock screen; lock-screen sign-in remains the platform authenticator. The plug-in cannot proxy domain credentials -- Kerberos and NTLM are unaffected. The plug-in is *not* a replacement for the legacy `CredMan` (Credential Manager) generic-credential surface; that surface is still where Windows applications stash Basic-Auth-style credentials. The plug-in model is, specifically, a WebAuthn credential store. Everything else stays where it was.
&lt;p&gt;The criterion-table consequence is mixed. The plug-in model strengthens &lt;em&gt;user choice&lt;/em&gt; and &lt;em&gt;recovery&lt;/em&gt;, because a user with an existing 1Password / Bitwarden vault can reuse the recovery primitives they already know. It weakens &lt;em&gt;verifier-compromise resistance&lt;/em&gt; relative to a pure platform-bound passkey, because the long-term key now lives in the vendor&apos;s vault rather than the TPM -- and the vendor&apos;s vault becomes another point of compromise. It does not change phishing resistance, replay resistance, or step-up, because those are properties of the WebAuthn ceremony and the plug-in still produces a WebAuthn-shaped assertion.&lt;/p&gt;
&lt;p&gt;What 1Password, Bitwarden, and Dashlane each ship in their plug-in implementations follows the same template: registration requests get either a &lt;code&gt;packed&lt;/code&gt; attestation statement (for vendor-signed batch attestation keys) or a &lt;code&gt;none&lt;/code&gt; attestation (most consumer flows), and authentication assertions come back the same shape as any other WebAuthn assertion. The plug-in itself decides whether the credential is &lt;code&gt;BE=1, BS=1&lt;/code&gt; (synced in the vendor&apos;s cloud) or &lt;code&gt;BE=0, BS=0&lt;/code&gt; (device-bound to the local install).&lt;/p&gt;
&lt;p&gt;A plug-in supplies the credential. But the &lt;em&gt;attestation statement&lt;/em&gt; on registration tells the relying party &lt;em&gt;what kind of credential it is&lt;/em&gt;. That&apos;s a separate API surface -- what shapes does it come in?&lt;/p&gt;
&lt;h2&gt;11. The seven attestation conveyance formats&lt;/h2&gt;
&lt;p&gt;The IANA WebAuthn registry lists seven format identifiers for the &lt;em&gt;attestation statement&lt;/em&gt; a registration ceremony can produce [@iana-webauthn-registry]. The registry is reachable via RFC 8809 (Hodges, Mandyam, M.B. Jones, August 2020) [@rfc8809] and the canonical normative definitions are in WebAuthn Level 2 §§8.2-8.8 [@webauthn-l2-latest], whose dated Recommendation is at &lt;code&gt;REC-webauthn-2-20210408&lt;/code&gt; [@webauthn-l2-rec]. The seven, in registry order: &lt;code&gt;packed&lt;/code&gt;, &lt;code&gt;tpm&lt;/code&gt;, &lt;code&gt;android-key&lt;/code&gt;, &lt;code&gt;android-safetynet&lt;/code&gt;, &lt;code&gt;fido-u2f&lt;/code&gt;, &lt;code&gt;apple&lt;/code&gt;, and &lt;code&gt;none&lt;/code&gt;. Each is one option a relying party can require, accept, or ignore.&lt;/p&gt;

The mechanism by which a WebAuthn registration ceremony optionally produces a signature over the new credential&apos;s public key (and `authenticatorData` containing the `rpIdHash`), chained to a vendor or platform root. The relying party validates the chain to establish that the new credential&apos;s private key is held by a specific authenticator model or certification level. Attestation is distinct from authentication; attestation runs once at registration, authentication runs every sign-in. The WebAuthn `attestation` parameter on registration controls whether the RP asks for an attestation statement at all (values: `none`, `indirect`, `direct`, `enterprise`).
&lt;p&gt;The table below summarises what each format teaches the relying party.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Format&lt;/th&gt;
&lt;th&gt;What the RP verifies&lt;/th&gt;
&lt;th&gt;Trust anchor required&lt;/th&gt;
&lt;th&gt;Criterion strengthened&lt;/th&gt;
&lt;th&gt;Current adoption&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;packed&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Signature over &lt;code&gt;authenticatorData || clientDataHash&lt;/code&gt; by batch attestation key or self-attestation key&lt;/td&gt;
&lt;td&gt;Vendor X.509 cert chain or none (self)&lt;/td&gt;
&lt;td&gt;Verifier-compromise (model identity), optional anti-fraud&lt;/td&gt;
&lt;td&gt;Default for most CTAP2 keys; dominant in production&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;tpm&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;TPM 2.0 &lt;code&gt;TPM2_Certify&lt;/code&gt;-style quote over the new credential public key&lt;/td&gt;
&lt;td&gt;AIK / EK chain to TPM vendor root&lt;/td&gt;
&lt;td&gt;Verifier-compromise + device-bound storage&lt;/td&gt;
&lt;td&gt;Windows platform-bound passkeys&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;android-key&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Android Keystore attestation chain&lt;/td&gt;
&lt;td&gt;Google-rooted hardware-attestation CA&lt;/td&gt;
&lt;td&gt;Verifier-compromise + StrongBox / TEE residency&lt;/td&gt;
&lt;td&gt;Android platform passkeys&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;android-safetynet&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;SafetyNet API-derived attestation token&lt;/td&gt;
&lt;td&gt;Google SafetyNet CA&lt;/td&gt;
&lt;td&gt;Legacy; declining&lt;/td&gt;
&lt;td&gt;Legacy Android; SafetyNet deprecation announced June 2022; migration deadline end of January 2024; complete shutdown end of January 2025&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;fido-u2f&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ECDSA P-256 signature with vendor X.509 cert&lt;/td&gt;
&lt;td&gt;Vendor U2F-era cert&lt;/td&gt;
&lt;td&gt;Verifier-compromise (legacy)&lt;/td&gt;
&lt;td&gt;Legacy U2F-era hardware keys; declining&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;apple&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Anonymous Apple-issued attestation chain&lt;/td&gt;
&lt;td&gt;Apple anonymous-attestation CA&lt;/td&gt;
&lt;td&gt;Verifier-compromise without device de-anonymisation&lt;/td&gt;
&lt;td&gt;Apple platform passkeys&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;none&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;No attestation; credential public key plus AAGUID only&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;The default for synced-passkey consumer flows&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;A few of these deserve a paragraph each.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;packed&lt;/code&gt;&lt;/strong&gt; is the spec default and the most widely deployed. The authenticator emits one signature over the concatenation of &lt;code&gt;authenticatorData&lt;/code&gt; and a hash of &lt;code&gt;clientDataJSON&lt;/code&gt;, using one of three keys: (a) a per-authenticator-model &lt;em&gt;batch attestation key&lt;/em&gt; whose X.509 chain anchors to the vendor&apos;s attestation root (the privacy-vs-anti-fraud trade-off -- the cert reveals the device model, but not which specific user owns which device); (b) an &lt;em&gt;Anonymisation CA&lt;/em&gt; or Enterprise Attestation key, which lets a managed enterprise distinguish its own devices without leaking that information to consumer relying parties; or (c) a &lt;em&gt;self-attestation&lt;/em&gt; key derived from the credential itself, which proves only that the private key signs and makes no identity claim.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;tpm&lt;/code&gt;&lt;/strong&gt; is the format the Windows platform authenticator emits when the user has a TPM 2.0. The signing object is a TPM &lt;code&gt;TPM2_Quote&lt;/code&gt;-style structure with the TPM&apos;s Attestation Identity Key (AIK), chained back to the TPM vendor&apos;s Endorsement Key (EK) root certificate. This is the most cryptographically opinionated attestation in the registry: it proves the credential is held by a specific TPM vendor&apos;s part. The Windows TPM article in this series walks the AIK / EK chain end to end.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;apple&lt;/code&gt;&lt;/strong&gt; is Apple&apos;s anonymous-attestation design. The X.509 chain ends in an Apple anonymous-attestation CA; cryptographically the relying party can verify the cert chain back to Apple&apos;s root, but the cert itself is engineered to not reveal the user&apos;s specific device. This is the privacy-vs-anti-fraud trade-off resolved in favour of privacy: a relying party gets &quot;this came from a real Apple device&quot; without learning &lt;em&gt;which&lt;/em&gt; Apple device.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;android-safetynet&lt;/code&gt;&lt;/strong&gt; is the legacy format that lots of installed-base Android passkeys still use. Google announced the SafetyNet Attestation API&apos;s deprecation in June 2022 in favour of Play Integrity; the migration deadline was extended to end of January 2024, with complete shutdown landing end of January 2025 [@android-safetynet-deprecation]. Any new Android passkey registered in 2025 or later uses &lt;code&gt;android-key&lt;/code&gt; or &lt;code&gt;none&lt;/code&gt; instead. Relying parties with old &lt;code&gt;android-safetynet&lt;/code&gt; credentials in their database must accept both formats during the transition window; new credentials use the new path.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;fido-u2f&lt;/code&gt;&lt;/strong&gt; is the U2F-era legacy format, descended directly from the December 2014 U2F design [@fido-u2f-overview]. ECDSA P-256 signing key plus a vendor X.509 cert. Modern keys still emit it for U2F-mode CTAP1 ceremonies, but every modern CTAP2 ceremony uses &lt;code&gt;packed&lt;/code&gt; instead.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;none&lt;/code&gt;&lt;/strong&gt; is the most-deployed format in &lt;em&gt;consumer&lt;/em&gt; flows -- and the recommended default for any relying party that does not have a specific anti-fraud requirement. The RP asks for &lt;code&gt;attestation: &quot;none&quot;&lt;/code&gt;; the authenticator returns just the credential public key and the AAGUID, with no signature chain. The privacy benefit is real: attestation deanonymises the user&apos;s device by model, and a relying party that does not need that information should not collect it. The 2024-2026 best practice is &lt;code&gt;attestation: &quot;none&quot;&lt;/code&gt; for consumer passkey flows. NIST SP 800-63B-4 (final) inherits this caution [@sp80063b4-html].&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Use &lt;code&gt;attestation: &quot;none&quot;&lt;/code&gt; for consumer flows; the privacy cost of &lt;code&gt;direct&lt;/code&gt; outweighs the anti-fraud benefit for low-value accounts. Use &lt;code&gt;attestation: &quot;direct&quot;&lt;/code&gt; only when (a) you have a documented anti-fraud requirement, (b) you can verify the chain against the FIDO Metadata Service, and (c) you accept that the cert reveals the authenticator model. Use &lt;code&gt;attestation: &quot;enterprise&quot;&lt;/code&gt; only inside a managed enterprise where the user&apos;s device is corporately enrolled.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;All seven formats assume the authenticator is &lt;em&gt;on the same device&lt;/em&gt; as the browser. What happens when it isn&apos;t?&lt;/p&gt;
&lt;h2&gt;12. Hybrid transport: a phone authenticator for a laptop browser&lt;/h2&gt;
&lt;p&gt;A user on a borrowed Windows laptop with no Windows passkey signs in to their bank by scanning a QR code with their iPhone. The phone is the authenticator. The laptop is the WebAuthn client. The protocol that ties them together is &lt;em&gt;hybrid transport&lt;/em&gt;, formerly known as caBLE (Cloud-Assisted Bluetooth Low Energy), standardised in W3C WebAuthn Level 3 §6.3.3 [@webauthn-l3-cr].&lt;/p&gt;

A WebAuthn transport in which a roaming authenticator (typically a mobile phone) cooperates with a WebAuthn client on a nearby device (typically a laptop) via three concurrent channels: an out-of-band channel (QR code) for one-time setup, BLE for proximity, and HTTPS to a discoverable cloud tunnel relay for the actual ceremony bytes. The cryptographic binding is an ephemeral ECDH key exchanged through the QR code; the BLE proves proximity, not identity; the tunnel relay carries the encrypted ceremony [@webauthn-l3-cr-dated].
&lt;p&gt;The ceremony, simplified: the laptop&apos;s browser asks the user to use a phone, generates an ephemeral ECDH keypair, and renders a QR code containing the Tunnel Service URL the phone should connect to, the laptop&apos;s ephemeral public key, and a derived HMAC key. The phone&apos;s camera scans the QR code and derives a shared secret with the laptop via ECDH. The phone then advertises its presence over BLE, the laptop listens for the BLE beacon to confirm physical proximity, and both endpoints connect to the Tunnel Service URL over HTTPS. From that point on, the laptop and the phone exchange CTAP2 ceremony messages, encrypted under the ECDH-derived key, through the tunnel relay. The phone produces a WebAuthn assertion locally using whatever authenticator is on the phone (the Secure Enclave on iPhone, the Android Keystore on Android), encrypts it for the laptop, and the laptop forwards it to the relying party.&lt;/p&gt;

sequenceDiagram
    participant U as User
    participant L as Laptop browser
    participant P as Phone authenticator
    participant T as Tunnel Service
    participant R as Relying Party
    L-&amp;gt;&amp;gt;R: navigator.credentials.get
    R-&amp;gt;&amp;gt;L: PublicKeyCredentialRequestOptions
    L-&amp;gt;&amp;gt;L: generate ephemeral ECDH keypair
    L-&amp;gt;&amp;gt;U: display QR code (tunnel URL, ephem pubkey, HMAC seed)
    U-&amp;gt;&amp;gt;P: scan QR code
    P-&amp;gt;&amp;gt;P: derive shared secret via ECDH
    P-&amp;gt;&amp;gt;L: BLE advertisement (proximity proof)
    L-&amp;gt;&amp;gt;L: confirm BLE advertisement
    P-&amp;gt;&amp;gt;T: HTTPS connect to tunnel URL
    L-&amp;gt;&amp;gt;T: HTTPS connect to tunnel URL
    T-&amp;gt;&amp;gt;L: relay encrypted CTAP2 traffic
    T-&amp;gt;&amp;gt;P: relay encrypted CTAP2 traffic
    P-&amp;gt;&amp;gt;U: prompt for user verification
    U-&amp;gt;&amp;gt;P: present gesture
    P-&amp;gt;&amp;gt;P: produce WebAuthn assertion (origin-bound)
    P-&amp;gt;&amp;gt;T: encrypted assertion
    T-&amp;gt;&amp;gt;L: encrypted assertion
    L-&amp;gt;&amp;gt;R: assertion
    R-&amp;gt;&amp;gt;U: signed in
&lt;p&gt;The criterion-table consequence is precise. Phishing resistance is preserved because the &lt;em&gt;origin&lt;/em&gt; in &lt;code&gt;clientDataJSON&lt;/code&gt; is the laptop&apos;s actual browser origin, which the phone signs over the same way it would for its own browser. The QR code is the cryptographic binding, not the BLE advertisement; the BLE advertisement is a proximity signal that proves the phone is physically near the laptop, but it does not authenticate the phone. The Tunnel Service is a &lt;em&gt;relay&lt;/em&gt;, not a trust anchor; even if the tunnel were compromised, the encrypted ceremony bytes would be unreadable without the ECDH-derived key.&lt;/p&gt;
&lt;p&gt;The design is attributed in the WebAuthn L3 spec to the W3C WebAuthn-3 editor masthead -- Jeff Hodges, J.C. Jones, Michael B. Jones, Akshay Kumar, and Emil Lundberg as current editors, with Dirk Balfanz as a previous editor [@wiki-webauthn]. The original caBLE design and the L3 §6.3.3 productisation were led by Google&apos;s Chrome security and Android Identity teams; the canonical reference is W3C WebAuthn Level 3 §6.3.3 itself.&lt;/p&gt;
&lt;p&gt;Hybrid transport is the only competitor to the Windows platform authenticator that involves no Windows-side credential storage. The Windows laptop holds nothing -- no key, no recovery state, no cached credential. Every ceremony round-trips to the phone. This is the use case the bank-on-a-borrowed-laptop story illustrates: you can sign in to your accounts on a machine you do not own without leaving a credential behind.&lt;/p&gt;
&lt;p&gt;How do other authentication approaches score on the criteria framework?&lt;/p&gt;
&lt;h2&gt;13. Competing approaches scored against the criteria&lt;/h2&gt;
&lt;p&gt;The criteria-framework table makes the competitive field legible. Five rows, six competing columns: password alone, password plus SMS-OTP, password plus TOTP, password plus push with number matching, smart card / PIV, and device-bound or synced passkey. The NIST SP 800-63B-4 AAL grading [@sp80063b4-html] and the NIST syncable-authenticator supplement [@sp80063sup1] anchor the right edge of the table; Yubico&apos;s commentary corroborates the dichotomy between device-bound (AAL3) and synced (AAL2) passkeys [@yubico-nist-guidance].&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Criterion&lt;/th&gt;
&lt;th&gt;Password&lt;/th&gt;
&lt;th&gt;Password + SMS-OTP&lt;/th&gt;
&lt;th&gt;Password + TOTP&lt;/th&gt;
&lt;th&gt;Password + Push (number match)&lt;/th&gt;
&lt;th&gt;Smart Card / PIV&lt;/th&gt;
&lt;th&gt;Device-bound passkey&lt;/th&gt;
&lt;th&gt;Synced passkey&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Phishing resistance&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;None (AitM relays the OTP)&lt;/td&gt;
&lt;td&gt;None (AitM relays the TOTP)&lt;/td&gt;
&lt;td&gt;Partial (number match defeats most kits)&lt;/td&gt;
&lt;td&gt;Strong (origin-bound via TLS client auth)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Strong&lt;/strong&gt; (&lt;code&gt;rpId&lt;/code&gt; binding)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Strong&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Verifier-compromise resistance&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;None (SMS infra leaks)&lt;/td&gt;
&lt;td&gt;Partial (TOTP seed on server)&lt;/td&gt;
&lt;td&gt;Partial&lt;/td&gt;
&lt;td&gt;Strong (public-key only)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Strong&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Strong&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Replay / relay resistance&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;Weak (OTP relay in 30-60 s)&lt;/td&gt;
&lt;td&gt;Weak (TOTP relay in 30 s)&lt;/td&gt;
&lt;td&gt;Strong (number match per challenge)&lt;/td&gt;
&lt;td&gt;Strong (per-handshake nonce)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Strong&lt;/strong&gt; (challenge + counter)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Strong&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Step-up / continuity&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;Partial&lt;/td&gt;
&lt;td&gt;Strong (PIN re-prompt)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Strong&lt;/strong&gt; (&lt;code&gt;UV=1&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Strong&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Recovery floor&lt;/td&gt;
&lt;td&gt;Reset via SMS&lt;/td&gt;
&lt;td&gt;SMS-OTP all the way down&lt;/td&gt;
&lt;td&gt;TOTP seed reset via SMS&lt;/td&gt;
&lt;td&gt;SMS / password&lt;/td&gt;
&lt;td&gt;Admin re-issue&lt;/td&gt;
&lt;td&gt;RP-dependent backup key&lt;/td&gt;
&lt;td&gt;Sync-fabric recovery (Recovery Key + Recovery Contact)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NIST AAL ceiling&lt;/td&gt;
&lt;td&gt;AAL1&lt;/td&gt;
&lt;td&gt;AAL2 nominal (SMS-OTP RESTRICTED in 800-63-3 [@nist-sp80063-3-final]; deprecated in 800-63-4 [@sp80063-4-final])&lt;/td&gt;
&lt;td&gt;AAL2&lt;/td&gt;
&lt;td&gt;AAL2&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;AAL3&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;AAL3&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;AAL2&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Push MFA needs a paragraph of nuance. Vanilla push -- &quot;tap to approve&quot; -- is phishable by default because the attacker can simply trigger the push at the moment they have the password, and a fatigued user taps. Number matching (the user types a code shown on the laptop into the phone, or vice versa) defeats most kits because it ties the push to a specific session. &lt;em&gt;Location binding&lt;/em&gt; (the push is rejected unless the phone is geographically near the laptop) adds another layer. The net is &quot;partial&quot; phishing resistance -- much better than vanilla push, not as strong as origin binding.&lt;/p&gt;
&lt;p&gt;Smart cards and PIV deserve their own paragraph because they are not historically associated with WebAuthn but score well on the criteria. A PIV card with a PIN provides strong phishing resistance via TLS client authentication (origin-bound at the TLS layer), strong verifier-compromise resistance via the public-key model, and strong replay resistance via per-handshake nonces. The weakness is &lt;em&gt;recovery&lt;/em&gt;: a lost card requires an administrative reissue, which scales poorly for consumer flows. The companion &lt;em&gt;App Identity in Windows&lt;/em&gt; article in this series walks the Windows smart-card stack end to end.&lt;/p&gt;
&lt;p&gt;OATH-TOTP is interesting in the criteria table because it is phishing-vulnerable by construction. The TOTP code is the same on the legitimate origin and the look-alike; the AitM kit forwards the code through. Google Authenticator&apos;s cloud-sync feature additionally broke the verifier-compromise property in a subtle way: if the user&apos;s Google account is compromised, the synced TOTP seeds give the attacker a complete second-factor toolkit [@google-auth-sync-2023].&lt;/p&gt;
&lt;p&gt;SAML and OIDC federation are not competitors to WebAuthn in the criteria table -- they are &lt;em&gt;transport layers above&lt;/em&gt; WebAuthn. A SAML or OIDC identity provider does the WebAuthn ceremony for the user; the IdP then issues a SAML assertion or an OIDC ID token to the relying party. WebAuthn underneath is the strong primitive; SAML and OIDC are the enterprise transport for the resulting assertions.&lt;/p&gt;
&lt;p&gt;WebAuthn wins decisively on four of five rows. What&apos;s left in row five? The recovery row.&lt;/p&gt;
&lt;h2&gt;14. Theoretical limits: the corners WebAuthn cannot reach&lt;/h2&gt;
&lt;p&gt;Even with everything from §§4-12 in place, WebAuthn has corners it cannot defend. The relevant impossibility results are well-known in the protocol literature; they are worth naming because they tell a practitioner where defence-in-depth has to come from.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Coerced consent.&lt;/strong&gt; WebAuthn cannot distinguish a willing user from a coerced one. The protocol&apos;s only signal is &quot;the user performed the gesture&quot; -- a fingerprint, a PIN, a face match. No protocol whose only observable is gesture completion can tell whether the user was free at the moment of the gesture. NIST SP 800-63B-4 does not classify physical coercion among the attacks it defends against [@sp80063b4-html]; this is a general impossibility, not a WebAuthn-specific weakness.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; A user under duress can be made to present a gesture. WebAuthn cannot detect this. The compensating control is &lt;em&gt;transactional&lt;/em&gt; -- step-up authentication with a fresh challenge for high-value actions, and out-of-band confirmation for transactions above a risk threshold. The protocol cannot solve coercion; the application layer must.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Kernel-level malware on the client.&lt;/strong&gt; Malware with kernel privilege on the user&apos;s device can race the legitimate user. If the malware can call into &lt;code&gt;webauthn.dll&lt;/code&gt; and trigger a Hello UV prompt the user blindly approves, it can extract assertions. The mitigation is TPM-bound keys plus the Hello ESS trustlet (covered in the companion &lt;em&gt;Windows Hello&lt;/em&gt; and &lt;em&gt;Credential Guard&lt;/em&gt; articles), not WebAuthn itself. WebAuthn protects against &lt;em&gt;network&lt;/em&gt; attackers; defending against a kernel-mode attacker on the same device requires the OS&apos;s secure-kernel architecture.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Sync-fabric compromise.&lt;/strong&gt; Compromise of Apple iCloud, Google account recovery, or Microsoft&apos;s recovery-key service effectively compromises every passkey held there. Apple&apos;s Advanced Data Protection model [@apple-adp-kb] is the strongest currently-shipped consumer realisation of the end-to-end-encrypted sync invariant, and even it depends on the user retaining their Recovery Contact or Recovery Key in some form. The NIST April 2024 supplement classifies synced passkeys at AAL2 for exactly this reason: the private key leaves the original authenticator [@sp80063sup1]. Yubico&apos;s commentary makes the practitioner consequence explicit: device-bound is AAL3, synced is AAL2 [@yubico-nist-guidance].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Username enumeration and discoverable-credential privacy.&lt;/strong&gt; Discoverable credentials let an authenticator answer &quot;do you have a credential for this &lt;code&gt;rpId&lt;/code&gt;?&quot; without further information. A relying party that asks the question maliciously can enumerate which of its users have set up a passkey. The &lt;code&gt;credProtect&lt;/code&gt; extension introduced in CTAP 2.1 [@ctap-2-1-ps] requires &lt;code&gt;UV=1&lt;/code&gt; to even list the credential, which closes most of the leak; it is not universally deployed.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Counter-regression false positives on synced passkeys.&lt;/strong&gt; The per-credential signature counter is per-authenticator. A passkey synced across two devices will see the counter desynchronise between them. WebAuthn L3 §6.1.1 explicitly permits a &lt;em&gt;zero-counter&lt;/em&gt; for synced passkeys; relying parties that treat any counter regression as evidence of cloning will produce false positives. Treat counter regression as evidence of cloning &lt;em&gt;only&lt;/em&gt; for &lt;code&gt;BS=0&lt;/code&gt; (device-bound) credentials. This is a deployment foot-gun, not a protocol flaw.&lt;/p&gt;

flowchart LR
    A[rpId binding / origin in clientDataJSON] --&amp;gt; P[Phishing resistance]
    B[Public-key model / no shared secret] --&amp;gt; V[Verifier-compromise resistance]
    C[Per-RP challenge + signCount + BS=0] --&amp;gt; RR[Replay / relay resistance]
    D[UP and UV flags + freshness] --&amp;gt; S[Step-up / continuity]
    E[BE / BS flags + sync fabric] --&amp;gt; AV[Availability]
    F[Recovery Key + Recovery Contact] --&amp;gt; RC[Recovery]
    G[TPM 2.0 / hardware secure element] --&amp;gt; AAL[AAL3 device-bound]
    H[End-to-end encrypted sync fabric] --&amp;gt; AAL2[AAL2 synced]
&lt;p&gt;These are the &lt;em&gt;protocol&lt;/em&gt; limits. The biggest practical limit is one the protocol cannot fix at all -- recovery. The protocol can specify what factor produces the credential at sign-in; it cannot specify what factor produces the credential when the original one is lost. That is the application-layer question every relying party answers differently, and it is the question §17 will land on.&lt;/p&gt;
&lt;h2&gt;15. Open problems: what&apos;s still moving in late 2025 / early 2026&lt;/h2&gt;
&lt;p&gt;Standardisation is not done. Several major surfaces are still in active draft.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;WebAuthn Level 3&lt;/strong&gt; is currently a W3C Candidate Recommendation [@webauthn-l3-cr]; the dated CR snapshot is 13 January 2026 [@webauthn-l3-cr-dated]. The expected progression is Candidate Recommendation to Proposed Recommendation to Recommendation through 2026, with no major spec-breaking changes expected at this point in the process. The active editor masthead is Hodges, J.C. Jones, M.B. Jones, Kumar, and Lundberg [@wiki-webauthn].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;CTAP 2.2&lt;/strong&gt; is a FIDO Proposed Standard as of 14 July 2025 [@ctap-2-2-ps]; &lt;strong&gt;CTAP 2.3&lt;/strong&gt; is also listed at FIDO&apos;s specifications download page [@fido-specs-download]. The 2.2 and 2.3 revisions refine hybrid transport, &lt;code&gt;credProtect&lt;/code&gt;, and PIN-protocol handling without breaking 2.1&apos;s command-byte table.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cross-vendor passkey portability.&lt;/strong&gt; The FIDO Alliance &lt;em&gt;Credential Exchange Protocol&lt;/em&gt; (CXP) and &lt;em&gt;Credential Exchange Format&lt;/em&gt; (CXF) Working Drafts, dated 3 October 2024 [@fido-cxp-wd], are the standards effort. The draft text identifies the problem: &quot;the transfer of credentials between two different providers has traditionally been an infrequent occurrence... As it becomes more common for users to have multiple credential providers that they use to create [and] manage credentials, it becomes important to address some of the security concerns with regard to migration&quot; [@fido-cxp-wd]. Apple has signalled CXP-based import for iOS; Bitwarden has signalled support. The likely 2026 trajectory is CXP becoming a Proposed Standard and Windows / Android / iOS implementing it as the OS-level import-export passkeys surface.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Transactional authorisation.&lt;/strong&gt; The earliest WebAuthn drafts included &lt;code&gt;txAuthSimple&lt;/code&gt; and &lt;code&gt;txAuthGeneric&lt;/code&gt; extensions [@webauthn-fpwd]; neither was ever implemented by browsers, and both are absent from L3. The productised path is Secure Payment Confirmation (a sibling spec to WebAuthn), but it covers only payment transactions. General &quot;sign a description of &lt;em&gt;this transaction&lt;/em&gt;&quot; remains an open problem. Conjecture: payment-confirmation becomes the template that gets generalised in WebAuthn Level 4.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Quantum-safe attestation.&lt;/strong&gt; The IANA COSE algorithm registry (last updated 2026-03-04) currently has no PQC algorithm in WebAuthn-recommended status [@iana-cose-registry]. ECDSA P-256, EdDSA Ed25519, RSA-PKCS1.5, and RSA-PSS are the registered options, all quantum-breakable in principle. A long-lived TPM AIK signed today is forgeable to a quantum-capable adversary at any future date. The companion &lt;em&gt;Post-Quantum Cryptography on Windows&lt;/em&gt; article in this series walks the algorithm-side rollout; the WebAuthn deployment side is open. The most plausible trajectory is ML-DSA (FIPS 204) entering the WebAuthn COSE registry by 2027 and existing TPM AIKs receiving a parallel ML-DSA enrolment.&lt;/p&gt;
&lt;p&gt;Standards are still moving. What should a practitioner do &lt;em&gt;today&lt;/em&gt;?&lt;/p&gt;
&lt;h2&gt;16. Practical guide: what to do this week&lt;/h2&gt;
&lt;p&gt;Six pieces of operational advice, each tied to a primary source.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. Windows developers: use &lt;code&gt;webauthn.dll&lt;/code&gt;, do not roll your own.&lt;/strong&gt; The Win32 reference at &lt;code&gt;learn.microsoft.com/en-us/windows/win32/api/webauthn/&lt;/code&gt; [@ms-learn-win32-webauthn] is the only surface you should be calling. The OS handles USB-HID, NFC, BLE, hybrid transport, Conditional Mediation, plug-in dispatch, and Windows Hello UV in one call. The header is at &lt;code&gt;github.com/microsoft/webauthn&lt;/code&gt; [@github-ms-webauthn]; the Microsoft Learn overview is at &lt;code&gt;learn.microsoft.com/.../hello-for-business/webauthn-apis&lt;/code&gt; [@ms-learn-webauthn-apis].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. Relying parties: default to &lt;code&gt;attestation: &quot;none&quot;&lt;/code&gt;, &lt;code&gt;userVerification: &quot;required&quot;&lt;/code&gt;, &lt;code&gt;residentKey: &quot;preferred&quot;&lt;/code&gt;.&lt;/strong&gt; This is the 2024-2026 consumer-flow baseline. &lt;code&gt;attestation: &quot;none&quot;&lt;/code&gt; preserves user privacy and interoperates with every authenticator type. &lt;code&gt;userVerification: &quot;required&quot;&lt;/code&gt; forces &lt;code&gt;UV=1&lt;/code&gt; and the gesture acquisition. &lt;code&gt;residentKey: &quot;preferred&quot;&lt;/code&gt; enables usernameless sign-in on platforms that support it without burning a credential slot on older authenticators that don&apos;t. The Microsoft Entra passwordless documentation [@ms-entra-passwordless] and the WebAuthn Level 3 spec [@webauthn-l3-cr] are the references.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. Enterprise IT: device-bound FIDO2 keys for AAL3 (admin, finance, tier 0); synced passkeys for AAL2 workforce.&lt;/strong&gt; NIST SP 800-63B-4 [@sp80063b4-html] formalises the dichotomy via the syncable-authenticator supplement [@sp80063sup1]. Yubico&apos;s enterprise commentary makes the operational point: device-bound passkeys on dedicated hardware are AAL3; synced passkeys are AAL2 [@yubico-nist-guidance]. For admin accounts use FIDO Alliance L3-certified hardware [@fido-certification-levels] -- YubiKey Bio, Feitian BioPass, the Entra-listed vendors at &lt;code&gt;learn.microsoft.com/.../concept-fido2-hardware-vendor&lt;/code&gt; [@ms-entra-fido2-hardware].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4. Windows 11 24H2 end users: enable third-party passkey providers in Settings.&lt;/strong&gt; Settings -&amp;gt; Accounts -&amp;gt; Passkeys -&amp;gt; Advanced options. Toggle the provider on for any vendor you trust (1Password, Bitwarden, Dashlane) [@ms-windev-passkeys-blog]. The Microsoft Learn third-party tutorial walks the flow [@ms-learn-thirdparty]. If you do not use a third-party vault, the Microsoft synced passkey provider is enabled by default on 24H2 systems signed in with a Microsoft Account.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;5. Security architects: write down your recovery flow first.&lt;/strong&gt; Score it against the five-axis criteria table from §2 before you design the authentication factors. The recovery row&apos;s strength is the system&apos;s ceiling, not the floor; the authentication ceremony cannot raise it. Microsoft Entra&apos;s own guidance flags account recovery as a deployment risk: FIDO2 keys &quot;can increase costs for equipment, training, and helpdesk support -- especially when users lose their physical keys and need account recovery&quot; [@ms-entra-passwordless]. §17 lands this argument.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;6. Incident responders: collect ETW events from the WebAuthn provider.&lt;/strong&gt; Plug-in authenticator registration events on managed devices are a high-signal indicator -- a newly enrolled &lt;code&gt;IPluginAuthenticator&lt;/code&gt; on a privileged user&apos;s machine should be treated as a credential-store change requiring review. The companion &lt;em&gt;ETW on Windows&lt;/em&gt; article in this series walks the WebAuthn provider events end to end.&lt;/p&gt;

Open PowerShell as the signed-in user (no admin needed for your own credentials) and call into the `webauthn.dll` `WebAuthNGetPlatformCredentialList` API via a managed wrapper, or use the Settings -&amp;gt; Accounts -&amp;gt; Passkeys page directly. There is no first-class `Get-WebAuthnCredential` cmdlet as of Windows 11 25H2; the Settings page is the supported management surface. The Microsoft Learn passkey overview is the canonical reference [@ms-learn-passkeys].
&lt;p&gt;Most of this is engineering. One row of the table has resisted engineering for fifty years. That&apos;s where the article lands.&lt;/p&gt;
&lt;h2&gt;17. Recovery: your weakest factor is always your recovery flow&lt;/h2&gt;
&lt;p&gt;The thesis surfaced in §2 and deferred through twelve sections is the one the article lands on. The argument is direct, almost embarrassingly so: every authentication system that admits any external recovery primitive is, in the formal sense, at most as strong as that primitive. Strong authentication ceremonies coexist with weaker recovery ceremonies in every consumer platform in production, and the &lt;em&gt;system&apos;s&lt;/em&gt; assurance level is the minimum of the two, not the maximum.&lt;/p&gt;

*Your weakest factor is always your recovery flow.*
&lt;p&gt;To make the claim concrete, score every major platform&apos;s recovery flow against the same five-axis criteria table.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Apple iCloud Keychain (with Advanced Data Protection).&lt;/strong&gt; Apple&apos;s published model has three recovery primitives [@apple-adp-kb]: (a) a &lt;em&gt;trusted device&lt;/em&gt; the user previously signed into; (b) an &lt;em&gt;iCloud Recovery Contact&lt;/em&gt; -- another Apple ID owner the user has nominated to attest their identity; and (c) an &lt;em&gt;iCloud Recovery Key&lt;/em&gt; -- a 28-character string the user must retain [@apple-recovery-key]. Apple&apos;s published architecture is the strongest current consumer realisation of the end-to-end-encrypted invariant: the recovery primitives unlock an HSM-backed escrow cluster that holds the user&apos;s iCloud Keychain encryption material, but Apple itself does not hold the keys in plaintext. The fundamental dependency is the Apple ID password plus, originally, SMS-OTP at device-trust establishment.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Google Password Manager (with Google Account end-to-end encrypted passkey sync).&lt;/strong&gt; Trusted-device fallback, security-key fallback, recovery code, recovery phone, recovery email. The recovery floor reduces, in the worst case, to SMS-OTP via the recovery phone. Google&apos;s architecture is end-to-end encrypted in the steady state but the trust establishment depends on Google account recovery, which depends on out-of-band verification primitives the user enrolled at account creation.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Microsoft Account.&lt;/strong&gt; The October 2024 Windows Developer Blog states the recovery primitive verbatim: &quot;you will be prompted to save a recovery key that will be used to verify your identity and protect your passkeys through end-to-end encryption&quot; [@ms-windev-passkeys-blog]. The recovery key is a high-entropy string the user retains; if they lose it, the recovery flow falls back to the secondary factors the user enrolled (alternate email or SMS-OTP via the recovery phone). As with Google, the worst-case recovery floor is the weakest of the secondary factors the user enrolled.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Microsoft Entra ID (enterprise).&lt;/strong&gt; Entra&apos;s Temporary Access Pass (TAP) is the strongest enterprise recovery primitive currently shipped: an administrator issues a time-bound passwordless TAP that the user redeems to bootstrap a new authenticator. TAP is stronger than consumer flows because of &lt;em&gt;accountability&lt;/em&gt; -- the admin&apos;s identity is on the issuance -- but weaker than the authentication ceremony itself because the admin is socially engineerable. Microsoft documents the TAP issuance and redemption flow in detail [@ms-entra-tap].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1Password, Bitwarden, Dashlane under the 24H2 plug-in model.&lt;/strong&gt; Each vendor&apos;s master password and secondary recovery primitive becomes the &lt;em&gt;de facto&lt;/em&gt; floor of the entire passkey ceremony when the plug-in is the credential store. 1Password&apos;s master password plus Secret Key, Bitwarden&apos;s master password plus 2FA recovery code, and Dashlane&apos;s device trust plus master password -- each is the recovery floor for every passkey the vault holds. The Microsoft Learn third-party tutorial reinforces the warning, in context: &quot;Contoso Passkey Manager is designed for passkey creation and usage testing only. Don&apos;t use the app for production passkeys&quot; [@ms-learn-thirdparty].&lt;/p&gt;

flowchart TD
    A[Apple iCloud Keychain ADP] --&amp;gt; A1[Recovery Contact]
    A --&amp;gt; A2[Recovery Key 28 chars]
    A --&amp;gt; A3[Trusted device]
    A3 --&amp;gt; A4[Apple ID password + SMS-OTP at trust establishment]
    B[Google Password Manager] --&amp;gt; B1[Recovery code]
    B --&amp;gt; B2[Recovery phone]
    B --&amp;gt; B3[Recovery email]
    B2 --&amp;gt; B4[SMS-OTP]
    C[Microsoft Account] --&amp;gt; C1[Recovery Key]
    C --&amp;gt; C3[Alternate email]
    C --&amp;gt; C4[Recovery phone -&amp;gt; SMS-OTP]
    D[Entra ID enterprise] --&amp;gt; D1[Temporary Access Pass]
    D1 --&amp;gt; D2[Admin: socially engineerable]
    E[1Password / Bitwarden / Dashlane vault] --&amp;gt; E1[Master password + Secret Key / 2FA recovery code]
    A4 --&amp;gt; Z[Weak shared-knowledge or SMS-OTP floor]
    B4 --&amp;gt; Z
    C4 --&amp;gt; Z
    D2 --&amp;gt; Z
    E1 --&amp;gt; Z
&lt;p&gt;The diagram looks busy because it is. Every major platform&apos;s recovery flow is a different combination of trusted-device fallback, recovery code or key, recovery contact, and an out-of-band primitive (SMS-OTP, email, or admin attestation). Every one of those out-of-band primitives is weaker than origin-bound public-key cryptography. The cryptographic ceremony scores AAL3 phishing-resistant at the authentication moment; the recovery primitive scores AAL1 or AAL2 at the recovery moment. &lt;em&gt;The system&apos;s AAL is the minimum.&lt;/em&gt;&lt;/p&gt;

NIST SP 800-63B-4&apos;s AAL2 / AAL3 split makes the recovery story explicit. Section 5.1 of SP 800-63B-4 enumerates permitted recovery primitives; every one is at most as strong as its underlying factor. The April 2024 supplement [@sp80063sup1] caps synced passkeys at AAL2 because the long-term private key has left the original authenticator -- the same logic that caps the recovery row applies to the sync fabric. Auditors who care about AAL3 for tier-zero accounts will require *both* a device-bound authenticator and a documented recovery flow whose own strength is at AAL3. The current best-practice composition is two device-bound hardware authenticators in different physical locations, each registered as primary for the other&apos;s recovery.
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; Every passkey platform in production in 2026 -- Apple, Google, Microsoft, Entra, 1Password, Dashlane, Bitwarden -- bottoms out, in its recovery flow, in some combination of trusted-device fallback and SMS-OTP-equivalent shared knowledge. That floor is the AAL ceiling for the entire system.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The protocol literature has been clear about this for fifty years and the regulatory literature has been catching up since 2017. NIST SP 800-63-3 introduced &quot;phishing-resistant authenticator&quot; as a first-class term; SP 800-63-4 (2025) [@sp80063-4-final] makes verifier-impersonation resistance a normative criterion. Neither standard solves recovery; both standards explicitly enumerate what counts as a recovery primitive without specifying how to &lt;em&gt;compose&lt;/em&gt; them into an AAL-graded flow. There is no IETF or FIDO Alliance standard that says &quot;here is a recovery flow whose strength is AAL3.&quot; There may never be -- recovery is application-specific, and the only general protocol is &quot;social attestation&quot; (multiple human witnesses), which does not scale.&lt;/p&gt;
&lt;p&gt;The same WebAuthn ceremony that scores AAL3 phishing-resistant at the authentication moment can be a single-factor SMS-OTP at the recovery moment. &lt;em&gt;Your weakest factor is always your recovery flow.&lt;/em&gt; That is the line. It is the line every working security architect should write down, score against, and design recovery against -- &lt;em&gt;before&lt;/em&gt; designing the authentication factors.&lt;/p&gt;
&lt;h2&gt;18. FAQ&lt;/h2&gt;

No. A password is a shared secret -- the user types a string, the server stores a hash of the same string, and an eavesdropper who captures the string in flight or compromises the server&apos;s database has a credential they can replay. A passkey is one half of an asymmetric keypair: the private key lives in the authenticator (TPM, secure enclave, hardware key, or end-to-end-encrypted sync fabric), and only its public key reaches the server. An eavesdropper who captures a passkey ceremony in flight has nothing they can replay; a server-database leak yields public keys that authenticate no one. WebAuthn Level 3 [@webauthn-l3-cr] and the Microsoft Entra &quot;origin-bound public key cryptography&quot; framing [@ms-entra-passwordless] are the references.

Insecure relative to device-bound; secure relative to passwords. The NIST syncable-authenticator supplement (April 2024) [@sp80063sup1] and SP 800-63B-4 (July 2025) [@sp80063b4-html] cap synced passkeys at AAL2, because the long-term private key has left the original authenticator. Device-bound passkeys on dedicated hardware -- &quot;FIDO passkeys that are not synced ... and are properly stored in dedicated hardware have an AAL3 rating&quot; [@yubico-nist-guidance] -- can reach AAL3. The right answer is to use device-bound keys for tier-zero accounts and synced passkeys for the bulk of consumer flows.

Hello *uses* biometrics but provides the *user-verification gesture* for WebAuthn; the credential itself is asymmetric and lives in the TPM. Microsoft Learn states the property verbatim: &quot;The private keys can only be used after they&apos;re unlocked by the user using the Windows Hello unlock factor (biometrics or PIN)&quot; [@ms-learn-passkeys]. The biometric is one mode of the Hello UV gesture, not the credential. If you disable face or fingerprint, your PIN still unlocks the passkey.

No. Attestation is privacy-leaking for synced passkeys; `attestation: &quot;none&quot;` is the 2024-2026 default for consumer flows. Use `attestation: &quot;direct&quot;` only when you have a documented anti-fraud requirement and can verify the chain against the FIDO Metadata Service. Use `attestation: &quot;enterprise&quot;` only inside a managed enterprise where the user&apos;s device is corporately enrolled. The relevant references are WebAuthn Level 2 §§8.2-8.8 [@webauthn-l2-latest] and the IANA WebAuthn registry [@iana-webauthn-registry].

No. The cryptographic binding is the QR-code-encoded ephemeral ECDH key. Bluetooth is a transport and a proximity signal; it is not a trust anchor. The QR code transfers the laptop&apos;s ephemeral public key plus a derived HMAC seed; the phone derives the shared secret via ECDH; the BLE advertisement merely proves the phone is physically close to the laptop. The encrypted CTAP2 ceremony bytes travel over HTTPS through a discoverable tunnel relay. WebAuthn Level 3 §6.3.3 is the normative description [@webauthn-l3-cr].

No. A Windows passkey can be used with PIN-only user verification; the biometric is one mode of the Hello UV gesture, not the credential. The credential is in the TPM, indexed under your Microsoft Account container, and the PIN is one valid unlock factor. If you use a third-party passkey provider via the 24H2 plug-in model, that provider may use its own master password as the UV gesture; the OS still mediates the gesture acquisition through `WebAuthNPluginPerformUserVerification` [@ms-learn-webauthn-apis].

Microsoft cannot see your TPM-sealed Windows Hello private key; the TPM does not expose the raw key material to the OS, let alone to Microsoft. Apple&apos;s iCloud Keychain with Advanced Data Protection [@apple-adp-kb] and Google&apos;s end-to-end-encrypted passkey sync mean the sync provider cannot see the plaintext keys either. *But* the recovery path can still expose them under specific conditions: an attacker who compromises your recovery contact, recovery key, or your account&apos;s out-of-band recovery primitives (SMS-OTP, recovery email) effectively defeats the end-to-end encryption invariant. The plaintext keys are not what gets exfiltrated; the recovery primitives are.
&lt;p&gt;This article is one of a series on Windows authentication primitives. &lt;em&gt;NTLMless: The Death of NTLM in Windows&lt;/em&gt; (2026-05-10) covers the legacy authentication protocol passkeys are displacing. &lt;em&gt;Windows Hello, Demystified&lt;/em&gt; covers the user-verification gesture WebAuthn leans on. &lt;em&gt;Adminless: Administrator Protection in Windows&lt;/em&gt; (2026-05-10) and &lt;em&gt;App Identity in Windows&lt;/em&gt; (2026-05-08) cover the privilege-escalation and code-identity primitives that surround the authentication stack. The companion &lt;em&gt;Kerberos on Windows&lt;/em&gt; (2026-05-11) covers the enterprise transport for the resulting assertions; &lt;em&gt;ETW on Windows&lt;/em&gt; (2026-05-11) covers the telemetry surface for incident responders.&lt;/p&gt;
&lt;p&gt;The Windows passkey stack is the productisation moment for a forty-year-old protocol-literature insight: authentication should be tied to &lt;em&gt;something the network attacker cannot change&lt;/em&gt;. WebAuthn ties it to the origin in &lt;code&gt;clientDataJSON&lt;/code&gt;, signed by a credential whose private key never reaches the wire. Windows 10 1903 made it a Win32 surface; Windows 11 24H2 made it a plug-in surface; Authenticate 2024 made it a default. The protocol bytes are FIDO2; the consumer experience is autofill. The Windows part is the dispatcher between them.&lt;/p&gt;
&lt;p&gt;The criteria framework is the diagnostic kit. Use it on every authentication system you ship. Score it against five axes, not three. Write down the recovery flow first. Match the authentication ceremony to the recovery flow you can actually defend. And remember the line: &lt;em&gt;your weakest factor is always your recovery flow.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;StudyGuide slug=&quot;webauthn-and-passkeys-on-windows-from-ctap-to-the-credential-provider-model&quot; keyTerms={[
  { term: &quot;Phishing-resistant authenticator&quot;, definition: &quot;An authenticator whose protocol prevents a relying party impersonator from inducing the authenticator to release a usable credential value. NIST SP 800-63B-4 calls this verifier-impersonation resistance.&quot; },
  { term: &quot;Origin binding&quot;, definition: &quot;The mechanism by which WebAuthn enforces phishing resistance: the browser writes the origin into clientDataJSON; the authenticator signs over the SHA-256 hash of the canonical rpId; the RP rejects any signature whose rpIdHash does not match the registered rpId.&quot; },
  { term: &quot;rpId&quot;, definition: &quot;A string identifying the WebAuthn relying party for credential scoping. Must be a registrable suffix of the page&apos;s origin. All WebAuthn signatures are made over its SHA-256 hash.&quot; },
  { term: &quot;CTAP 2.x&quot;, definition: &quot;The Client-to-Authenticator Protocol: the wire format browser to roaming authenticator over USB-HID, NFC, or BLE. CTAP1 is APDU-based; CTAP2 is CBOR-based. Modern keys speak CTAP 2.1 (June 2021) or 2.2 (July 2025).&quot; },
  { term: &quot;Discoverable credential (resident key, passkey)&quot;, definition: &quot;A WebAuthn credential whose account metadata is stored on the authenticator, enabling usernameless sign-in. CTAP 2.0 called these resident keys; the May 2022 vendor commitment branded them passkeys.&quot; },
  { term: &quot;Attestation conveyance&quot;, definition: &quot;The mechanism by which a registration ceremony optionally produces a signature over the credential public key, chained to a vendor or platform root. Seven IANA-registered formats: packed, tpm, android-key, android-safetynet, fido-u2f, apple, none.&quot; },
  { term: &quot;Hybrid transport (caBLE)&quot;, definition: &quot;A WebAuthn transport in which a phone acts as a roaming authenticator for a nearby laptop. QR code carries an ephemeral ECDH key; BLE proves proximity; HTTPS tunnel relay carries encrypted CTAP2 bytes.&quot; },
  { term: &quot;AAGUID&quot;, definition: &quot;A 16-byte Authenticator Attestation GUID identifying the authenticator make and model. Some authenticators emit all-zeros for privacy; the FIDO Metadata Service is the authoritative directory.&quot; },
  { term: &quot;Conditional UI / Conditional Mediation&quot;, definition: &quot;A WebAuthn invocation mode in which the browser offers discoverable credentials inside the autofill UI rather than via a modal picker. RP calls navigator.credentials.get with mediation: &apos;conditional&apos;.&quot; },
  { term: &quot;BE / BS flags&quot;, definition: &quot;Backup Eligible and Backup State bits in authenticatorData. BE=1 means the credential is in principle syncable; BS=1 means it is currently backed up. NIST SP 800-63B-4 caps BS=1 credentials at AAL2.&quot; },
  { term: &quot;AAL1 / AAL2 / AAL3&quot;, definition: &quot;NIST SP 800-63B-4 authentication assurance levels. AAL1 is single-factor; AAL2 is multi-factor or phishing-resistant; AAL3 is hardware-bound non-syncable authentication.&quot; }
]} /&amp;gt;&lt;/p&gt;
</content:encoded><category>windows-security</category><category>webauthn</category><category>passkeys</category><category>fido2</category><category>ctap</category><category>phishing-resistance</category><category>windows-hello</category><category>authentication</category><author>noreply@paragmali.com (Parag Mali)</author></item><item><title>No Secrets to Steal: How Windows Hello Eliminated the Shared Secret</title><link>https://paragmali.com/blog/your-face-is-not-your-password-inside-windows-hellos-hardwar/</link><guid isPermaLink="true">https://paragmali.com/blog/your-face-is-not-your-password-inside-windows-hellos-hardwar/</guid><description>How Windows Hello replaced passwords with TPM-backed biometrics, survived a decade of attacks, and helped make passwordless the default.</description><pubDate>Tue, 28 Apr 2026 00:00:00 GMT</pubDate><content:encoded>
**Windows Hello replaces passwords with biometric authentication backed by hardware cryptography.** Your face or fingerprint unlocks a private key sealed inside a TPM chip -- no biometric data ever leaves your device, and no shared secret crosses the network. After a decade of enterprise growing pains and a cat-and-mouse security arms race, Microsoft made passwordless the default for new accounts in May 2025, with passkeys now achieving a 98% sign-in success rate. The password&apos;s 64-year reign is ending -- but open problems in biometric spoofing, credential portability, and quantum-resistant cryptography mean the replacement is still under construction.
&lt;h2&gt;Why Passwords Must Die&lt;/h2&gt;
&lt;p&gt;In 2024, Microsoft observed 7,000 password attacks every second [@ms-passkeys] -- more than double the rate from 2023. Picture this: a user types their carefully memorized 16-character password into what looks like a corporate login page. The page is a phishing replica. In under a second, that password -- the one they have been rotating every 90 days for three years -- belongs to someone else.&lt;/p&gt;

Microsoft observed 7,000 password attacks per second in 2024. The password Corbato invented as a quick fix in 1961 had become the single greatest attack surface in computing.
&lt;p&gt;The problem is not weak passwords. The problem is passwords themselves. They are shared secrets -- a piece of information that both you and the server know. Anything a server stores can be stolen. Anything you type can be intercepted. Anything you memorize can be phished. These are not implementation bugs. They are design properties.&lt;/p&gt;
&lt;p&gt;It was not supposed to be this way. In 1961, Fernando Corbato [@wiki-password] introduced computer passwords at MIT as a quick fix for multi-user mainframes. Users needed separate file spaces on the Compatible Time-Sharing System (CTSS), and a secret string was the simplest way to provide per-user isolation. It was a temporary measure for a specific engineering constraint.&lt;/p&gt;
&lt;p&gt;That temporary measure lasted 64 years.&lt;/p&gt;
&lt;p&gt;What if authentication did not require a secret at all? What if your face unlocked a cryptographic key -- and that key never left your device? That is the promise of Windows Hello. But the story of how we got here passes through a gelatin finger, a low-cost USB device, and a near-infrared camera that shattered assumptions about what &quot;secure&quot; really means.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;The Password&apos;s 64-Year Reign: A Brief History of Authentication Failure&lt;/h2&gt;
&lt;p&gt;In 1966, a software bug in MIT&apos;s CTSS printed the master password file to every user&apos;s terminal -- the first known password breach [@wiki-password].The 1966 CTSS incident was not a hack. A system administrator accidentally swapped the login message file with the master password file. Every user who logged in that day saw everyone else&apos;s password on screen.&lt;/p&gt;
&lt;p&gt;It was a sign of things to come. For the next six decades, every generation of authentication would solve one problem -- and reveal a deeper one.&lt;/p&gt;

gantt
    title Authentication Evolution
    dateFormat YYYY
    axisFormat %Y
    section Passwords
    Plaintext passwords on CTSS       :1961, 1979
    section Hashed
    UNIX crypt / hashed passwords     :1979, 1993
    section Network Auth
    NTLM challenge-response           :1993, 2000
    Kerberos / Windows AD             :2000, 2015
    section Biometrics
    Software biometrics via WBF       :2009, 2015
    section Windows Hello
    Hello + TPM asymmetric auth       :2015, 2021
    ESS + VBS + Cloud Trust           :2021, 2024
    Passkeys and passwordless default :2024, 2026
&lt;h3&gt;Generation 0: Plaintext passwords (1961)&lt;/h3&gt;
&lt;p&gt;Corbato&apos;s CTSS stored passwords in plaintext [@wiki-password] in a file accessible to administrators. The model was simple: the user enters a string, the system compares it to a stored copy, and access is granted on match. The key assumption -- that only the legitimate user knows the password -- held exactly as long as the system remained uncompromised. Which was about five years.&lt;/p&gt;
&lt;h3&gt;Generation 1: Hashed passwords (1970s)&lt;/h3&gt;
&lt;p&gt;The obvious fix: do not store passwords in plaintext. In 1979, Robert Morris and Ken Thompson published the design behind UNIX&apos;s &lt;code&gt;crypt()&lt;/code&gt; function [@wiki-crypt], a one-way hash based on a modified DES algorithm with a 12-bit salt. Even if an attacker stole the hash file, they could not directly read the passwords. They would have to try every possible password and compare hashes -- a brute-force attack.&lt;/p&gt;
&lt;p&gt;For a while, that was computationally infeasible. Then Moore&apos;s Law caught up. By the late 1990s, EFF&apos;s DES Cracker and distributed.net had reduced 56-bit DES keysearch to &lt;strong&gt;22 hours and 15 minutes&lt;/strong&gt; [@eff-des], making DES-based &lt;code&gt;crypt()&lt;/code&gt; increasingly untenable against well-funded attackers. Users also chose weak, predictable passwords, and attackers built rainbow tables that mapped common passwords to their hashes instantly.&lt;/p&gt;
&lt;p&gt;Windows made this worse. LAN Manager (LM) hashes [@ms-lm-hash] uppercased every password, limited them to 14 characters, and split them into two 7-byte halves hashed independently.The LM hash design was spectacularly bad. By splitting a 14-character password into two 7-character halves, it reduced the brute-force search space from 95^14 to 2 x 95^7 -- a reduction of over 34 trillion times. An attacker could crack each half separately.&lt;/p&gt;
&lt;p&gt;Rainbow tables could crack LM hashes in seconds. Microsoft eventually disabled LM hashing by default in Windows Vista, but the damage to enterprise networks had been done.&lt;/p&gt;
&lt;h3&gt;Generation 2: Network challenge-response (1990s)&lt;/h3&gt;
&lt;p&gt;The next insight: stop transmitting passwords over the network. NTLM [@ms-lm-hash] used a challenge-response protocol -- the server sends a random nonce, the client computes a response using the nonce and the password hash, and the server verifies the response. The password never crosses the wire.&lt;/p&gt;
&lt;p&gt;Kerberos [@ms-kerberos], adopted in Windows 2000, improved further with mutual authentication, time-limited tickets, and single sign-on. It was elegant protocol engineering.&lt;/p&gt;
&lt;p&gt;But the fundamental problem remained: shared secrets. NTLM was vulnerable to pass-the-hash attacks [@mitre-pth] -- an attacker who obtains the password hash can authenticate without ever knowing the password. Kerberos tickets could be stolen (Golden Ticket, Silver Ticket attacks). Both systems still depended on users choosing strong passwords, which they consistently failed to do.&lt;/p&gt;
&lt;h3&gt;Generation 3: First software biometrics (2000s)&lt;/h3&gt;
&lt;p&gt;By the early 2000s, fingerprint readers appeared on Windows laptops. The idea was appealing: replace &quot;something you know&quot; with &quot;something you are.&quot; No password to remember, no password to steal.&lt;/p&gt;
&lt;p&gt;Microsoft introduced the Windows Biometric Framework (WBF) [@ms-wbf] in Windows 7 (2009), standardizing the API and driver interface. Before WBF, each fingerprint reader vendor -- AuthenTec, Validity, UPEK -- shipped proprietary middleware that injected into the Windows logon process. The result was inconsistent security, driver conflicts, and no centralized management.&lt;/p&gt;
&lt;p&gt;But WBF solved the wrong problem. It standardized the API while leaving the security model unchanged: biometric templates stored with weak encryption in user-accessible files, matching running in OS user space, and no hardware isolation whatsoever.&lt;/p&gt;
&lt;p&gt;In 2002, Tsutomu Matsumoto at Yokohama National University demonstrated the &quot;gummy finger&quot; attack -- creating gelatin replicas of fingerprints that fooled approximately 80% of commercial readers [@gummy-finger]. The materials cost just a few dollars. Without liveness detection and hardware protection, biometrics were security theater.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The pattern was unmistakable.&lt;/strong&gt; Each generation protected a different layer -- plaintext storage, hash computation, network transmission, biometric convenience -- but each left the next layer exposed. By 2013, passwords were fundamentally broken, and software-only biometrics were not the answer. Then Apple proved something nobody expected.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;The Catalyst: How Touch ID Changed Everything&lt;/h2&gt;
&lt;p&gt;September 2013. Apple unveils the iPhone 5S [@apple-touchid] with a fingerprint sensor embedded in the home button. It was not the first phone with a fingerprint reader -- Motorola&apos;s ATRIX 4G shipped with a biometric fingerprint reader in 2011 [@motorola-atrix]. But it was the first one that hundreds of millions of people actually used.&lt;/p&gt;
&lt;p&gt;What made Touch ID different was not the sensor. It was the Secure Enclave -- a dedicated secure subsystem integrated into Apple&apos;s system-on-chip and isolated from the main processor [@apple-secure-enclave]. The enclave runs its own microkernel, stores biometric material in protected memory, and keeps the matching pipeline outside the reach of normal iOS processes. Apple designed it so the biometric path stayed inside the enclave boundary rather than becoming just another app-visible API.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Apple controlled the sensor, the SoC, the Secure Enclave hardware, and iOS. This vertical integration meant the entire biometric pipeline -- from sensor capture through template matching to key release -- could be designed as a single trust chain. No Windows OEM could match this in 2013 because the sensor, CPU, and OS came from three different vendors with no unified security model.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That architecture established a pattern that Windows Hello would later follow with the TPM. Both isolate secrets in hardware, but they do different jobs: the Secure Enclave is a richer coprocessor that protects both biometric processing and keys, while the TPM is a narrower trust anchor for key storage, signing, and attestation. Apple&apos;s newer Secure Enclave documentation also emphasizes encrypted enclave memory, whereas Windows later needed ESS and &lt;a href=&quot;https://paragmali.com/blog/the-windows-secure-kernel/&quot; rel=&quot;noopener&quot;&gt;VBS&lt;/a&gt; to give its broader PC system a comparable isolation boundary [@apple-secure-enclave; @ms-ess].&lt;/p&gt;
&lt;p&gt;Touch ID proved two things simultaneously: that consumer biometrics could be both secure and delightful, and that the key to secure biometrics was hardware isolation, not better algorithms.&lt;/p&gt;
&lt;p&gt;The FIDO Alliance had already been working on the standards side. Founded in July 2012 [@fido-launch] by Michael Barrett (PayPal&apos;s CISO), Ramesh Kesanupalli (Nok Nok Labs), and partners including Lenovo, Validity Sensors, and Infineon, the Alliance set out to create open standards for strong authentication that would replace passwords. Its first protocols split the problem in two: UAF defined a passwordless flow where a device-local biometric or PIN unlocks a per-service key pair [@fido-uaf], while U2F defined a hardware-token second factor that signs a challenge after the user taps the device [@fido-u2f]. FIDO2 later unified these ideas into the WebAuthn + CTAP stack used for passkeys today [@fido-how].&lt;/p&gt;
&lt;p&gt;The convergence was forming: consumer demand (Apple proved people wanted biometrics), open standards (FIDO defined how it should work), and enterprise need (Microsoft tracked thousands of password attacks per second). Apple showed &lt;em&gt;what&lt;/em&gt; was possible. The FIDO Alliance defined &lt;em&gt;how&lt;/em&gt; it should work. Microsoft was about to show how to do it at the scale of an entire operating system.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;The Breakthrough: Windows Hello&apos;s Architecture&lt;/h2&gt;
&lt;p&gt;On March 17, 2015, Joe Belfiore announced Windows Hello. The key insight was not an algorithm -- it was an architecture. What if the biometric never leaves the device, and the authentication secret is a cryptographic key that even the server never sees?&lt;/p&gt;

A dedicated security chip soldered to a computer&apos;s motherboard (or implemented in firmware) that generates, stores, and manages cryptographic keys. The TPM can create key pairs where the private key is physically bound to the chip and cannot be exported -- even the operating system cannot extract it. Windows Hello uses TPM 2.0 to seal authentication keys.

A cryptographic system using two mathematically related keys: a public key (shared openly) and a private key (kept secret). Data encrypted with one key can only be decrypted with the other. In Windows Hello, the TPM holds the private key and signs authentication challenges; the server holds only the public key, which is useless to an attacker.
&lt;p&gt;Here is how Windows Hello authentication [@ms-whfb] works:&lt;/p&gt;

sequenceDiagram
    participant U as User
    participant B as Biometric Sensor
    participant D as Device OS
    participant T as TPM Chip
    participant S as Identity Server
    U-&amp;gt;&amp;gt;B: Present face or fingerprint
    B-&amp;gt;&amp;gt;D: Capture biometric sample
    D-&amp;gt;&amp;gt;D: Match against stored template
    Note over D: Local verification only
    D-&amp;gt;&amp;gt;T: Request private key release
    T-&amp;gt;&amp;gt;T: Verify TPM-bound policy
    T--&amp;gt;&amp;gt;D: Private key available for signing
    S-&amp;gt;&amp;gt;D: Send challenge nonce
    D-&amp;gt;&amp;gt;D: Sign nonce with private key
    D-&amp;gt;&amp;gt;S: Return signed assertion
    S-&amp;gt;&amp;gt;S: Verify signature with public key
    S-&amp;gt;&amp;gt;D: Authentication success
&lt;p&gt;&lt;strong&gt;Step 1: Enrollment.&lt;/strong&gt; The TPM generates an asymmetric key pair -- RSA-2048 or ECDSA P-256. The private key is sealed inside the TPM and cannot be exported. The public key is registered with the identity provider (Azure AD, Entra ID, or on-premises AD) [@ms-whfb].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 2: Biometric enrollment.&lt;/strong&gt; The user registers their face (via a near-infrared camera) or fingerprint. The biometric template is stored locally on the device, protected by the OS.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 3: Authentication.&lt;/strong&gt; The user presents their biometric gesture. The device verifies it locally against the stored template. If the match succeeds, the TPM releases the private key. The identity server sends a random challenge nonce; the device signs it with the private key and returns the signed assertion. The server verifies the signature using the stored public key. No shared secret ever crosses the network.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; Windows Hello&apos;s breakthrough was architectural, not algorithmic. By pairing biometrics with hardware-backed asymmetric cryptography, it eliminated shared secrets entirely. No biometric data ever leaves the device. No password hash sits on a server waiting to be stolen. Each authentication is a fresh, unreplayable cryptographic signature.&lt;/p&gt;
&lt;/blockquote&gt;

The probability that a biometric system incorrectly accepts an unauthorized person. Windows Hello requires a facial recognition FAR below 0.001% (1 in 100,000) [@ms-biometric-reqs]. Apple&apos;s Face ID is documented at less than 0.0001% (1 in 1,000,000) for a single enrolled face [@apple-faceid-security]. Lower is better -- but zero is theoretically impossible.

A camera technology that captures light in the 700--1000 nanometer wavelength range, invisible to the human eye. Windows Hello uses NIR cameras because infrared illumination works regardless of ambient lighting and is harder to spoof with printed photos or screens -- standard displays do not emit near-infrared light. Or so everyone assumed until 2025.
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Without a TPM, Windows Hello falls back to software key storage, dramatically weakening the security model. The private key becomes a file protected by the OS rather than a secret sealed in tamper-resistant silicon. Always verify TPM 2.0 is present and active before relying on Hello&apos;s security properties.&lt;/p&gt;
&lt;/blockquote&gt;

A Trusted Platform Module is not a general-purpose processor. It is a purpose-built chip (or firmware module) designed for a narrow set of cryptographic operations: key generation, key storage, signing, and attestation.&lt;p&gt;When Windows Hello enrolls a user, the TPM generates a key pair using its internal random number generator. The private key never exists outside the chip&apos;s boundary -- it is generated inside the TPM and stays there. The TPM enforces access policies: it will only release the key for signing after the device OS confirms that the biometric match succeeded. Even a compromised operating system kernel cannot extract the private key from a hardware TPM.&lt;/p&gt;
&lt;p&gt;This is fundamentally different from software key storage, where the key is a file on disk that any sufficiently privileged process can read.
&lt;/p&gt;&lt;p&gt;&lt;/p&gt;
&lt;h3&gt;The PIN paradox&lt;/h3&gt;
&lt;p&gt;Windows Hello also revived the humble PIN -- and made it more secure than a complex password. A Hello PIN [@ms-whfb] is device-bound: it unlocks the TPM-stored private key on that specific device. A stolen PIN is useless without physical access to the hardware. Compare this to a password, which works from any device on earth. A 4-digit PIN on Windows Hello is architecturally more secure than a 20-character password reused across services.Microsoft Passport was briefly announced as a separate product in early 2015 -- the cryptographic key infrastructure behind Windows Hello. By late 2015, the branding was merged. &quot;Microsoft Passport&quot; was retired and its functionality absorbed into &quot;Windows Hello&quot; and &quot;Windows Hello for Business.&quot; The separate brand caused market confusion and was quickly abandoned.&lt;/p&gt;
&lt;p&gt;The biometric FAR can be expressed mathematically. For a face recognition system with $n$ enrolled users and a per-comparison FAR of $p$, the probability of at least one false acceptance across all comparisons is:&lt;/p&gt;
&lt;p&gt;$$P(\text{false accept}) = 1 - (1 - p)^n$$&lt;/p&gt;
&lt;p&gt;For Windows Hello&apos;s required FAR of $10^{-5}$ [@ms-biometric-reqs] and a single user, this gives a 0.001% chance per authentication attempt. With 1,000 attempts, the cumulative probability rises to roughly 1% -- which is why lockout policies and anti-hammering protections exist.&lt;/p&gt;
&lt;p&gt;{`
// This demonstrates the core idea behind Windows Hello&apos;s authentication.
// In the real system, the private key lives in the TPM and never leaves.&lt;/p&gt;
&lt;p&gt;async function simulateHelloAuth() {
  // Step 1: Enrollment -- generate key pair (TPM does this in hardware)
  const keyPair = await crypto.subtle.generateKey(
    { name: &quot;ECDSA&quot;, namedCurve: &quot;P-256&quot; },
    true, // extractable for demo only; TPM keys are NOT extractable
    [&quot;sign&quot;, &quot;verify&quot;]
  );
  console.log(&quot;Key pair generated (simulating TPM enrollment)&quot;);&lt;/p&gt;
&lt;p&gt;  // Step 2: Server sends a challenge nonce
  const challenge = crypto.getRandomValues(new Uint8Array(32));
  console.log(&quot;Server challenge:&quot;, Array.from(challenge.slice(0, 8)).map(b =&amp;gt; b.toString(16).padStart(2, &apos;0&apos;)).join(&apos;&apos;));&lt;/p&gt;
&lt;p&gt;  // Step 3: Device signs the challenge with the private key
  const signature = await crypto.subtle.sign(
    { name: &quot;ECDSA&quot;, hash: &quot;SHA-256&quot; },
    keyPair.privateKey,
    challenge
  );
  console.log(&quot;Signed assertion:&quot;, new Uint8Array(signature).slice(0, 16).join(&apos;,&apos;) + &apos;...&apos;);&lt;/p&gt;
&lt;p&gt;  // Step 4: Server verifies with the public key
  const valid = await crypto.subtle.verify(
    { name: &quot;ECDSA&quot;, hash: &quot;SHA-256&quot; },
    keyPair.publicKey,
    signature,
    challenge
  );
  console.log(&quot;Server verification:&quot;, valid ? &quot;SUCCESS&quot; : &quot;FAILED&quot;);
  console.log(&quot;\nNote: The private key never left the device.&quot;);
  console.log(&quot;The server only has the public key -- useless to an attacker.&quot;);
}&lt;/p&gt;
&lt;p&gt;simulateHelloAuth();
`}&lt;/p&gt;
&lt;p&gt;Windows Hello solved the fundamental password problem: no shared secrets ever traverse the network. But the story does not end here -- because researchers would soon discover that protecting the key was not enough if you could not trust the camera.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;The Enterprise Gambit: Windows Hello for Business&lt;/h2&gt;
&lt;p&gt;Windows Hello delighted consumers. But enterprise IT administrators asked a harder question: how do I deploy this to 50,000 machines managed by Active Directory?&lt;/p&gt;

The W3C Web Authentication API -- a browser standard that lets websites request public-key-based authentication from platform authenticators (like Windows Hello) or roaming authenticators (like security keys). WebAuthn became a W3C Recommendation on March 4, 2019, forming the browser-side component of the FIDO2 standard alongside CTAP (Client-to-Authenticator Protocol).
&lt;p&gt;Windows Hello for Business (WHfB) [@ms-whfb] launched in 2016 with two trust types, each carrying its own infrastructure burden:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Certificate Trust&lt;/strong&gt; required a full Public Key Infrastructure -- a Certificate Authority hierarchy, CRL distribution points, certificate templates, and ADFS (Active Directory Federation Services). For organizations that already had PKI, this was a natural fit. For everyone else, it meant weeks of setup.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Key Trust&lt;/strong&gt; required Windows Server 2016+ domain controllers with AD schema extensions. Simpler than Certificate Trust, but still demanded on-premises infrastructure that many cloud-first organizations were trying to eliminate.Yogesh Mehta, Principal Group Program Manager at Microsoft, evangelized Windows Hello for Business at Ignite 2016. He would later be credited as a key figure in the FIDO2 certification effort. The original Belfiore blog post URL announcing Windows Hello is now lost to link rot.&lt;/p&gt;
&lt;p&gt;Two milestones accelerated adoption. In March 2019, WebAuthn became a W3C Recommendation [@w3c-webauthn] -- a universal browser API for public-key authentication. Android had already been FIDO2-certified in February 2019 [@fido-android-certification]; two months after WebAuthn&apos;s recommendation, Windows Hello became one of the first FIDO2-certified platform authenticators built into a desktop operating system [@fido-certification]. Together, these meant that Windows Hello could authenticate not just to Windows, but to any FIDO2-supporting website through any modern browser.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Unless you have specific PKI requirements, Cloud Trust -- announced by Microsoft in 2022 [@ms-cloud-trust-ga] -- eliminates much of the complexity of certificate and key trust deployments. It requires Entra ID configuration and Microsoft Entra Kerberos rather than a full on-prem PKI or ADFS stack, which is why Microsoft now treats it as the default recommendation for many hybrid organizations.&lt;/p&gt;
&lt;/blockquote&gt;


flowchart TD
    A[Choose a WHfB Trust Model] --&amp;gt; B{Cloud-native org using Entra ID?}
    B --&amp;gt;|Yes| C[Cloud Trust -- Recommended]
    B --&amp;gt;|No| D{On-prem AD still required?}
    D --&amp;gt;|Yes| E{Existing PKI infrastructure?}
    D --&amp;gt;|No| C
    E --&amp;gt;|Yes| F[Certificate Trust]
    E --&amp;gt;|No| G[Key Trust]
    C --&amp;gt; H[Simplest deployment: Entra ID only]
    F --&amp;gt; I[Most complex: CA + CRL + ADFS]
    G --&amp;gt; J[Moderate: Server 2016+ DCs required]
&lt;p&gt;&lt;strong&gt;Cloud Trust&lt;/strong&gt; delegates all validation to Entra ID. No on-premises PKI, no ADFS, no certificate templates. Best for organizations that are cloud-native or hybrid with Azure AD.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Key Trust&lt;/strong&gt; requires Windows Server 2016+ domain controllers with AD schema extensions. Choose this if you need on-premises AD support but do not have PKI.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Certificate Trust&lt;/strong&gt; requires the full PKI stack -- CA hierarchy, CRL distribution, ADFS. Choose this only if your organization already has PKI infrastructure and needs certificate-based authentication for regulatory compliance.&lt;/p&gt;
&lt;p&gt;Enterprise deployment was painful -- multiple trust models confused administrators, and adoption was slower than hoped. But it was about to get much worse. In July 2021, a researcher with a low-cost USB board would demonstrate that Windows Hello&apos;s most basic assumption was wrong.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;The Security Arms Race: When Researchers Fought Back&lt;/h2&gt;
&lt;p&gt;Omer Tsarfati had a simple question: what happens if you plug in a USB device that &lt;em&gt;claims&lt;/em&gt; to be an IR camera? The answer would force Microsoft to rethink Windows Hello&apos;s entire trust model.&lt;/p&gt;
&lt;h3&gt;The USB camera bypass (CVE-2021-34466)&lt;/h3&gt;
&lt;p&gt;In July 2021, Tsarfati at CyberArk Labs [@cyberark-bypass] revealed that Windows Hello&apos;s facial recognition accepted input from any USB device presenting itself as an IR camera -- with no attestation, no hardware trust verification, and no device identity check.Tsarfati&apos;s attack required only a single IR frame -- not video, not a 3D reconstruction, just one static infrared image of the target&apos;s face. The simplicity of the attack was what made it so alarming.&lt;/p&gt;
&lt;p&gt;Using an NXP evaluation board [@cyberark-bypass], Tsarfati constructed a custom USB device that replayed a single IR frame of a target&apos;s face. Plug it in, and Windows Hello authenticated the attacker as the target. At the time, 85% of Windows 10 users employed Windows Hello [@cyberark-bypass] -- making this a massive attack surface.&lt;/p&gt;
&lt;p&gt;The insight was devastating: the TPM protected the key, but nobody protected the camera. Windows Hello&apos;s threat model assumed trusted camera hardware. The USB specification makes no such guarantee.&lt;/p&gt;

A Windows feature that uses the hardware hypervisor to create an isolated virtual environment (Virtual Trust Level 1, or VTL1) separated from the main OS kernel (VTL0). Even if an attacker gains SYSTEM-level access to the Windows kernel, they cannot read memory in VTL1. Windows Hello&apos;s Enhanced Sign-in Security uses VBS to isolate biometric processing.
&lt;h3&gt;Microsoft&apos;s response: ESS and VBS&lt;/h3&gt;
&lt;p&gt;Microsoft&apos;s answer came with Windows 11: Enhanced Sign-in Security (ESS) [@ms-ess], which moved biometric matching into the VBS-protected enclave described above. Even a compromised Windows kernel cannot access templates or tamper with the comparison pipeline there.&lt;/p&gt;

flowchart TD
    subgraph VTL0[&quot;VTL0: Normal OS Environment&quot;]
        A[Windows Kernel]
        B[Applications]
        C[Standard Drivers]
    end
    subgraph VTL1[&quot;VTL1: Secure World -- ESS&quot;]
        D[Biometric Matching Engine]
        E[Encrypted Template Storage]
        F[Credential Isolation]
    end
    G[Hypervisor] --- VTL0
    G --- VTL1
    H[Secure Biometric Sensor] --&amp;gt; D
    A -.-&amp;gt;|Blocked by Hypervisor| D
    B -.-&amp;gt;|Blocked by Hypervisor| E
&lt;p&gt;Alongside ESS, Microsoft rolled out Cloud Trust in 2022 [@ms-cloud-trust-ga], eliminating the need for on-premises PKI for many deployments. Two problems -- biometric isolation and deployment complexity -- were finally being addressed in parallel.&lt;/p&gt;
&lt;h3&gt;Red Bleed: the NIR assumption shatters (CVE-2025-26644)&lt;/h3&gt;
&lt;p&gt;The arms race was not over. In August 2025, researchers Bowen Hu, Kuo Wang, and Chip Hong Chang at Nanyang Technological University presented &quot;Red Bleed&quot; [@red-bleed] at USENIX Security 2025. Microsoft had already patched CVE-2025-26644 [@wiz-cve] in April 2025, but the full attack was now public.&lt;/p&gt;
&lt;p&gt;Windows Hello&apos;s NIR facial recognition relied on a critical assumption: no commercial display can emit near-infrared light. The researchers shattered this assumption [@nvd-red-bleed] with a custom-built LCD screen costing less than $400 that could display NIR images. They trained a Variational Autoencoder to convert widely available RGB photos -- from social media, video calls, public sources -- into convincing NIR facial videos. The result: a presentation attack that bypassed Windows Hello face authentication and prompted liveness-detection hardening [@red-bleed-pdf]. The Red Bleed attack name references the &quot;red bleed&quot; phenomenon in LCD panels where a small amount of near-infrared light leaks through the color filters -- the researchers amplified this effect with a custom panel.&lt;/p&gt;
&lt;p&gt;Microsoft&apos;s April 2025 patch strengthened liveness detection and anti-spoofing measures for NIR authentication.&lt;/p&gt;
&lt;h3&gt;Faceplant: the template swap (CVE-2026-20804)&lt;/h3&gt;
&lt;p&gt;The third major attack came from ERNW Research in August 2025. At Black Hat USA 2025, Baptiste David and Tillmann Oßwald&apos;s official conference briefing &quot;Windows Hell No for Business&quot; [@blackhat-windows-hell-no] detailed the Faceplant template-injection attack, which they later documented technically on ERNW&apos;s research blog [@faceplant].&lt;/p&gt;
&lt;p&gt;In practice, an attacker with local administrator privileges could enroll their own face on one machine, extract the resulting template, and transplant it into the victim&apos;s biometric database on the target device. After injection, Windows Hello accepted the attacker&apos;s face for the victim&apos;s account. ERNW traced the weakness to software-protected templates that a local administrator could extract and replace on non-ESS systems [@faceplant].&lt;/p&gt;
&lt;p&gt;ESS blocks this attack completely -- biometric templates in VTL1 are inaccessible even to local administrators. But many enterprise PCs lack ESS-compatible hardware.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Many enterprise PCs -- particularly those shipped without an ESS-certified built-in biometric sensor, including many AMD-based and older Intel-based machines -- lack ESS capability. On these machines, biometric templates remain in software-protected storage vulnerable to the Faceplant attack. Verify hardware compatibility before assuming biometric isolation is active.&lt;/p&gt;
&lt;/blockquote&gt;

flowchart TD
    A[&quot;2015: Windows Hello Launch&quot;] --&amp;gt; B[&quot;2021: CVE-2021-34466\nUSB Camera Spoofing&quot;]
    B --&amp;gt; C[&quot;Microsoft Response:\nESS + VBS Isolation&quot;]
    C --&amp;gt; D[&quot;2025: CVE-2025-26644\nRed Bleed NIR Attack&quot;]
    D --&amp;gt; E[&quot;Microsoft Response:\nLiveness Detection Update&quot;]
    E --&amp;gt; F[&quot;2025: CVE-2026-20804\nFaceplant Template Injection&quot;]
    F --&amp;gt; G[&quot;Defense: ESS Hardware\nIsolation Blocks Attack&quot;]
    G --&amp;gt; H[&quot;Ongoing: Adversarial ML\nArms Race&quot;]
    classDef fake fill:#7a3030,stroke:#c44b4b,color:#fce8e8
    class B fake,stroke:#333
    class D fake,stroke:#333
    class F fake,stroke:#333
    classDef real fill:#2f5a3a,stroke:#5fa872,color:#dff5e4
    class C real,stroke:#333
    class E real,stroke:#333
    class G real,stroke:#333
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; Each generation of authentication protected a new layer -- but every layer revealed the next attack surface. The TPM protected the key. ESS protected the biometric pipeline. Liveness detection hardened NIR authentication. Security is never a single solution. It is a stack, and each layer needs its own defense.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The arms race revealed a humbling truth: biometric authentication is not a silver bullet. It is a layered defense -- and each layer needs its own protection. But while researchers probed Windows Hello&apos;s defenses, the industry was converging on something bigger.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;The Convergence: Passkeys and the Passwordless Future&lt;/h2&gt;
&lt;p&gt;May 5, 2022. Apple, Google, and Microsoft [@passkeys-announcement] -- three companies that agree on almost nothing -- issued a joint announcement: they were all committing to passkeys.&lt;/p&gt;

A FIDO2/WebAuthn credential built on the same public-key model as Windows Hello. Passkeys can be device-bound (like traditional Hello credentials, stored in the TPM) or synced across devices through a credential manager such as iCloud Keychain or Google Password Manager. The local biometric or PIN check stays on-device; the relying party only sees public keys and signatures.
&lt;p&gt;FIDO2 had a usability problem. Credentials were bound to a single device. Lose your laptop, lose your credentials. Passkeys solved this by introducing synced credentials -- private keys encrypted and distributed across a user&apos;s devices through their platform credential manager. The FIDO Alliance&apos;s protocol [@fido-how] maintained the cryptographic guarantees (no shared secrets, phishing resistance) while adding the portability users demanded.&quot;World Password Day&quot; was symbolically renamed &quot;World Passkey Day&quot; in May 2025, when Microsoft announced that new accounts would default to passwordless authentication.&lt;/p&gt;
&lt;h3&gt;The numbers tell the story&lt;/h3&gt;
&lt;p&gt;By May 2025, Microsoft made new accounts passwordless by default [@ms-passkeys]:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Nearly 1 million passkey registrations daily [@ms-passkeys]&lt;/li&gt;
&lt;li&gt;98% passkey sign-in success rate [@ms-passkeys] vs. 32% for passwords&lt;/li&gt;
&lt;li&gt;Passkey sign-ins 8x faster [@ms-passkeys] than password + MFA&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;How the platforms compare&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Dimension&lt;/th&gt;
&lt;th&gt;Windows Hello (WHfB)&lt;/th&gt;
&lt;th&gt;Apple Face ID / Passkeys&lt;/th&gt;
&lt;th&gt;Google Passkeys&lt;/th&gt;
&lt;th&gt;FIDO2 Hardware Keys&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Hardware root of trust&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href=&quot;https://paragmali.com/blog/the-tpm-in-windows-one-primitive-twenty-five-years-and-the-c/&quot; rel=&quot;noopener&quot;&gt;TPM 2.0&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Secure Enclave&lt;/td&gt;
&lt;td&gt;TEE / Titan M&lt;/td&gt;
&lt;td&gt;On-key secure element&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Credential sync&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No (device-bound)&lt;/td&gt;
&lt;td&gt;Yes (iCloud Keychain)&lt;/td&gt;
&lt;td&gt;Yes (Google PM)&lt;/td&gt;
&lt;td&gt;No (hardware-bound)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cross-platform&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Windows only&lt;/td&gt;
&lt;td&gt;Apple + QR/BT bridge&lt;/td&gt;
&lt;td&gt;Android/Chrome + QR/BT&lt;/td&gt;
&lt;td&gt;Universal USB/NFC/BT&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;FAR (face)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&amp;lt; 0.001%&lt;/td&gt;
&lt;td&gt;&amp;lt; 0.0001%&lt;/td&gt;
&lt;td&gt;Varies by OEM&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Enterprise management&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Intune, GP, Conditional Access&lt;/td&gt;
&lt;td&gt;Limited (Apple MDM)&lt;/td&gt;
&lt;td&gt;Android Enterprise&lt;/td&gt;
&lt;td&gt;Manual provisioning&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Recovery on device loss&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Re-enroll on new device&lt;/td&gt;
&lt;td&gt;iCloud backup restore&lt;/td&gt;
&lt;td&gt;Google Account restore&lt;/td&gt;
&lt;td&gt;Requires backup key&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;NIST AAL level&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;AAL2&lt;/td&gt;
&lt;td&gt;AAL2&lt;/td&gt;
&lt;td&gt;AAL2&lt;/td&gt;
&lt;td&gt;AAL3-eligible&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Best suited for&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Windows enterprise&lt;/td&gt;
&lt;td&gt;Apple platform&lt;/td&gt;
&lt;td&gt;Android / cross-platform web&lt;/td&gt;
&lt;td&gt;High-assurance regulated&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Sources: Microsoft biometric requirements [@ms-biometric-reqs], Apple passkey security [@apple-passkeys-security], Google passkeys [@google-passkeys], FIDO specifications [@fido-specs]&lt;/p&gt;
&lt;p&gt;Google&apos;s passkey story is centered on Google Password Manager: passkeys created on Android or Chrome sync across Android, ChromeOS, Windows, macOS, Linux, and Chrome browsers where the same account is available [@google-passkeys]. FIDO2 hardware security keys (YubiKey, Google Titan) take the opposite approach: the credential stays on a dedicated secure element, works across platforms via USB/NFC/Bluetooth, and must be provisioned deliberately on each account [@fido-u2f; @fido-how]. That trade-off buys the highest assurance available today; multi-factor cryptographic hardware authenticators are the mainstream route to NIST AAL3 [@nist-aal].&lt;/p&gt;

sequenceDiagram
    participant U as User
    participant B as Browser
    participant A as Platform Authenticator
    participant S as Relying Party Server
    U-&amp;gt;&amp;gt;B: Click Register with Passkey
    B-&amp;gt;&amp;gt;S: Request registration options
    S-&amp;gt;&amp;gt;B: Return challenge + relying party info
    B-&amp;gt;&amp;gt;A: navigator.credentials.create()
    A-&amp;gt;&amp;gt;U: Prompt biometric verification
    U-&amp;gt;&amp;gt;A: Present face / fingerprint / PIN
    A-&amp;gt;&amp;gt;A: Generate key pair in TPM
    A-&amp;gt;&amp;gt;B: Return public key + attestation
    B-&amp;gt;&amp;gt;S: Send credential to server
    S-&amp;gt;&amp;gt;S: Store public key for user
    S-&amp;gt;&amp;gt;B: Registration complete
&lt;p&gt;{`
// This shows the structure of a WebAuthn registration request.
// In production, the challenge comes from your server.&lt;/p&gt;
&lt;p&gt;const registrationOptions = {
  publicKey: {
    // Random challenge from the server (32 bytes)
    challenge: crypto.getRandomValues(new Uint8Array(32)),&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// Your service identity
rp: {
  name: &quot;Example Corp&quot;,
  id: &quot;example.com&quot;
},

// User identity
user: {
  id: new Uint8Array([1, 2, 3, 4]),
  name: &quot;alice@example.com&quot;,
  displayName: &quot;Alice&quot;
},

// Acceptable key types (ES256 = ECDSA P-256)
pubKeyCredParams: [
  { type: &quot;public-key&quot;, alg: -7 }  // ES256
],

// Request a resident/discoverable credential (passkey)
authenticatorSelection: {
  residentKey: &quot;required&quot;,
  userVerification: &quot;required&quot;  // Biometric or PIN
},

// 5-minute timeout
timeout: 300000
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  }
};&lt;/p&gt;
&lt;p&gt;console.log(&quot;Registration options structure:&quot;);
console.log(JSON.stringify(registrationOptions.publicKey.rp, null, 2));
console.log(&quot;\nKey algorithm: ES256 (ECDSA P-256)&quot;);
console.log(&quot;Resident key: required (discoverable passkey)&quot;);
console.log(&quot;User verification: required (biometric or PIN)&quot;);
console.log(&quot;\nIn production, call: navigator.credentials.create(registrationOptions)&quot;);
`}&lt;/p&gt;
&lt;h2&gt;Deploying Windows Hello Today&lt;/h2&gt;
&lt;p&gt;For consumers, the simplest path is built into Windows: open &lt;strong&gt;Settings &amp;gt; Accounts &amp;gt; Sign-in options&lt;/strong&gt;, create a Windows Hello PIN first, then enroll face or fingerprint if the hardware is present [@ms-whfb]. If Windows only offers PIN, the machine lacks a compatible biometric sensor. On a laptop with an IR camera or certified fingerprint reader, enrollment takes a few minutes and the credential becomes device-bound immediately.&lt;/p&gt;
&lt;p&gt;For enterprises, Microsoft now recommends starting with Cloud Trust unless certificate-based authentication is a hard requirement. A practical rollout checklist is short: confirm devices are Entra joined or hybrid joined, deploy Microsoft Entra Kerberos, verify Windows 10 21H2+/Windows 11 clients and Windows Server 2016+ read-write domain controllers in each site, then push &lt;strong&gt;Use Windows Hello for Business&lt;/strong&gt; plus &lt;strong&gt;Use cloud trust for on-premises authentication&lt;/strong&gt; through Intune or Group Policy [@ms-cloud-trust-ga]. That is dramatically lighter than standing up PKI, ADFS, and certificate templates.&lt;/p&gt;
&lt;p&gt;ESS deserves its own hardware check. A TPM alone is not enough: ESS depends on Windows 11, VBS-capable hardware, and compatible secure biometric sensors [@ms-ess]. Unsupported systems can still use Hello, but they fall back to the older software-protected biometric path. Hardware inventory determines whether you are getting the modern threat model or merely the old UX.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Start with a pilot group, require a Hello PIN for every enrolled user, and issue at least one backup FIDO2 security key to admins and help-desk staff. The cleanest password migration is additive: enroll Hello first, prove recovery works, then remove password prompts from the highest-value workflows last.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;For password migration, avoid a flag day. Keep passwords as break-glass recovery while you move device sign-in, Microsoft 365, VPN, and high-value internal apps onto Hello or passkeys first [@ms-entra-passwordless]. Measure enrollment completion, recovery success, and hardware exceptions. Once those numbers stabilize, tighten Conditional Access so phishing-resistant credentials satisfy MFA and passwords become the fallback of last resort.&lt;/p&gt;
&lt;p&gt;After 64 years, the password is finally losing its grip. But the story of Windows Hello is not a triumph -- it is a lesson in the limits of security engineering.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;The Limits: What Remains Unsolved&lt;/h2&gt;
&lt;p&gt;Biometrics fail in a way passwords do not: they are hard to rotate.&lt;/p&gt;

You cannot change your face. This single fact defines the deepest unsolved problem in biometric authentication.
&lt;p&gt;Passwords can be rotated. Security keys can be replaced. But you have one face, ten fingerprints, and two irises. If a biometric template is compromised, there is no &quot;reset&quot; button.&lt;/p&gt;

A technique for generating revocable biometric templates by applying non-invertible mathematical transformations to the original biometric data. If a transformed template is compromised, a new transformation can be applied to create a fresh template from the same biometric trait. In theory, this solves the irrevocability problem. In practice, the trade-off between non-invertibility and matching accuracy remains unresolved.
&lt;h3&gt;The biometric floor&lt;/h3&gt;
&lt;p&gt;The theoretical limit on biometric authentication error is the Bayes error rate [@jain-biometric] -- the minimum achievable error when the genuine-user and impostor score distributions overlap. Per information theory, the error probability is bounded by Fano&apos;s inequality:&lt;/p&gt;
&lt;p&gt;$$P_e \geq \frac{H(X|Y) - 1}{\log |X|}$$&lt;/p&gt;
&lt;p&gt;where $P_e$ is the probability of error, $H(X|Y)$ is the conditional entropy of identity given the biometric sample, and $|X|$ is the number of possible identities. Current systems achieve a FAR of $10^{-5}$ to $10^{-6}$, but the theoretical minimum [@jain-biometric] -- given perfect sensors and optimal classifiers -- could be orders of magnitude lower. The practical gap is driven by sensor noise, environmental variability, and aging of biometric features.&lt;/p&gt;
&lt;h3&gt;Five open problems&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;1. Cross-platform credential portability.&lt;/strong&gt; Passkeys are currently vendor-locked. An Apple passkey does not transfer to a Google account. The FIDO Alliance published draft CXP/CXF specifications [@fido-cxp] in late 2024 for encrypted credential exchange, but full cross-vendor interoperability is not expected before late 2026.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. The adversarial ML arms race.&lt;/strong&gt; Generative AI can create increasingly convincing biometric spoofs -- the Red Bleed attack [@red-bleed] used a VAE to convert RGB photos to NIR facial videos. Discriminative AI tries to detect these spoofs. This is an open-ended arms race with no known endpoint.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. Account recovery.&lt;/strong&gt; When all biometric and device-based credentials fail, how does a user recover their account? Most services fall back to email or SMS [@ms-entra-passwordless] -- reintroducing the very phishable factors they were designed to eliminate. Recovery codes are functionally passwords.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Systems that fall back to passwords or SMS for account recovery reintroduce the very vulnerabilities they were designed to eliminate. A truly passwordless system needs passwordless recovery -- and no universal solution exists yet.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;4. The quantum threat.&lt;/strong&gt; Shor&apos;s algorithm [@nist-pqc] on a sufficiently large quantum computer would break all ECDSA and RSA authentication -- including every FIDO2 credential in existence. NIST finalized post-quantum standards [@nist-pqc] (ML-DSA, SLH-DSA, ML-KEM) in 2024, but no FIDO2 authenticator ships with post-quantum support as of 2026.&lt;/p&gt;

All current FIDO2/WebAuthn authentication uses ECDSA P-256, which provides 128-bit classical security. Breaking a single credential requires approximately $2^{128}$ operations -- far beyond any existing computer.&lt;p&gt;Shor&apos;s algorithm changes this equation. A cryptographically relevant quantum computer could factor the elliptic curve discrete logarithm problem in polynomial time, breaking ECDSA entirely. No such computer exists today, but the &quot;harvest now, decrypt later&quot; threat means adversaries may be collecting signed assertions now to verify forged credentials later.&lt;/p&gt;
&lt;p&gt;NIST finalized its first post-quantum cryptography standards in 2024 [@nist-pqc]: ML-DSA (formerly CRYSTALS-Dilithium) for signatures, ML-KEM (formerly CRYSTALS-Kyber) for key encapsulation, and SLH-DSA (formerly SPHINCS+) for hash-based signatures. The FIDO Alliance and W3C are exploring hybrid signature schemes that combine classical ECDSA with post-quantum algorithms, but no timeline for standardization has been published.
&lt;/p&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;5. The ESS hardware gap.&lt;/strong&gt; ESS requires specific secure sensors and VBS-capable CPUs [@ms-ess]. Many enterprise PCs -- particularly those shipped without an ESS-certified built-in biometric sensor, including many AMD-based and older Intel-based machines -- lack ESS capability. On these devices, Windows Hello falls back to the pre-ESS security model, leaving them vulnerable to attacks like Faceplant.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;6. Accessibility and inclusion.&lt;/strong&gt; Biometric authentication creates barriers for people with facial differences, missing fingers, or conditions that affect biometric stability. A passwordless future must ensure that non-biometric alternatives (PINs, hardware keys) remain first-class options, not afterthoughts. Behavioral biometrics -- keystroke dynamics, gait analysis, continuous session verification -- represent an emerging parallel path that may expand authentication options beyond traditional biometric modalities.&lt;/p&gt;

Open PowerShell as administrator and run:&lt;pre&gt;&lt;code&gt;Get-CimInstance -Namespace root/Microsoft/Windows/DeviceGuard -ClassName Win32_DeviceGuard | Select-Object VirtualizationBasedSecurityStatus
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A value of &lt;code&gt;2&lt;/code&gt; means VBS is running. Then check the biometric service:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Get-WinEvent -LogName Microsoft-Windows-Biometrics/Operational -MaxEvents 10 | Format-List
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Look for events indicating ESS-protected biometric operations. If your device lacks ESS, consider disabling biometric sign-in on sensitive accounts and using FIDO2 hardware keys instead.
&lt;/p&gt;&lt;p&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; Biometric traits are permanent and finite. Unlike passwords, they cannot be changed if compromised. This irrevocability is the deepest unsolved challenge in passwordless authentication -- and no amount of better sensors or smarter algorithms can change the fact that you have one face, ten fingerprints, and two irises.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The theoretically ideal system would combine zero-knowledge biometric verification, post-quantum cryptographic authentication, hardware-attested revocable credentials, and cross-platform portability. None of this exists yet.&lt;/p&gt;
&lt;p&gt;The password&apos;s 64-year reign is ending, but its replacement is still under construction. Every generation of authentication solved one problem and revealed a deeper one. The question is not whether passwordless authentication will win -- it is whether we can build it before the attackers catch up.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Frequently Asked Questions&lt;/h2&gt;

No. Biometric data never leaves the device. During enrollment, your face or fingerprint template is stored locally, protected by the operating system (and by VBS on ESS-enabled devices). Only a public key is registered with the identity provider (Azure AD / Entra ID) [@ms-whfb]. Microsoft&apos;s servers never receive, store, or process your biometric data.

Standard photos cannot. Windows Hello uses near-infrared cameras [@ms-biometric-reqs] with anti-spoofing algorithms that distinguish between live faces and flat images. However, researchers have demonstrated advanced attacks: CVE-2021-34466 [@cyberark-bypass] used a custom USB device emulating an IR camera, and the Red Bleed attack [@red-bleed] used a custom NIR-emitting LCD display. Both have been patched, but the arms race continues.

No -- it is more secure. A Windows Hello PIN is device-bound [@ms-whfb]: it unlocks a TPM-stored private key on that specific hardware. A stolen PIN is useless without physical access to the device. A password, by contrast, works from any device on earth and can be phished, reused, or leaked in a breach.

Consumer Windows Hello [@ms-whfb] ties authentication to a personal Microsoft account. Windows Hello for Business integrates with Azure AD / Entra ID with enterprise management capabilities: conditional access policies, Intune deployment, multiple trust models (cloud, key, certificate), and group policy controls. They share the same biometric and TPM technology but have different management and security models.

No. Passkeys build on Hello&apos;s foundation. Windows Hello acts as the platform authenticator for FIDO2 passkeys [@fido-how] on Windows -- your biometric gesture unlocks the passkey stored in the TPM. Passkeys extend Hello&apos;s model to cross-platform and cross-service authentication via the WebAuthn standard [@webauthn-3].

With device-bound credentials (traditional Windows Hello), you re-enroll on the new device using your Microsoft or organizational account. With synced passkeys, credentials restore from your credential manager -- iCloud Keychain [@apple-passkeys-security] for Apple, Google Password Manager [@google-passkeys] for Android/Chrome. Registering a FIDO2 hardware security key [@fido-specs] as a backup authenticator is strongly recommended.

Not indefinitely. The asymmetric cryptography underlying Hello and FIDO2 (ECDSA P-256) is theoretically vulnerable [@nist-pqc] to quantum computers running Shor&apos;s algorithm. No quantum computer can break it today, and the timeline for cryptographically relevant quantum computers remains uncertain. NIST finalized post-quantum cryptography standards in 2024, but no FIDO2 authenticator ships with post-quantum support yet. Migration planning should begin now.
&lt;hr /&gt;
&lt;p&gt;&amp;lt;StudyGuide slug=&quot;windows-hello-revolution&quot; keyTerms={[
  { term: &quot;TPM&quot;, definition: &quot;Trusted Platform Module -- hardware chip that generates and stores cryptographic keys&quot; },
  { term: &quot;Asymmetric cryptography&quot;, definition: &quot;Public-key/private-key system where data signed with one key is verified with the other&quot; },
  { term: &quot;FAR&quot;, definition: &quot;False Acceptance Rate -- probability a biometric system accepts an unauthorized person&quot; },
  { term: &quot;NIR&quot;, definition: &quot;Near-infrared imaging -- camera technology used by Windows Hello for anti-spoofing&quot; },
  { term: &quot;WebAuthn&quot;, definition: &quot;W3C standard browser API for public-key-based authentication&quot; },
  { term: &quot;VBS&quot;, definition: &quot;Virtualization-Based Security -- hypervisor isolation for secure processing&quot; },
  { term: &quot;ESS&quot;, definition: &quot;Enhanced Sign-in Security -- VBS-isolated biometric matching in Windows 11&quot; },
  { term: &quot;Passkey&quot;, definition: &quot;FIDO2 credential that can be synced across devices via credential managers&quot; },
  { term: &quot;FIDO2&quot;, definition: &quot;Industry standard for passwordless authentication (WebAuthn + CTAP)&quot; },
  { term: &quot;Cancelable biometrics&quot;, definition: &quot;Revocable biometric templates using non-invertible transformations&quot; }
]} /&amp;gt;&lt;/p&gt;
</content:encoded><category>windows-hello</category><category>authentication</category><category>biometrics</category><category>fido2</category><category>passkeys</category><category>security</category><category>tpm</category><author>noreply@paragmali.com (Parag Mali)</author></item></channel></rss>