diff --git a/dashboard/src/utils/authLoginProof.ts b/dashboard/src/utils/authLoginProof.ts index 492740228..7a71a608b 100644 --- a/dashboard/src/utils/authLoginProof.ts +++ b/dashboard/src/utils/authLoginProof.ts @@ -1,9 +1,9 @@ -import { md5 } from 'js-md5'; +import { md5 } from "js-md5"; export type LoginChallenge = { challenge_id: string; nonce: string; - algorithm: 'pbkdf2_sha256' | 'legacy_md5' | 'argon2'; + algorithm: "pbkdf2_sha256" | "legacy_md5" | "argon2"; iterations?: number; salt?: string; }; @@ -12,13 +12,13 @@ const encoder = new TextEncoder(); function bytesToHex(buffer: ArrayBuffer): string { return Array.from(new Uint8Array(buffer)) - .map((byte) => byte.toString(16).padStart(2, '0')) - .join(''); + .map((byte) => byte.toString(16).padStart(2, "0")) + .join(""); } function hexToBytes(hex: string): Uint8Array { if (hex.length % 2 !== 0) { - throw new Error('Invalid hex payload'); + throw new Error("Invalid hex payload"); } const bytes = new Uint8Array(hex.length / 2); @@ -31,31 +31,40 @@ function hexToBytes(hex: string): Uint8Array { async function signNonce(secret: BufferSource, nonce: string): Promise { const subtle = globalThis.crypto?.subtle; if (!subtle) { - throw new Error('Current browser does not support secure login'); + throw new Error("Current browser does not support secure login"); } const key = await subtle.importKey( - 'raw', + "raw", secret, - { name: 'HMAC', hash: 'SHA-256' }, + { name: "HMAC", hash: "SHA-256" }, false, - ['sign'] + ["sign"] ); - const signature = await subtle.sign('HMAC', key, encoder.encode(nonce)); + const signature = await subtle.sign("HMAC", key, encoder.encode(nonce)); return bytesToHex(signature); } -async function createPbkdf2Proof(password: string, challenge: LoginChallenge): Promise { +async function createPbkdf2Proof( + password: string, + challenge: LoginChallenge, +): Promise { const subtle = globalThis.crypto?.subtle; if (!subtle || !challenge.salt || !challenge.iterations) { - throw new Error('Invalid secure login challenge'); + throw new Error("Invalid secure login challenge"); } - const passwordKey = await subtle.importKey('raw', encoder.encode(password), 'PBKDF2', false, ['deriveBits']); + const passwordKey = await subtle.importKey( + "raw", + encoder.encode(password), + "PBKDF2", + false, + ["deriveBits"], + ); const derivedBits = await subtle.deriveBits( { - name: 'PBKDF2', - hash: 'SHA-256', + name: "PBKDF2", + hash: "SHA-256", salt: hexToBytes(challenge.salt), iterations: challenge.iterations }, @@ -66,16 +75,25 @@ async function createPbkdf2Proof(password: string, challenge: LoginChallenge): P return signNonce(derivedBits, challenge.nonce); } -async function createLegacyMd5Proof(password: string, challenge: LoginChallenge): Promise { - return signNonce(encoder.encode(md5(password).toLowerCase()), challenge.nonce); +async function createLegacyMd5Proof( + password: string, + challenge: LoginChallenge, +): Promise { + return signNonce( + encoder.encode(md5(password).toLowerCase()), + challenge.nonce, + ); } -export async function createLoginProof(password: string, challenge: LoginChallenge): Promise { - if (challenge.algorithm === 'pbkdf2_sha256') { +export async function createLoginProof( + password: string, + challenge: LoginChallenge, +): Promise { + if (challenge.algorithm === "pbkdf2_sha256") { return createPbkdf2Proof(password, challenge); } - if (challenge.algorithm === 'legacy_md5') { + if (challenge.algorithm === "legacy_md5") { return createLegacyMd5Proof(password, challenge); } - throw new Error('Unsupported secure login algorithm'); + throw new Error("Unsupported secure login algorithm"); }