This is the last post of a four-part series on cryptographic authentication. Links to earlier posts can be found at the end of this post.
A few months ago I was talking with a business woman about technology topics. As I was trying to explain the concept of cryptographic authentication with a key pair, she asked: what if the attacker steals the computer?
She then told me that a boyfriend had once stolen her computer and used it to launch a devastating attack against her life, which it took her months to recover from, by impersonating her on the internet. We did not discuss the details of the attack, but it is easy to imagine how it may have been carried out. He may have screen-unlocked her computer using her PIN, which she may have given to him before they became estranged, or he may have obtained the PIN through shoulder surfing. Her browser may have saved all her passwords and supplied them as he logged in to her financial and social media accounts with the stolen computer. He may also have been able to extract the passwords from the browser and transfer them to his own computer, using the same PIN to authenticate to the browser.
As I remembered this story I realized that I had missed this attack as I listed attacks relevant to the consumer space in part 2 of the series. I did list theft of the computer by a determined attacker who plans ahead and mounts a prior attack to get the PIN. But this attack is different because the attacker has to make little or no effort to get the PIN if he lives in the same house or apartment as the victim or visits often. It is also a different kind of attack, because the the goal of the attacker is to inflict pain rather than to obtain information or material gain. Together with cyberstalking and other forms of digital abuse against women, the attack belongs in a category that deserves special efforts to protect against. Yet FIDO2 and WebAuthn provide no defense against it, since no password is used, and only a PIN is required to unlock a credential.
A password-centric user experience
Remembering the story also made me rethink the user experience that I was going the propose in this blog post for the strong authentication method that I specified in the previous post (part 3).
I realized that users want passwords because they know that they need passwords. Maybe the real reason for the lack of adoption of FIDO authentication is not the loss-of-credential problem or the cost, as I guessed in part 1 of the series, but the fact that it is passwordless. Finding out whether advertising passwordless authentication attracts end-users or turns them away would be a hot topic for a human-computer interaction study.
The user experience should therefore be centered on the password factor rather than on the cryptographic factor. This can be done by:
- Referring to the cryptographic credential as the second factor, and making it optional, while making the password a required first factor.
- Referring to the cryptographic credential as providing protection for the password. This is technically accurate, since, as I explained in part 3, combining the password with the cryptographic credential protects the combined credential against phishing attacks, backend breaches, and reuse at malicious sites.
- Referring to the combined two-factor credential as a cryptographically protected password.
User experience on a single browser
Here is a password-centric user experience for the authentication method of the last post:
- To register, the user submits her email address together with self-asserted user data in a registration form that the relying party displays on the user’s browser. The relying party then sends a message with an email verification link to the submitted address.
- The user opens the link in her browser, causing the relying party to display a password registration form.
- The password registration form has input boxes for entering and confirming a password, plus a checkbox labeled “Add cryptographic protection to the password”. The label is clickable, and clicking it leads to a help page with frequently asked questions that explains what it means to add cryptographic protection to the password and what the multi-browser experience will be if the user checks the box. Not checking the box will result in the creation of a one-factor password credential, while checking the box will result in the creation of a cryptographic credential that will be combined with the password as described in the previous post (part 3).
- To authenticate, the user visits a login page containing a form
with an input box where the user submits her email address. The
JavaScript frontend of the relying party looks
in
localStorage
for a cryptographic credential associated with the address. - If a cryptographic credential is found, JavaScript code in the login page replaces the email address form with a form where the user enters her password, then authenticates to the backend by sending the public key component of the credential, a signature computed with the private key on a challenge included as JavaScript data in the login page, and a hash of the password with the secret salt component of the credential.
If a cryptographic credential is not found, the frontend sends the email address to the backend, which checks whether one-factor or two-factor authentication is used for the account. If one-factor is used, the backend authenticates the user by verifying the password. The two-factor case it discussed in the multi-browser section below.
User experience on multiple browsers
At first glance, the multi-browser user experience faces an unsurmountable difficulty. To authenticate with the same password on two different browsers, the result of computing the joint hash of the public key with the hash of the password and the secret salt would have to be the same on both browsers. This requires the cryptographic credentials to the same on both browsers. We thus need multi-browser credentials rather than the single-browser credentials of part 1. But syncing credentials across browsers from different vendors is utterly impractical.
This difficulty can be solved by generating the cryptographic
credential in each browser in a manner that produces the same result
in all browsers. In the demo apps referenced
in part
1, the key pair is generated using a deterministic random bit
generator (DRBG) seeded with browser entropy from
Crypto.getRandomValues()
plus downloaded server entropy
from /dev/random
, as described in the GitHub README
files of the demos. To obtain the same result, the DRBG can be
seeded instead with pseudo-random bits derived
using HKDF
from the email address and true random bits generated and stored in
a hardware security module (HSM) such
as AWS CloudHSM.
This reduces security, as the seed has to be transported from the HSM where it is computed to the browser where it is used to generated the credential. But less so than replicating the credential by syncing, which would typically require non-phishing resistant authentication to the party doing the syncing.
With this solution the user experience on multiple browsers is as follows:
- To use a new browser, the user visits the login page on that
browse, enters her email address on the login form, and submits
the form. The
onsubmit
script of the form sees that there is no cryptographic credential in the browser for the email address, and forwards the form with the address to the backend. The backend sees that the account uses a cryptographically protected password, and sends the email address to the HSM, which computes the seed. The backend includes the seed in an email verification message that it sends to the email address. - The user receives the message and opens the link on the new browser.
- The relying party responds with a page containing a password submission form, and JavaScript code with data including the seed and an authentication challenge.
- The user enters the password and submits the form.
- The
onsubmit
script of the form intercepts the submission, generates the cryptographic credential using the seed, and submits the public key, a signature on the challenge computed with the private key, and a hash of the secret salt and the password. - The backend of the relying party verifies the signature using the public key, and authenticates the user by comparing the joint hash of the public key and the salted hash of the password to the joint hash stored in the backend database.
See also:
- Part 1: Passwordless Authentication for the Consumer Space
- Part 2: Comparative Security Analysis of Three Cryptographic Authentication Solutions for the Web
- Part 3: Strong Authentication for the Consumer Space
- Overview of the series in the cryptographic authentication page