From 87aed17092cbb14d7d5beff1089772d08706bce6 Mon Sep 17 00:00:00 2001 From: Timothy Farrell Date: Fri, 15 May 2026 03:34:22 +0000 Subject: [PATCH] Minor things that Gemma found with Qwen's code --- src/lib/crypto/crypto.js | 23 +++++++++++++++++------ src/lib/models/schema.js | 4 +++- src/lib/storage/db.js | 13 ------------- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/lib/crypto/crypto.js b/src/lib/crypto/crypto.js index 3347673..242e355 100644 --- a/src/lib/crypto/crypto.js +++ b/src/lib/crypto/crypto.js @@ -9,7 +9,7 @@ import { generateId } from '../models/schema.js' -const PBKDF2_ITERATIONS = 100_000 +const PBKDF2_ITERATIONS = 600_000 const SALT_LENGTH = 16 // bytes const IV_LENGTH = 12 // bytes (recommended for AES-GCM) @@ -135,7 +135,7 @@ export async function createTestPayload(masterPassword) { // --- Utility: Uint8Array ↔ Base64 --- -function uint8ArrayToBase64(buffer) { +export function uint8ArrayToBase64(buffer) { const bytes = new Uint8Array(buffer) let binary = '' for (let i = 0; i < bytes.byteLength; i++) { @@ -144,7 +144,7 @@ function uint8ArrayToBase64(buffer) { return btoa(binary) } -function base64ToUint8Array(base64) { +export function base64ToUint8Array(base64) { const binary = atob(base64) const bytes = new Uint8Array(binary.length) for (let i = 0; i < binary.length; i++) { @@ -189,10 +189,21 @@ export function generatePassword({ throw new Error('Password charset is empty — enable at least one character type') } - const randomValues = crypto.getRandomValues(new Uint8Array(length)) + const charsetLength = charset.length + const maxValid = 256 - (256 % charsetLength) + const randomBytes = new Uint8Array(length * 2) let password = '' - for (let i = 0; i < length; i++) { - password += charset[randomValues[i] % charset.length] + let byteIdx = 0 + + while (password.length < length) { + if (byteIdx >= randomBytes.length) { + crypto.getRandomValues(randomBytes) + byteIdx = 0 + } + const byte = randomBytes[byteIdx++] + if (byte < maxValid) { + password += charset[byte % charsetLength] + } } return password } diff --git a/src/lib/models/schema.js b/src/lib/models/schema.js index a35e4b0..87fb88f 100644 --- a/src/lib/models/schema.js +++ b/src/lib/models/schema.js @@ -11,7 +11,9 @@ */ export function generateId() { const timestamp = Date.now().toString(36) - const random = Math.random().toString(36).slice(2, 10) + const randomBytes = new Uint8Array(4) + crypto.getRandomValues(randomBytes) + const random = Array.from(randomBytes).map(b => b.toString(16).padStart(2, '0')).join('').slice(0, 8) return `${timestamp}_${random}` } diff --git a/src/lib/storage/db.js b/src/lib/storage/db.js index 599b2f4..ecf3ea1 100644 --- a/src/lib/storage/db.js +++ b/src/lib/storage/db.js @@ -310,19 +310,6 @@ export async function exportAll() { } } -/** - * Convert a base64 string back to Uint8Array. - * @param {string} base64 - * @returns {Uint8Array} - */ -function base64ToUint8Array(base64) { - const binary = atob(base64) - const bytes = new Uint8Array(binary.length) - for (let i = 0; i < binary.length; i++) { - bytes[i] = binary.charCodeAt(i) - } - return bytes -} /** * Import data from a previously exported JSON object.