const basicLatin = String.fromCharCode(...range(32, 127)) const makeRandomPassword = ({ length = 32, characters = basicLatin }: { /** Max 256 */ length?: number, characters?: string | ReadonlyArray } = {}) => { const entropyPerCharacter = 8 const statesPerCharacter = 2 ** entropyPerCharacter if (characters.length > statesPerCharacter) throw new Error(`Character count (${characters.length}) must not exceed 2^8 (256)`) const limit = statesPerCharacter - (statesPerCharacter % characters.length) const randomValuesUnderLimit: number[] = [] while (randomValuesUnderLimit.length < length) { const randomValues = crypto.getRandomValues( new Uint8Array(length - randomValuesUnderLimit.length) ) for (const randomValue of randomValues) if (randomValue < limit) randomValuesUnderLimit.push(randomValue) } let result = "" for (const n of randomValuesUnderLimit) result += characters[n % characters.length] return result }