From 830048d3e2e10976cdf522cb55c20116199da40a Mon Sep 17 00:00:00 2001
From: Dusan Jakub
clientDataJSON
@@ -345,6 +347,8 @@This contains information about the authentication event. It typically includes the hash of the clientDataJSON, a sign count (to protect against clone attacks), and other data relevant to the authentication process.
+ +signature
@@ -418,6 +422,63 @@ } } + function readHexString(view, start, len){ + const hash = new Uint8Array(len); + + for (let i = 0; i < len; i++) { + hash[i] = view.getUint8(i+start); + } + + return Array.from(hash).map(byte => { + return ('0' + byte.toString(16)).slice(-2); // Ensure two-digit hex representation + }).join(''); + } + + function parseCredentialPubKey(array) { + console.log(array) + let view = new DataView(array.buffer, array.byteOffset, array.byteLength); + let credentialIdLength = view.getUint16(16, false); + return { + "aaguid": readHexString(view, 0, 16), + "credentialIdLength": credentialIdLength, + "credentialId": WebAuthn.bufferToBase64(array.slice(18, credentialIdLength).buffer), + "credentialPublicKey": WebAuthn.bufferToBase64(array.slice(18+credentialIdLength).buffer) + } + } + + function parseAuthenticatorData(array) { + try { + console.log(array) + let view = new DataView(array.buffer, array.byteOffset, array.byteLength); + let flags = view.getInt8(32); + const hashHex = readHexString(view, 0, 32); + + const result = { + "rpIdHash": hashHex, + "flags": { + "userPresent": !!(flags & 1), + "userVerified": !!(flags & (1 << 2)), + "attestedCredentialData": !!(flags & (1 << 6)), + "extensionDataIncluded": !!(flags & (1 << 7)) + }, + "signCount": view.getUint32(33, false), + } + + try { + if (result.flags.attestedCredentialData) { + result['credentialPubKey'] = parseCredentialPubKey(array.slice(37)); + } + } catch (e) { + console.log(e) + } + + return result; + } catch (e) { + console.warn(e) + return "Unable to parse: " + e; + } + } + function tracer(stage, params) { console.log(stage, params) @@ -498,7 +559,10 @@ $("#navigator-attestation").showInViewport(); $("#navigator-attestation-body").html(JSON.stringify(response, null, 2)); $("#navigator-attestation-clientDataJSON").html(JSON.stringify(JSON.parse(tryDecodeBase64(response.response.clientDataJSON)), null, 2)); - $("#navigator-attestationObject").html(JSON.stringify(CBOR.decode(WebAuthn.base64ToBuffer(response.response.attestationObject)), null, 2)); + let attestationObject = CBOR.decode(WebAuthn.base64ToBuffer(response.response.attestationObject)); + let authData = parseAuthenticatorData(attestationObject.authData); + $("#navigator-attestationObject").html(JSON.stringify(attestationObject, null, 2)); + $("#navigator-authData").html(JSON.stringify(authData, null, 2)); return continueButton("#navigator-attestation", response); } @@ -512,6 +576,9 @@ $("#navigator-assertion").showInViewport(); $("#navigator-assertion-body").html(JSON.stringify(response, null, 2)); $("#navigator-assertion-clientDataJSON").html(JSON.stringify(JSON.parse(tryDecodeBase64(response.response.clientDataJSON)), null, 2)); + let authenticatorData = WebAuthn.base64ToBuffer(response.response.authenticatorData); + let authData = parseAuthenticatorData(new Uint8Array(authenticatorData)); + $("#navigator-authenticatorData").html(JSON.stringify(authData, null, 2)); return continueButton("#navigator-assertion", response); }