Learn how to delete passkeys on Windows 10 using certutil & other tools to enhance Windows Hello. Follow our guide to manage WebAuthn credentials effectively.
Vincent
Created: May 14, 2024
Updated: August 27, 2024
Our mission is to make the Internet a safer place, and the new login standard passkeys provides a superior solution to achieve that. That's why we want to help you understand passkeys and its characteristics better.
2.1 How to Set a PIN for Windows Hello in Windows 10?
2.2 How to Verify if Windows Hello is Activated?
2.3 For Developers: How to Effectively Test Passkeys on Windows 10?
3.1 Where does Windows Hello Store Passkeys?
3.1.1 Key Storage Locations
3.1.2 How WebAuthn Credentials are Managed
3.1.3 Security Measures
3.2 How to Use Certutil to List & Analyze Passkeys on Windows 10?
3.2.1 How to List All Available Passkeys on Windows 10?
3.2.2 Windows 10 PC (Intel CPU): certutil output
3.2.3 Windows 11 VM (Parallels on ARM-Mac): certutil output
4.1 Deleting Passkeys with Command Line Tool certutil
4.2 Deleting Passkeys with webauthn-fido2-key-remover
4.2.1 Using the Latest Release from webauthn-fido2-key-remover Directly
4.2.2 Using Latest webauthn-fido2-key-remover Version from Corbado
At Corbado, we are developing a Passkey-First authentication solution. Many passkey challenges come from using passkeys on Windows 10. Windows 10 offers device-bound passkeys, but the operating system lacks the ability to manage passkeys via a UI.
Discuss passkeys news and questions in r/passkey.
Join SubredditAs the number of passkeys increases within the Windows 10 authenticator, Windows Hello becomes slower and slower, which is especially unproductive for developers. In this article, we will:
Make a short deep dive into Windows 10 WebAuthn cryptography: We will examine how Windows 10 handles WebAuthn cryptography and where FIDO2 credentials are generally stored on Windows 10. We will start by activating Windows Hello and ensuring it is set up correctly.
Find out how to manage and remove passkeys on Windows 10: We will go through the possibilities for listing and identifying passkeys and WebAuthn credentials locally. At the end, we will discuss how to remove them.
When having to deal with a lot of credentials, command line tools are not enough. Therefore, we have extended the webauthn-fido2-key-remover, an open-source tool to help identify and delete passkeys more comfortably with multiple domains and multiple passkeys per domain.
Recent Articles
Before we start deleting passkeys, we will go through some basics of Windows 10 cryptography with passkeys. To activate passkeys on Windows 10, the Windows Hello authenticator needs to be activated. Since Windows 10 can operate without a hardware security module (TPM), it can store passkeys within a software-based HSM. However, this method is not as secure as using a physical HSM, which is required for Windows 11.
If you are working on a system where you are not sure if Windows Hello is activated, you can check on https://state-of-passkeys.io for passkey-readiness. If Windows Hello is activated, the check for passkey-ready should hold true:
In case you wonder why Conditional UI works without a platform authenticator (as in the screenshot), you need to know that this behavior can occur on Chrome browsers. Chrome started to return true for Conditional-UI-readiness with version 123 (due to privacy considerations). To activate Windows Hello, open the settings in Windows 10 and navigate to “Sign-in options”. Start by adding a Windows Hello PIN:
Depending on your Windows version, this might look slightly different. After entering the current account password, the PIN can be added. You can continue to add further biometric login methods like "Windows Hello Face" or "Windows Hello Fingerprint," but they are not necessary to activate Windows Hello. They are both shortcuts for the actual PIN. In case a Microsoft account is used with the computer, other forms of verification might be triggered.
Verify that Windows Hello has been successfully activated on https://state-of-passkeys.io/ you should see something like this now:
It is important that not only the WebAuthn API is available and active (“WebAuthn-ready”) but also “Passkey-ready” is
true. For checking the passkey-readiness, the browser is queried
via PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable()
and returns true if a platform authenticator (
Windows Hello) is available.
Windows 10 will not get feature updates anymore but still gets security updates and dominates the desktop market as of May 2024. Our prediction is that Windows 10 will be a major player in the desktop OS market until 2027. Recent statistics released by statcounter even showed that Windows 10 market share increased slightly for two months in a row. Therefore, testing on Windows including version 10 is extremely important for any passkey-based application. You have the following options for testing:
Option 1 - Windows 10 PC (our recommendation): Actually have a real Windows 10 installation in order to have the most realistic experience and see how the actual UI looks. Of course, the best way to test is to actually be developing on Windows 10 but depending on the Enterprise among Frontend-heavy and Native-App focused companies Macs often dominate.
Option 2 - Windows 10 VM on macOS: In case you have an Intel-based macOS device, you can install a Windows 10 image into a simulator like Parallels, but this needs some more effort as this is not officially supported anymore.
Option 3 - Windows 11 VM on macOS: This works very well for a generic feeling of how Windows feels like with the latest version of Chrome. Actual compatibility settings cannot be tested as Windows 11 has a newer Windows Hello version which also includes Cross-Device-Authentication natively, which Windows 10 does not.
At Corbado, we have product managers who volunteered to continue to use Windows 10 as their primary working environment to get an authentic experience of passkeys on Windows 10. As they do not necessarily need to run a full docker system locally that developers might need and which performs better on macOS, it is the best way for us to keep our device coverage. In addition, we have some spare Windows 10 computers for developer testing.
In this section, we will find out how we can list all registered passkeys on a Windows 10 system.
Subscribe to our Passkeys Substack for the latest news, insights and strategies.
SubscribeWindows Hello on Windows 10 stores passkeys and WebAuthn credentials in a secure, system-protected location within the operating system. These credentials are stored in a similar manner to other cryptographic keys and certificates used for authentication and encryption purposes. As we have outlined in the introduction, Windows 10 is prepared to do so even without a HSM in form of an TPM, as this is not a hardware requirement for Windows 10. Here are the different approaches and options for storage:
Windows Hello utilizes the Local Security Authority (LSA) to manage sensitive information such as cryptographic keys and user credentials. LSA Secrets are stored in the Windows registry under HKEY_LOCAL_MACHINE\Security\Policy\Secrets.
These secrets are protected by the LSA and can only be accessed by privileged system processes, making them secure from unauthorized access.
Windows 10 also leverages the Credential Manager to store user credentials. This includes WebAuthn credentials that are created when users register passkeys through their browsers or applications.
The Credential Manager stores these credentials in an encrypted format within the Credential Store, which is located in %SystemRoot%\System32\config\systemprofile\AppData\Local\Microsoft\Credentials.
On systems equipped with a Trusted Platform Module (TPM), Windows Hello can utilize the TPM to provide additional security. The TPM is a hardware-based security feature that securely generates, stores, and manages cryptographic keys.
On systems without a TPM, Windows 10 uses a software-based approach to emulate similar security functions, storing cryptographic keys securely within the system.
Become part of our Passkeys Community for updates and support.
JoinWhen a user registers a new WebAuthn credential, a key pair (public and private keys) is generated. The private key is securely stored on the device (in the LSA Secrets or TPM), while the public key is sent to the authenticating server.
The public key, along with a unique credential ID, is associated with the user's account on the server.
During authentication, the system retrieves the appropriate private key from the secure storage. The user is prompted to verify their identity (e.g., via PIN, fingerprint, or facial recognition).
Once verified, the private key is used to sign a challenge provided by the server, proving the user's identity without exposing the private key itself.
Encryption: All stored credentials and keys are encrypted, ensuring they are protected from unauthorized access even if an attacker gains physical access to the storage medium.
Access Controls: Access to the stored credentials is tightly controlled by the operating system, with only privileged processes having the ability to read or modify them.
Attestation: Windows Hello supports attestation, which allows the device to prove to the server that it holds a genuine key generated by a trusted platform.
In summary, Windows 10 uses a combination of the LSA, Credential Manager, and optionally TPM, to securely store and manage WebAuthn credentials and passkeys. These components work together to ensure that user credentials are protected by strong encryption and access control mechanisms, providing a secure authentication experience.
After activating Windows Hello on the device, we went on and created a passkey on https://state-of-passkeys.io. In this section, we will list the created passkeys and explain more details of them.
To list credentials on the system with existing tools, the command line tool certutil
has to be used:
Command:
certutil -csp NGC -key -v
The command certutil -csp NGC -key -v
involves the use of certutil
, a command-line utility for managing certificates
in Windows. Here’s a breakdown of the command:
certutil
: This is the command-line utility provided by Windows for certificate management tasks. It allows
users to perform various operations related to certificates, including creation, verification, and management of
certificate stores.
-csp NGC
: This specifies the Cryptographic Service Provider (CSP) to be used. CSPs are libraries that implement
cryptographic algorithms and manage keys. NGC (Next Generation Credentials) refers to a CSP associated with the
Next Generation Credentials framework. NGC was introduced by Microsoft to enhance authentication mechanisms in
Windows, especially starting from Windows 10. It is part of Microsoft's move towards more secure and user-friendly
authentication methods, such as Windows Hello for Business, which includes biometric and PIN-based logins.
-key
: This option is used to perform operations related to cryptographic keys. It can include tasks like key
generation, listing, or deletion.
-v
: This stands for verbose mode, which provides detailed output of the command's execution process. It’s
useful for debugging or understanding the steps being performed.
Let’s run this command on a native Windows 10 machine after we created a passkey on https://state-of-passkeys.io/.
Command:
certutil -csp NGC -key -v
Output:
In this example, there is only one passkey registered as we have just activated Windows Hello. In case you had Windows Hello active for a longer time and have registered device-bound passkeys already, the list will be quite extensive.
How to find the right passkey for a specific domain in the Windows 10 certutil export?
The first thing to learn is that Windows Hello actually stores the passkeys under a very long identifier that includes the SHA256 of the relying party ID (domain) where the passkey was created. In our case, we search for the SHA256 representation of "state-of-passkeys.io" (dd52225b9c6….), as you can see below in the table.
How can WebAuthn credentials be distinguished from other entries in the Windows certutil export?
All FIDO2 keys have FIDO_AUTHENTICATOR
as part of their identifier.
How to find the right passkey if you have multiple passkeys associated with a specific domain in the Windows 10 certutil export?
If you have registered multiple passkeys for one domain, you need to decode the user.id
, which is also part of the
identifier. It is encoded as a hex string. In our test, state-of-passkeys.io generated the following unique
user.id (dXNyLTYyMDQzMjkyNzUyMzIyNzA4NjQNjQ
), which we cannot find directly in the export. However, by decoding the
hex string after the SHA256 string, we can identify the passkey that we just generated.
Step | Content |
---|---|
Identifier | S-1-5-21-3027362018-461445109-2096225366-1001/ a4647d39-e794-4db7-bf79-1f672b0b7e6c/FIDO_AUTHENTICATOR// dd52225b9c6e7aafc9d4091b7f97c1b20cbe27644fc1685f65639ede1232aa22_64584e794c5459794d44517a4d6a6b344e7a55794d7a49794e7a41344e6a51 |
SHA256 of rpID | S-1-5-21-3027362018-461445109-2096225366-1001/ a4647d39-e794-4db7-bf79-1f672b0b7e6c/FIDO_AUTHENTICATOR// dd52225b9c6e7aafc9d4091b7f97c1b20cbe27644fc1685f65639ede1232aa22_64584e794c5459794d44517a4d6a6b344e7a55794d7a49794e7a41344e6a51 Explanation: print(hashlib.sha256("state-of-passkeys.io".encode()).hexdigest()) dd52225b9c6e7aafc9d4091b7f97c1b20cbe27644fc1685f65639ede1232aa22 |
user.id as hexcode | S-1-5-21-3027362018-461445109-2096225366-1001/ a4647d39-e794-4db7-bf79-1f672b0b7e6c/FIDO_AUTHENTICATOR// dd52225b9c6e7aafc9d4091b7f97c1b20cbe27644fc1685f65639ede1232aa22_64584e794c5459794d44517a4d6a6b344e7a55794d7a49794e7a41344e6a51 Explanation: print(bytes.fromhex("64584e794c5467304e7a45774e6a41344d54497a4f4449774e6a45784d6a45").decode()) dXNyLTYyMDQzMjkyNzUyMzIyNzA4NjQNjQ |
SHA1 has of public-key | Key Id Hash(sha1): cbd8ad3cc05402afa0bb176708346aea53408832 |
Public-key in hex octets (with address) | |
Actual algorithm used with length | Algorithm Group: RSA Algorithm Name: RSA Length: 2048 (0x800) Lengths: - dwMinLength = 2048 (0x800) - dwMaxLength = 2048 (0x800) - dwIncrement = 0 (0x0) - dwDefaultLength = 2048 (0x800) |
The three other important information that can be seen are:
In the next section we will see how this would look like on Windows 10 Parallels VM on a macOS device.
As we have discussed before, one possible way to test and run Windows is to use a Windows 11 VM on a Mac with Parallels.
Within the VM, we will run certutil
. Windows 11 has passkey management since the 23H2 update, but certutil
still
runs as expected. It is interesting to see that the VM can use the secure enclave of the Mac, generating different key
types. The algorithm used is ECDSA with a much shorter public key. More information about different algorithms can be
found here.
Command:
certutil -csp NGC -key -v
Output:
As in the first example, we have extracted all important information from the command. Keep in mind this key was created
with the same rpID and therefore has the same SHA-256 hash, but the user.id
is different because a different creation
process used a new unique user.id
, and a different key-pair was created.
Step | Content |
---|---|
Identifier | S-1-5-21-2866724682-2111110670-3654107035-1000/4c99708f-4538-4dc8-91ba-9cd4709496b4/FIDO_AUTHENTICATOR// dd52225b9c6e7aafc9d4091b7f97c1b20cbe27644fc1685f65639ede1232aa22_ 64584e794c5467304e7a45774e6a41344d54497a4f4449774e6a45784d6a45 |
SHA256 of rpID | S-1-5-21-2866724682-2111110670-3654107035-1000/4c99708f-4538-4dc8-91ba-9cd4709496b4/FIDO_AUTHENTICATOR// dd52225b9c6e7aafc9d4091b7f97c1b20cbe27644fc1685f65639ede1232aa22_ 64584e794c5467304e7a45774e6a41344d54497a4f4449774e6a45784d6a45 Explanation: print(hashlib.sha256("state-of-passkeys.io".encode()).hexdigest()) dd52225b9c6e7aafc9d4091b7f97c1b20cbe27644fc1685f65639ede1232aa22 |
user.id as hexcode | S-1-5-21-2866724682-2111110670-3654107035-1000/4c99708f-4538-4dc8-91ba-9cd4709496b4/FIDO_AUTHENTICATOR// dd52225b9c6e7aafc9d4091b7f97c1b20cbe27644fc1685f65639ede1232aa22_ **64584e794c5467304e7a45774e6a41344d54497a4f4449774e6a45784d6a45 Explanation: print(bytes.fromhex("64584e794c5467304e7a45774e6a41344d54497a4f4449774e6a45784d6a45").decode()) dXNyLTg0NzEwNjA4MTIzODIwNjExNjExNjExMjE |
SHA1 has of public-key | Key Id Hash(sha1): 495e3b9538dd07f9cee08fdfc4838cd464a6560c |
Public-key in hex octets (with address) | |
Actual algorithm used with length | Algorithm Group: RSA Algorithm Name: ECDSA_P256 Length: 2048 (0x800) Lengths: - dwMinLength = 2048 (0x800) - dwMaxLength = 2048 (0x800) - dwIncrement = 0 (0x0) - dwDefaultLength = 2048 (0x800) |
From the provided certutil output, we can conclude that the key created in the Windows 11 VM using the secure enclave of the Mac is significantly different from the RSA keys typically generated on a native Windows 10 machine. The primary difference lies in the algorithm used: ECDSA (Elliptic Curve Digital Signature Algorithm) versus RSA ( Rivest–Shamir–Adleman). ECDSA keys, specifically ECDSA_P256, are much shorter in length compared to RSA keys while providing equivalent levels of security.
This is evident from the container public key data, which shows a more compact representation in hex octets. Furthermore, the algorithm name ECDSA_P256 highlights the use of elliptic curve cryptography, which is efficient and well-suited for modern secure environments. In contrast, the native Windows 10 example shows RSA with a key length of 2048 bits, which is larger and less efficient in terms of performance.
In this section, we will look at how to delete passkeys to optimize the authenticator performance. With the accumulation of passkeys over time, Windows Hello may slow down, which can be particularly unproductive for developers. Deleting unnecessary or outdated passkeys can help a faster development experience because the authenticator is loading faster.
To delete passkeys using certutil, you need to start a command line with administrative privileges. While listing passkeys can be done without elevated permissions, deleting them requires administrative rights. Here’s how to delete a specific passkey.
certutil -csp NGC -delkey S-1-5-21-3027362018-461445109-2096225366-1001/a4647d39-e794-4db7-bf79-1f672b0b7e6c/FIDO_AUTHENTICATOR//dd52225b9c6e7aafc9d4091b7f97c1b20cbe27644fc1685f65639ede1232aa22_64584e794c5459794d44517a4d6a6b344e7a55794d7a49794e7a41344e6a51
Explanation:
certutil
: Command-line utility provided by Windows for certificate management tasks.
-csp NGC
: This specifies the Cryptographic Service Provider (CSP) to be used. NGC stands for Next Generation
Credentials.
-delkey
: This option is used to delete the specified key.
<Identifier>
: The identifier of the passkey to be deleted. It includes the user SID, a unique identifier for the
passkey, and the SHA256 of the rpID and the hex string user.id
(as explained above).
Using this approach, you can delete the passkeys after selecting the appropriate identifiers manually, which is quite tiring.
In the following section, we will use the webauthn-fido2-key-remover and introduce some smaller tweaks into the source-code.
The original version of webauthn-fido2-key-remover was created in 2021 (long before passkeys appeared). It internally
issues the same commands that we have outlined above but with a CLI. It decodes the user.id
and shows the SHA256 hash
of the rpID. When started with administrative privileges, you can also delete passkeys. Here is a short animation that
shows the functionality (taken from the official README):
When we were using the CLI tool, we still had the difficulties that we would have to lookup the SHA256 hashes (as only a short list of rpIDs where incorporated into the tool).
We have forked and created a pull request with our modifications for the webauthn-fido2-key-remover (has not been merged yet). You can find our version here: https://github.com/kopy/webauthn-fido2-key-remover. The following adjustments have been made:
Adding default rpIDs: We have included common WebAuthn & passkey playgrounds (mainly used by developers during implementation & testing) and also added larger popular platforms like google.com, github.com, and microsoft.com to allow for easier deletion of test accounts here.
CSV lookup functionality for rpIDs: We added functionality to look up rpIDs from custom domain names in a text/CSV
list, enabling further distinction of passkeys from your own environment. The CSV file needs to be in the same path as
the executable and needs to be named domains.csv
.
Minor adjustments: We updated the versions and made some smaller library adjustments necessary due to library version changes.
We plan to release further simplifications, such as a ruleset that automatically deletes test accounts based on their naming.
When testing or working with Windows 10 as a developer in the field of passkeys, there are limited ways to test implementation. However, it is crucial to know how to navigate the Windows Hello authenticator (as the main authenticator for desktop).
Use our adjusted version of webauthn-fido2-key-remover: We recommend running or compiling our version with the custom domain list. This will facilitate the cleanup of unnecessary passkeys and streamline the process of deleting test accounts. You can find our version here: https://github.com/kopy/webauthn-fido2-key-remover.
Easiest way to delete all passkeys: The simplest method to delete all passkeys is to remove the Windows Hello PIN and then re-add it. This action effectively removes all stored passkeys, providing a clean start but keep in mind this might lock you out of some real accounts.
Create a separate Windows user profile: Consider creating a separate Windows user profile specifically for testing purposes. This allows for easier resetting and deleting of all passkeys. Additionally, it is important to test scenarios with a deactivated authenticator to ensure comprehensive coverage.
To ensure a smooth development experience, it is essential to manage passkeys efficiently. By following the outlined steps and using the recommended tools, you can maintain optimal authenticator performance and streamline your workflow.
Managing and deleting passkeys on Windows 10 is essential for maintaining optimal system performance, especially for developers working with passkey-first authentication solutions. We addressed and answered our initial questions:
Understand Windows 10 WebAuthn cryptography: Passkeys and WebAuthn credentials are securely stored in locations such as LSA Secrets and the Credential Store. Credential creation involves generating key pairs, with private keys stored securely on the device and public keys sent to the authenticating server. Security measures include encryption, access controls, and attestation to protect user credentials.
Learn how to manage and remove passkeys on Windows 10: Use the certutil command-line tool to list, analyze, and delete passkeys. Activate Windows Hello to enable passkey functionality. Utilize the webauthn-fido2-key-remover tool for more comfortable passkey management.
By following these steps and recommendations, you can effectively manage and delete passkeys on Windows 10, optimizing the performance of the Windows Hello authenticator and enhancing your overall development experience. This all helps developers in building secure applications to make the Internet a safer place.
Table of Contents
Enjoyed this read?
🤝 Join our Passkeys Community
Share passkeys implementation tips and get support to free the world from passwords.
🚀 Subscribe to Substack
Get the latest news, strategies, and insights about passkeys sent straight to your inbox.
We provide UI components, SDKs and guides to help you add passkeys to your app in <1 hour
Start for free