Passwordless

One of the recent Windows 11 updates described in release notes that passkeys are now easier than ever to manage in Windows Settings, so I gave it a go to see if it is time to go passwordless for websites that support Web Authentication.

After poking around this functionality for a bit, however, I realized that the line between going passwordless and ending up passwordless is not as bold as one would hope with passkeys, because this technology is not well documented, relies on data hard-wired into a specific device, and on how well tech behemoths, such as Microsoft, Google and Apple, interact with one another, which is not the strongest trait for many of them.

What are passkeys?

There's a lot of marketing-speak in how passkeys are described, focusing mostly on how easy and secure is to use them, rather on what they actually are, like this Windows 11 page from Microsoft:

https://support.microsoft.com/en-us/windows/passkeys-in-windows-301c8944-5ea2-452b-9886-97e4d2ef4422

A passkey is a public/private cryptographic key pair generated by a user's device for each website. The underlying public/private key technology is not new - that padlock in the web browser uses it and so do crypto wallets and SSH keys for remote access to Linux computers, but passkeys organize key pairs in a way that is supposed to work more securely by reducing potentially error-prone human choices in how and when a key pair is generated and used.

For example, when one creates an SSH key pair, it is stored as a password-protected (ideally, but not always) local file and the same pair is often used for gaining access to multiple remote servers, which is not supposed to happen with passkeys that are individually generated for different web applications and typically stored in tampering-proof locations, such as TPM chips in PCs.

A good description of how passkeys work in Web Authentication can be found on this page:

https://webauthn.guide/

In brief, a web application stores a user's public key, while the private key associated with the web application in question is stored locally on one of user's devices. When a user is trying to authenticate, the web application generates a random challenge and sends it to the user's web browser, which interacts with the operating system to generate a response for that challenge that only a holder of the private key associated with the authenticating user can. The response can be verified by the web application using the matching public key, which proves to the web application user's identity.

The advantage of using passkeys over passwords is that there is no shared secret, such as a password or data derived from the password, ever exchanged between the user's client and the web application. This by itself eliminates many forms of security attacks, such as phishing, because the user never enters their password into the UI rendered in the web browser.

How does one use a passkey?

This section describes using a passkey on a PC that is set up with a local Windows account, and without Windows Hello. If the latter were set up, Web Authentication would instead pop up a Windows Hello sign-in dialog and store passkeys in the local TPM module.

Web Authentication with passkeys can be tested on this page:

https://webauthn.io/

After clicking Register on Windows, the system dialog similar to the one shown below pops up. Notice that it is not rendered by the web browser, but rather by Windows.

Windows Security Passkey Registration

Clicking Next presents a QR code, which is scanned by a phone, linking it to the Windows device. The phone must be configured with some form of lock screen authentication for this to work - otherwise Android will refuse creating a passkey.

After the registration is done, when authenticating, a similar dialog pops up, but it would also list the name of the registered phone. Clicking the phone name pops up a question on the phone to enter a lock screen password, after which the the private key stored on the phone will be used to complete the website authentication.

Where is my passkey?

All of this sounds great and promising, but I could not help but wonder where exactly is my passkey stored, so I can ensure it is backed up and, also, just to know where important security bits are stored. This is where it got tricky.

In a typical Windows Hello authentication, Windows would store passkeys in a Microsoft Passport Key Storage Provider, which can be queried with this command (the provider may also be aliased as NGC):

certutil -csp "Microsoft Passport Key Storage Provider" -key

Given that I ended up authenticated on Windows and that the name of the phone was presented in that security dialog, I incorrectly assumed that the passkey is stored somewhere in Windows and the phone was used just to scan the QR code to link the two and to prove that I have access to that phone.

Checking Settings > Accounts > Passkey settings after the registration above, running certutil and checking other places suggested in online discussions, such as passkey settings in Chrome or Edge, did not show the passkey created in this test. It took me some time to find out that my Samsung phone stored passkeys in Google Password Manager, which can be found in Settings > General management > Passwords and autofill > Google.

Great, I deleted this passkey on my phone, in order to verify if this propagates to Windows and, hopefully, the website as well, but no, my phone name still kept popping up in that Windows Security dialog. Clicking through the authentication workflow, the phone still presented an authentication form, but the only choice on it was to use a hardware secure key, proving that the passkey was deleted from the phone.

This was completely unexpected and there was no apparent location in Windows settings where the phone name could be deleted. Imagine authenticating somewhere on a public computer via your phone, thinking it is secure, and then somebody else using that computer while your phone is within the Bluetooth distance, popping up the authentication form.

Searching through Windows settings a bit more, I finally found where Windows stores my phone name, which was in this key in the registry:

HKEY_USERS\
S-1-5-{ID1}\
Software\
Microsoft\
Cryptography\
FIDO\S-1-5-{ID2}\
LinkedDevices\
{ID3}

The name of my phone was in that last ID3 label of the key, which contained 512 bytes of some data. This data seems to be related to how Windows communicates with Android, but I didn't dig deeper into this.

Deleting this registry key while the passkey was still in the phone, did remove my phone name from the Windows Security dialog and I had to repeat the steps with the QR code when I was trying to authenticate again, which allowed me to authenticate without having to register again.

What's the worry?

While the underlying authentication mechanism in passkeys is fantastically awesome, all of these little quirks about where the keys are stored and how they are maintained will cause confusion and quite possibly result in lost passkeys if the hardware storing them is damaged or lost.

In my test, the passkey was stored locally on the phone, but this is not quite obvious from the registration process, given that Windows orchestrates all those pop-ups and interaction with the phone. This, in turn, means that many people may not realize that if they were not backing up their phone before, they would need to arrange for a regular backup, or they risk to lose all of their passkeys if the phone gets damaged or lost.

Moreover, I'm not even sure at this point that those keys can be backed up. Checking how Windows Hello stores these keys in TPM, they are shown as not exportable (certutil -v will show various storage flags). If Android uses a similar approach, does it mean that if I reset my phone all my passkeys are gone, for example? I didn't verify this, but that would be an important question for me to find an answer to before I can switch to passkeys.

The lingering phone name in Windows configuration is another concern that one would expect Microsoft to address right from the beginning - the passkeys settings should show not only passkeys stored on the system, but also the linked ones, so they can be removed. Better yet, the authentication dialog should give users a choice to remember the phone on this system or not, so there is no need to remove anything in the first place.

Final Thoughts

The technology behind passkeys is solid and it, effectively, replaces multiple passwords for different services with a single credential that can be used only on a specific device to protect an unlimited number of strong cryptographic keys stored locally, which in turn can be used to authenticate to any number of remote and local services and applications.

However, at this point all of these cryptographic keys are stored in a single hardware location, such as the TPM on PCs, and may not even be exportable, which equates this solution to transporting all eggs in one basket on a bumpy road. Granted, one must be careful when backing up security data, but that is another problem to solve, which presents fewer challenges than not having any backup of such data at all.

I used similar setups in the past, when I would generate private keys locally and then import the resulting PFX files onto cloud VMs, marking them as non-exportable - that works well because I can still back up properly the original data, but with TPM-backed storage, it appears that there is no way to back up non-exportable keys.

With all this in mind, passkeys seem to me as a usable convenience for websites that offer both options - a password and a passkey, so the latter can be used to authenticate with a couple of clicks, but leaving me the option to access the account if the hardware storage for cryptographic keys fails for any reason. Otherwise, using a good password manager with strong random passwords that can be securely backed up feels like a better option for the time being, until some form of key recovery is introduced into these protocols.

Comments: