mirror of
https://github.com/bitwarden/browser
synced 2025-12-06 00:13:28 +00:00
[PM-18809] Passkey: use ArrayBuffer instead of Uint8Array (#15092)
* Passkey: use ArrayBuffer instead of Uint8Array to conform WebAuthn spec * ArrayBufferView generics was too modern for this project * Correctly update the types from Uint8arrays to ArrayBuffers * Fixed broken tests + bugs * Removed arrayBufferViewToArrayBuffer as it's not needed in this invocation paths --------- Co-authored-by: ozraru <ozraru@raru.work> Co-authored-by: Todd Martin <106564991+trmartin4@users.noreply.github.com>
This commit is contained in:
@@ -209,7 +209,7 @@ export class DesktopAutofillService implements OnDestroy {
|
||||
}
|
||||
|
||||
request.credentialId = Array.from(
|
||||
parseCredentialId(decrypted.login.fido2Credentials?.[0].credentialId),
|
||||
new Uint8Array(parseCredentialId(decrypted.login.fido2Credentials?.[0].credentialId)),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -336,12 +336,12 @@ export class DesktopAutofillService implements OnDestroy {
|
||||
response: Fido2AuthenticatorGetAssertionResult,
|
||||
): autofill.PasskeyAssertionResponse {
|
||||
return {
|
||||
userHandle: Array.from(response.selectedCredential.userHandle),
|
||||
userHandle: Array.from(new Uint8Array(response.selectedCredential.userHandle)),
|
||||
rpId: request.rpId,
|
||||
signature: Array.from(response.signature),
|
||||
signature: Array.from(new Uint8Array(response.signature)),
|
||||
clientDataHash: request.clientDataHash,
|
||||
authenticatorData: Array.from(response.authenticatorData),
|
||||
credentialId: Array.from(response.selectedCredential.id),
|
||||
authenticatorData: Array.from(new Uint8Array(response.authenticatorData)),
|
||||
credentialId: Array.from(new Uint8Array(response.selectedCredential.id)),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@ export class Fido2AuthenticatorError extends Error {
|
||||
}
|
||||
|
||||
export interface PublicKeyCredentialDescriptor {
|
||||
id: Uint8Array;
|
||||
id: ArrayBuffer;
|
||||
transports?: ("ble" | "hybrid" | "internal" | "nfc" | "usb")[];
|
||||
type: "public-key";
|
||||
}
|
||||
@@ -155,9 +155,9 @@ export interface Fido2AuthenticatorGetAssertionParams {
|
||||
|
||||
export interface Fido2AuthenticatorGetAssertionResult {
|
||||
selectedCredential: {
|
||||
id: Uint8Array;
|
||||
userHandle?: Uint8Array;
|
||||
id: ArrayBuffer;
|
||||
userHandle?: ArrayBuffer;
|
||||
};
|
||||
authenticatorData: Uint8Array;
|
||||
signature: Uint8Array;
|
||||
authenticatorData: ArrayBuffer;
|
||||
signature: ArrayBuffer;
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ describe("credential-id-utils", () => {
|
||||
new Uint8Array([
|
||||
0x08, 0xd7, 0x0b, 0x74, 0xe9, 0xf5, 0x45, 0x22, 0xa4, 0x25, 0xe5, 0xdc, 0xd4, 0x01, 0x07,
|
||||
0xe7,
|
||||
]),
|
||||
]).buffer,
|
||||
);
|
||||
});
|
||||
|
||||
@@ -20,7 +20,7 @@ describe("credential-id-utils", () => {
|
||||
new Uint8Array([
|
||||
0x08, 0xd7, 0x0b, 0x74, 0xe9, 0xf5, 0x45, 0x22, 0xa4, 0x25, 0xe5, 0xdc, 0xd4, 0x01, 0x07,
|
||||
0xe7,
|
||||
]),
|
||||
]).buffer,
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
import { Fido2Utils } from "./fido2-utils";
|
||||
import { guidToRawFormat } from "./guid-utils";
|
||||
|
||||
export function parseCredentialId(encodedCredentialId: string): Uint8Array {
|
||||
export function parseCredentialId(encodedCredentialId: string): ArrayBuffer {
|
||||
try {
|
||||
if (encodedCredentialId.startsWith("b64.")) {
|
||||
return Fido2Utils.stringToBuffer(encodedCredentialId.slice(4));
|
||||
}
|
||||
|
||||
return guidToRawFormat(encodedCredentialId);
|
||||
return guidToRawFormat(encodedCredentialId).buffer;
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
@@ -18,13 +18,16 @@ export function parseCredentialId(encodedCredentialId: string): Uint8Array {
|
||||
/**
|
||||
* Compares two credential IDs for equality.
|
||||
*/
|
||||
export function compareCredentialIds(a: Uint8Array, b: Uint8Array): boolean {
|
||||
if (a.length !== b.length) {
|
||||
export function compareCredentialIds(a: ArrayBuffer, b: ArrayBuffer): boolean {
|
||||
if (a.byteLength !== b.byteLength) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (let i = 0; i < a.length; i++) {
|
||||
if (a[i] !== b[i]) {
|
||||
const viewA = new Uint8Array(a);
|
||||
const viewB = new Uint8Array(b);
|
||||
|
||||
for (let i = 0; i < viewA.length; i++) {
|
||||
if (viewA[i] !== viewB[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -514,7 +514,7 @@ async function getPrivateKeyFromFido2Credential(
|
||||
const keyBuffer = Fido2Utils.stringToBuffer(fido2Credential.keyValue);
|
||||
return await crypto.subtle.importKey(
|
||||
"pkcs8",
|
||||
keyBuffer,
|
||||
new Uint8Array(keyBuffer),
|
||||
{
|
||||
name: fido2Credential.keyAlgorithm,
|
||||
namedCurve: fido2Credential.keyCurve,
|
||||
|
||||
@@ -127,9 +127,9 @@ export class Fido2ClientService<ParentWindowReference>
|
||||
}
|
||||
|
||||
const userId = Fido2Utils.stringToBuffer(params.user.id);
|
||||
if (userId.length < 1 || userId.length > 64) {
|
||||
if (userId.byteLength < 1 || userId.byteLength > 64) {
|
||||
this.logService?.warning(
|
||||
`[Fido2Client] Invalid 'user.id' length: ${params.user.id} (${userId.length})`,
|
||||
`[Fido2Client] Invalid 'user.id' length: ${params.user.id} (${userId.byteLength})`,
|
||||
);
|
||||
throw new TypeError("Invalid 'user.id' length");
|
||||
}
|
||||
|
||||
@@ -47,8 +47,8 @@ export class Fido2Utils {
|
||||
.replace(/=/g, "");
|
||||
}
|
||||
|
||||
static stringToBuffer(str: string): Uint8Array {
|
||||
return Fido2Utils.fromB64ToArray(Fido2Utils.fromUrlB64ToB64(str));
|
||||
static stringToBuffer(str: string): ArrayBuffer {
|
||||
return Fido2Utils.fromB64ToArray(Fido2Utils.fromUrlB64ToB64(str)).buffer;
|
||||
}
|
||||
|
||||
static bufferSourceToUint8Array(bufferSource: BufferSource): Uint8Array {
|
||||
|
||||
Reference in New Issue
Block a user