From ed507a0446041e53c3d90da1a6e699a4dc26b1d0 Mon Sep 17 00:00:00 2001 From: Frederik Rothenberger Date: Tue, 19 Mar 2024 11:02:12 +0100 Subject: [PATCH] debug --- .../src/flows/recovery/setupRecovery.ts | 2 +- .../src/utils/WebAuthnIdentityCopy.ts | 73 +++++++++++-------- 2 files changed, 43 insertions(+), 32 deletions(-) diff --git a/src/frontend/src/flows/recovery/setupRecovery.ts b/src/frontend/src/flows/recovery/setupRecovery.ts index 513cfa1d40..26afa6aaf6 100644 --- a/src/frontend/src/flows/recovery/setupRecovery.ts +++ b/src/frontend/src/flows/recovery/setupRecovery.ts @@ -9,8 +9,8 @@ import { IC_DERIVATION_PATH, } from "$src/utils/iiConnection"; import { unreachable, unreachableLax } from "$src/utils/utils"; -import { DerEncodedPublicKey, SignIdentity } from "@dfinity/agent"; import { WebAuthnIdentity } from "$src/utils/WebAuthnIdentityCopy"; +import { DerEncodedPublicKey, SignIdentity } from "@dfinity/agent"; import { confirmSeedPhrase } from "./confirmSeedPhrase"; import { displaySeedPhrase } from "./displaySeedPhrase"; diff --git a/src/frontend/src/utils/WebAuthnIdentityCopy.ts b/src/frontend/src/utils/WebAuthnIdentityCopy.ts index 13b966f925..daaa0844ed 100644 --- a/src/frontend/src/utils/WebAuthnIdentityCopy.ts +++ b/src/frontend/src/utils/WebAuthnIdentityCopy.ts @@ -1,16 +1,16 @@ import { + DER_COSE_OID, DerEncodedPublicKey, PublicKey, - Signature, SignIdentity, - wrapDER, - DER_COSE_OID, + Signature, fromHex, toHex, -} from '@dfinity/agent'; -import borc from 'borc'; -import { randomBytes } from '@noble/hashes/utils'; -import { bufFromBufLike } from '@dfinity/candid'; + wrapDER, +} from "@dfinity/agent"; +import { bufFromBufLike } from "@dfinity/candid"; +import { randomBytes } from "@noble/hashes/utils"; +import borc from "borc"; function _coseToDerEncodedBlob(cose: ArrayBuffer): DerEncodedPublicKey { return wrapDER(cose, DER_COSE_OID).buffer as DerEncodedPublicKey; @@ -68,9 +68,11 @@ export class CosePublicKey implements PublicKey { * @param challenge The challenge to transform into a byte array. By default a hard * coded string. */ -function _createChallengeBuffer(challenge: string | Uint8Array = ''): Uint8Array { - if (typeof challenge === 'string') { - return Uint8Array.from(challenge, c => c.charCodeAt(0)); +function _createChallengeBuffer( + challenge: string | Uint8Array = "" +): Uint8Array { + if (typeof challenge === "string") { + return Uint8Array.from(challenge, (c) => c.charCodeAt(0)); } else { return challenge; } @@ -84,27 +86,29 @@ function _createChallengeBuffer(challenge: string | Uint8Array = ''): U * @param credentialCreationOptions an optional CredentialCreationOptions object */ async function _createCredential( - credentialCreationOptions?: CredentialCreationOptions, + credentialCreationOptions?: CredentialCreationOptions ): Promise { const creds = (await navigator.credentials.create( credentialCreationOptions ?? { publicKey: { authenticatorSelection: { - userVerification: 'preferred', + userVerification: "preferred", }, - attestation: 'direct', + attestation: "direct", challenge: _createChallengeBuffer(), - pubKeyCredParams: [{ type: 'public-key', alg: PubKeyCoseAlgo.ECDSA_WITH_SHA256 }], + pubKeyCredParams: [ + { type: "public-key", alg: PubKeyCoseAlgo.ECDSA_WITH_SHA256 }, + ], rp: { - name: 'Internet Identity Service', + name: "Internet Identity Service", }, user: { id: randomBytes(16), - name: 'Internet Identity', - displayName: 'Internet Identity', + name: "Internet Identity", + displayName: "Internet Identity", }, }, - }, + } )) as PublicKeyCredentialWithAttachment | null; if (creds === null) { @@ -136,8 +140,8 @@ export class WebAuthnIdentity extends SignIdentity { public static fromJSON(json: string): WebAuthnIdentity { const { publicKey, rawId } = JSON.parse(json); - if (typeof publicKey !== 'string' || typeof rawId !== 'string') { - throw new Error('Invalid JSON string.'); + if (typeof publicKey !== "string" || typeof rawId !== "string") { + throw new Error("Invalid JSON string."); } return new this(fromHex(rawId), fromHex(publicKey), undefined); @@ -148,26 +152,33 @@ export class WebAuthnIdentity extends SignIdentity { * @param credentialCreationOptions an optional CredentialCreationOptions Challenge */ public static async create( - credentialCreationOptions?: CredentialCreationOptions, + credentialCreationOptions?: CredentialCreationOptions ): Promise { const creds = await _createCredential(credentialCreationOptions); - if (!creds || creds.type !== 'public-key') { - throw new Error('Could not create credentials. Error: ' + creds + ' creds JSON: ' + JSON.stringify(creds)); + if (!creds || creds.type !== "public-key") { + throw new Error( + "Could not create credentials. Error: " + + creds + + " creds JSON: " + + JSON.stringify(creds) + ); } const response = creds.response as AuthenticatorAttestationResponse; if (response.attestationObject === undefined) { - throw new Error('Was expecting an attestation response.'); + throw new Error("Was expecting an attestation response."); } // Parse the attestationObject as CBOR. - const attObject = borc.decodeFirst(new Uint8Array(response.attestationObject)); + const attObject = borc.decodeFirst( + new Uint8Array(response.attestationObject) + ); return new this( creds.rawId, _authDataToCose(attObject.authData), - creds.authenticatorAttachment ?? undefined, + creds.authenticatorAttachment ?? undefined ); } @@ -176,7 +187,7 @@ export class WebAuthnIdentity extends SignIdentity { public constructor( public readonly rawId: ArrayBuffer, cose: ArrayBuffer, - protected authenticatorAttachment: AuthenticatorAttachment | undefined, + protected authenticatorAttachment: AuthenticatorAttachment | undefined ) { super(); this._publicKey = new CosePublicKey(cose); @@ -203,12 +214,12 @@ export class WebAuthnIdentity extends SignIdentity { publicKey: { allowCredentials: [ { - type: 'public-key', + type: "public-key", id: this.rawId, }, ], challenge: blob, - userVerification: 'preferred', + userVerification: "preferred", }, })) as PublicKeyCredentialWithAttachment; @@ -223,10 +234,10 @@ export class WebAuthnIdentity extends SignIdentity { authenticator_data: new Uint8Array(response.authenticatorData), client_data_json: new TextDecoder().decode(response.clientDataJSON), signature: new Uint8Array(response.signature), - }), + }) ); if (!cbor) { - throw new Error('failed to encode cbor'); + throw new Error("failed to encode cbor"); } return cbor.buffer as Signature; }