in fido.js [124:211]
extensionDataHex: defaultTo(authenticatorData.extensionDataHex, "No extension data"),
clientDataJSONHex: "none",
signatureHex: "none",
userHandleHex: "none"
}
};
await storage.Credentials.create(credential);
return credential;
};
/**
* Verifies a FIDO assertion
* @param {String} uid user id
* @param {EncodedAssertionResponse} assertion AuthenticatorAssertionResponse received from client
* @return {Promise<Credential>} credential object that the assertion verified
*/
fido.verifyAssertion = async (uid, assertion) => {
// https://w3c.github.io/webauthn/#verifying-assertion
// Step 1 and 2 are skipped because this is a sample app
// Step 3: Using credential’s id attribute look up the corresponding
// credential public key.
/** @typeof {Credential} */
const credential = await storage.Credentials.findOne({
uid: uid,
id: assertion.id
});
// Step 4: Let cData, authData and sig denote the value of credential’s
// response's clientDataJSON, authenticatorData, and signature respectively
const cData = assertion.clientDataJSON;
const authData = Buffer.from(assertion.authenticatorData, 'base64');
const sig = Buffer.from(assertion.signature, 'base64');
// Step 5 and 6: Let C be the decoded client data claimed by the signature.
let C;
try {
C = JSON.parse(cData);
} catch (e) {
throw new Error("clientDataJSON could not be parsed");
}
//Step 7-10: Verify client data
validateClientData(C, uid, "webauthn.get");
//Parse authenticator data used for the next few steps
const authenticatorData = parseAuthenticatorData(authData);
//Step 11: Verify that the rpIdHash in authData is the SHA-256 hash of the
//RP ID expected by the Relying Party.
const expectedRpId = defaultTo(assertion.metadata.rpId, hostname)
if (!authenticatorData.rpIdHash.equals(sha256(expectedRpId))) {
throw new Error("RPID hash does not match expected value: sha256(" + expectedRpId + ")");
}
//Step 12: Verify that the User Present bit of the flags in authData is set
if ((authenticatorData.flags & 0b00000001) == 0) {
throw new Error("User Present bit was not set.");
}
//Step 13-14 are skipped because this is a test site
//Step 15: Let hash be the result of computing a hash over the cData using
//SHA-256.
const hash = sha256(cData);
//Step 16: Using the credential public key looked up in step 3, verify
//that sig is a valid signature over the binary concatenation of authData
//and hash.
const publicKey = JSON.parse(credential.creationData.publicKey);
const publicKeyEd = publicKey.key;
var verify;
if (publicKey.kty === "RSA")
{
verify = crypto.createVerify('RSA-SHA256');
verify.update(authData);
verify.update(hash);
if (!verify.verify(jwkToPem(publicKey), sig))
throw new Error("Could not verify signature");
}
else if (publicKey.kty === "EC")
{
if (publicKey.crv === "P-256")
{