I think you all have repeatedly heard that "passwords are dead," "passwords are dying out," "new technology will kill passwords," and the like.
We in the FIDO Alliance just came to inform you that the passwords will die out ... in authentication.
Before we start talking about the mass destruction of verbose reptiles, let's go back to our most popular protocol
FIDO U2F about which I wrote earlier .

')
That is, the authentication script with U2F is:
Check in:
- User is registered using login and password
- The server hashes the password using scrypt, argon2, bcrypt and saves to the database
- The user adds his device, storing on the server the public key and the id key pair on the device
Authentication:
- User enters login and password
- The server hashes the password and compares it with the hash in the database
- The server generates a random "call" and sends to the client along with the ID
- The client sends the call, id, token binding, and origin of the U2F session to the token
- The authenticator signs all this with a private key and sends it to the client, and that to the server
- Profit
Today, multifactor authentication using U2F is the easiest, most phishing-resistant and secure authentication method. But even this method has its drawbacks.
Which ones?
Passwords!

Passwords can still be stolen at all stages of authentication:
- Can be stolen using keylogger;
- Can be stolen with problems with TLS (see Heartbleed);
- Can be stolen if the server is vulnerable to code injection, or if there are errors in the code (see Twitter)
- Can be stolen if passwords are weakly hashed or have not been hashed at all.
While there is a password, it can be stolen
And what if you remove the password at all?
Actually, that's what we thought at the FIDO Alliance (we have nothing to do with the hypertext fidonet, although we can potentially be used there) and made FIDO2

For those who have not heard of us, the FIDO Alliance is a consortium that develops open standards for secure authentication. Above in the picture you can see our board members, who actually develop standards.
FIDO2 is our last project, which we have been developing for more than three years. It consists of two parts:
- WebAuthn - JS API for account management on public keys. This is the W3C standard, so it will be required for all browsers. Chrome, Firefox and Edge itself have already publicly announced their work on its support.
- CTAP2 - Client-to-Authenticator 2 is a standard that describes the CBOR protocol for communicating with an authenticator via USB, NFC and BLE.
User
For the user, it’s just:
- User enters name
- Pass verification
- Profit!

Actually, a demonstration:

Protocol
FIDO2 is a member of the FIDO call-response family. There are six basic security mechanisms in the protocol:
1. Call-answer

The first mechanism is call-answer. The server generates a random call and sends it to the client. The client transfers this call to the authenticator, who signs the call and returns it to the client, and the latter in turn to the server. The server, knowing the call, signature and public key, can confirm the signature and thus authenticate the client.
2. Phishing protection

The second mechanism is a session-dependent transaction. When the client receives a call from the server, it adds to the call information about the session: origin (approx:
example.com ), token binding. This information is signed by the authenticator and returned to the server. The server decodes the response and looks at or in the source was himself, and if the user has undergone a phishing attack, the server will be able to see that the source was for example
attacker.com and not
example.com and thus prevent the attack.
3. Protection against replay attacks

To protect against replay attacks, there is a counter in the transaction that is incremented by one for every operation. If the server received a response with a counter whose value is less than or equal to the last saved value, then the server can say for sure that this is a replay attack.
4. Privacy

The fourth protection mechanism is registration-unique key pairs. At each registration, the authenticator generates a random key pair with a random identifier. Thus, even if you and your partner use the same authenticator for both accounts, the server will not be able to recognize this.
During authentication, the identifier of a key pair is transferred to the authenticator, and the latter, using origin and identifier, will find your key pair in its secured database and return the signature.

An alternative to transmitting an identifier is to use resident keys (RK). During authentication, the authenticator will return signatures for all RK key pairs. The client gives the user a choice of a pair and returns the signature to the server. In more detail RK I will paint below.
5. Certification

The fifth mechanism is certification. Sometimes the site needs to know the type of device from the user. For example, in the US, all government agencies are required to use only FIPS (Federal Information Processing Standards) certified devices. There are similar requirements in France, Israel, Russia and other countries. For all this, there is certification.
In the production of authenticators, for every hundred thousand devices the company generates a “lot certificate” and the keys to it and installs them on each device. When registering, the device signs all information with the private key of the party certificate and returns the certificate instead of the public key. The certificate contains information about the authenticator and its AAGUID (Authenticator Attestation GUID). Also, upon receipt of FIDO certification, the company issues a special metadata document, or simply a metadata, and places metadata in our repository accessible to all. The metadata contains information about the authenticator, including its cryptographic characteristics, biometric characteristics if it supports biometrics, algorithms, security levels, a basic description and a lot of other information. On the basis of the available information, the server can judge whether it should receive the authenticator or not.
Certification is different. There is a full version of certification in which the server returns a certificate. There is a self-certification, in which the device does not support certificates, but instead returns the public key of the newly generated pair.
The user can also customize the method by which he wants to return certification. So for example, the user can forbid to return the certification at all and the client will simply delete it, returning the registration response without certification. I will tell about it later.
6. User availability test
One of the fundamental requirements of FIDO is a test for user availability. In this case, it is meant that the authenticator is obliged to make sure that the user is present ... This can be done in different ways: just pressing a button, a fingerprint, a pin code, and more.
WebAuthn
In this section, we will look at the JS API for working with FIDO2.
Credential Management API
WebAuthn is an add-on to the Credential Management API for managing public key accounts. CredMan API is an API (unexpectedly!) For managing user credentials or, to put it simply, it is an API for accessing auto-completion in a browser.
Next, we will look at an example of creating credentials:
navigator.credentials.store({
'type': 'password',
'id': 'alice',
'password': 'VeryRandomPassword123456'
})
:
navigator.credentials
.get({ 'password': true })
.then(credential => {
if (!credential) {
throw new Error('No credentials returned!')
}
let credentials = {
'username': credential.id,
'password': credential.password
}
return fetch('https://example.com/loginEndpoint', {
method: 'POST',
body: JSON.stringify(credentials),
credentials: 'include'
})
})
.then((response) => {
...
})
CredManAPI
pusher.com/sessions/meetup/js-monthly-london/building-a-better-login-with-the-credential-management-apiCreate public-key credential
Public-Key Credential navigator.credentials.create , CreateCredential «publicKey».
var randomChallengeBuffer = new Uint8Array(32);
window.crypto.getRandomValues(randomChallengeBuffer);
var base64id = 'MIIBkzCCATigAwIBAjCCAZMwggE4oAMCAQIwggGTMII='
var idBuffer = Uint8Array.from(window.atob(base64id), c=>c.charCodeAt(0))
var publicKey = {
challenge: randomChallengeBuffer,
rp: { name: "FIDO Example Corporation" },
user: {
id: idBuffer,
name: "alice@example.com",
displayName: "Alice von Wunderland"
},
attestation: 'direct',
pubKeyCredParams: [
{ type: 'public-key', alg: -7 }, // ES256
{ type: 'public-key', alg: -257 } // RS256
]
}
// Note: The following call will cause the authenticator to display UI.
navigator.credentials.create({ publicKey })
.then((newCredentialInfo) => {
console.log('SUCCESS', newCredentialInfo)
})
.catch((error) => {
console.log('FAIL', error)
})
, , :
— challenge user.id
— pubKeyCredParams — , . FIDO2 : RSA-PSS 2048 SHA256/384/512, RSA-PKCS1_3 SHA256/384/512/1, EC SHA256/384/512, secp256/384/521p1(NIST) secp256k1, EdDSA ED25519.
— attestation — , . : none, direct, indirect. Direct , , . None , AAGUID 0x00000000000000000000000000000000. Indirect privacy-ca. - attestation none. , . , 'none' .

Firefox Nightly
:

:
— id/rawId — credId. id base64url rawId.
— response.clientDataJSON — CollectedDataJSON, JSON . clientDataJSON:
{
"challenge": "1KnytoY-it44IiEMx0lK5GBlBvAJeVULPSCw5E-5qpA",
"origin": "http://localhost:3000",
"tokenBinding": {
"status": "not-supported"
},
"type": "webauthn.create"
}
— attestationObject —
CBOR , , , , .

— authData — , rpIdHash, , , , .
— fmt — . WebAuthn «packed», «fido-u2f», «android», «tpm» «safety-net» .
— attStmt — . , .
clientDataJSON clientDataHash. authData clientDataHash signatureBase. attStmt.sig, signatureBase.

Get assertion
navigator.credentials.create , «publicKey».
var randomChallengeBuffer = new Uint8Array(32);
window.crypto.getRandomValues(randomChallengeBuffer);
var idBuffer = encoder.encode("mFuXJYt-0qYZDUBFyN_SW_Cach6U56mrnHA_ZuxtlOnjHLhjfWjYVftbxr4WMmxp1-MG3nRRNQoI7WvvAM0pmw")
var options = {
challenge: randomChallengeBuffer,
allowCredentials: [{ type: "public-key", id: idBuffer }]
}
navigator.credentials.get({ "publicKey": options })
.then((assertion) => {
console.log('SUCCESS', assertion)
})
.catch((error) => {
console.log('FAIL', error)
})
allowCredentials — , (credId). allowCredentials c credId . authenticatorSelection.requireResidentialKey, allowCredentials.
:

, , :
— clientDataJSON.type «webauthn.get»
{
"challenge": "-0NPkC-1zxpcGanUJMbKFdd7Ze0kRphWFy1_Sgc4FpI",
"origin": "http://localhost:3000",
"tokenBinding": {
"status": "not-supported"
},
"type": "webauthn.get"
}
— attestationObject
— authenticatorData authData, authenticatorAttestation
— signature
— userHandle — , user.id
, .
UPD:
webauthn.org ( U2F )
. CTAP2(Client-to-Authenticator 2).
.