Minor things that Gemma found with Qwen's code

This commit is contained in:
Timothy Farrell 2026-05-15 03:34:22 +00:00
parent 0fdcaf4ecc
commit 87aed17092
3 changed files with 20 additions and 20 deletions

View File

@ -9,7 +9,7 @@
import { generateId } from '../models/schema.js' import { generateId } from '../models/schema.js'
const PBKDF2_ITERATIONS = 100_000 const PBKDF2_ITERATIONS = 600_000
const SALT_LENGTH = 16 // bytes const SALT_LENGTH = 16 // bytes
const IV_LENGTH = 12 // bytes (recommended for AES-GCM) const IV_LENGTH = 12 // bytes (recommended for AES-GCM)
@ -135,7 +135,7 @@ export async function createTestPayload(masterPassword) {
// --- Utility: Uint8Array ↔ Base64 --- // --- Utility: Uint8Array ↔ Base64 ---
function uint8ArrayToBase64(buffer) { export function uint8ArrayToBase64(buffer) {
const bytes = new Uint8Array(buffer) const bytes = new Uint8Array(buffer)
let binary = '' let binary = ''
for (let i = 0; i < bytes.byteLength; i++) { for (let i = 0; i < bytes.byteLength; i++) {
@ -144,7 +144,7 @@ function uint8ArrayToBase64(buffer) {
return btoa(binary) return btoa(binary)
} }
function base64ToUint8Array(base64) { export function base64ToUint8Array(base64) {
const binary = atob(base64) const binary = atob(base64)
const bytes = new Uint8Array(binary.length) const bytes = new Uint8Array(binary.length)
for (let i = 0; i < binary.length; i++) { 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') 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 = '' let password = ''
for (let i = 0; i < length; i++) { let byteIdx = 0
password += charset[randomValues[i] % charset.length]
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 return password
} }

View File

@ -11,7 +11,9 @@
*/ */
export function generateId() { export function generateId() {
const timestamp = Date.now().toString(36) 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}` return `${timestamp}_${random}`
} }

View File

@ -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. * Import data from a previously exported JSON object.