Use crypto.getRandomValues() to fill a typed array, then map those values to characters from your chosen alphabet. This produces passwords with entropy equal to log₂(charset_size^length), avoiding the biases inherent in simpler methods like Math.random().
Why Standard Random Functions Fail
Most programming environments offer a basic random function, such as Math.random() in JavaScript. While convenient, these functions are often deterministic or use lower-quality pseudorandom number generators (PRNGs) that prioritize speed over statistical distribution. For security-sensitive tasks like password generation, this can lead to predictable patterns or insufficient entropy, making passwords easier to guess or crack through brute force.
The solution is to use the browser’s native cryptographic random number generator, accessed via crypto.getRandomValues(). This API utilizes the platform’s underlying CSPRNG (Cryptographically Secure Pseudorandom Number Generator), which is the same engine used for generating TLS keys and other security-critical identifiers. It ensures a uniform distribution of values across the entire range of possible outputs, providing a solid foundation for strong passwords. Unlike standard random functions, which may have smaller internal states or shorter periods, the cryptographic generator provides high-quality randomness suitable for authentication systems.
Using crypto.getRandomValues() Correctly
Generating a password involves two main steps: obtaining random bytes and mapping them to characters. First, you request random bytes from the cryptographic API. These bytes are raw numerical values. Next, you map these values to characters in your desired alphabet. This mapping must be done carefully to avoid modulo bias, where certain characters appear more frequently than others due to uneven division of the random range.
Here is a practical example of generating a 16-character password using a standard alphanumeric alphabet (uppercase letters, lowercase letters, and digits). This alphabet has 62 characters.
function generatePassword(length = 16) {
const charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
const charsetLength = charset.length; // 62
const arrayLength = Math.ceil(length * Math.log2(charsetLength) / 8);
// Request enough random bytes to cover the entropy needed
const randomValues = new Uint8Array(arrayLength);
crypto.getRandomValues(randomValues);
let password = "";
// Map random bytes to characters, handling modulo bias
for (let i = 0; i < randomValues.length && password.length < length; i++) {
const value = randomValues[i];
// Calculate the largest multiple of charsetLength that fits in 255
const maxMultiple = Math.floor(255 / charsetLength) * charsetLength;
// Reject values that would cause bias
if (value > maxMultiple) continue;
password += charset[value % charsetLength];
}
return password;
}
console.log(generatePassword(16));
// Example output: "aB3xY9zQ1wP2mN5k"
This approach ensures each character selection is independent and uniformly distributed. The loop handles cases where the random byte value exceeds the largest multiple of the charset size that fits within a byte, preventing certain characters from being slightly more likely than others. This is crucial for maintaining the theoretical entropy of the generated string.
Calculating Entropy in Bits
Entropy measures the unpredictability of a password. For random character passwords, entropy is calculated using the formula: log₂(charset_size^length). This equals length × log₂(charset_size). Using the previous example with a 62-character alphabet and a length of 16, the calculation is 16 × log₂(62). Since log₂(62) is approximately 5.95, the total entropy is roughly 95 bits.
Higher entropy means more possible combinations, making brute-force attacks harder. A 95-bit password offers significantly more security than a shorter password or one drawn from a smaller set of characters. When evaluating password strength, focus on this bit count rather than just character length. Different alphabets yield different entropy per character. For instance, a numeric-only PIN (digits 0-9) has log₂(10) ≈ 3.3 bits per digit, while the alphanumeric set provides nearly 6 bits per character.
PasswordForge displays this entropy calculation directly alongside each generated password, allowing you to verify that your chosen length and character set meet your security requirements without manual calculation. This transparency helps you choose between longer passwords from smaller sets or shorter passwords from larger sets based on your specific needs.
Bulk Generation for Credential Rotation
When managing multiple accounts or rotating credentials across systems, generating passwords one by one becomes inefficient. Bulk generation allows you to create many unique passwords in a single operation. This is particularly useful for service accounts, API keys, or initial setup for multiple users.
The process involves repeating the generation logic for the desired count. Each password should be independent, meaning the generation of one does not influence the next. Using crypto.getRandomValues() ensures this independence. After generating the batch, you can format the output for easy import into other systems. Common formats include CSV, JSON, or plain text lines.
For example, if you need 5 passwords for different departmental accounts, you would run the generation function five times. Each result is stored with its associated account identifier. This batch can then be exported as a CSV file, where each row contains the account name and the corresponding password. This structured format simplifies importing into password managers or configuration files.
Bulk mode in PasswordForge supports generating between 1 and 1,000 passwords at once. Each generated password includes its calculated entropy score. You can export the entire batch as CSV, JSON, or plain text, making it easy to integrate into existing workflows or secrets management systems without additional formatting steps.
Verifying Strength with Offline Checks
Even with high entropy, passwords can be weak if they match common patterns or previously breached credentials. An offline breach check helps verify uniqueness without compromising privacy. This check compares the generated password against a database of known breached passwords.
The check uses a k-anonymity approach. Instead of sending the full password to a server, it sends only the first five characters of the SHA-1 hash of the password. The server returns the matching hashes themselves to resolve collisions caused by truncated queries. If the returned hashes match your prefix, the password might be common. If no hashes are returned, it is likely unique. This minimizes data exposure while providing useful feedback.
This verification step is critical for ensuring that high-entropy passwords are not inadvertently common phrases or default values. By combining cryptographic randomness with breach checking, you achieve both mathematical strength and practical uniqueness. The entire process, from generation to verification, runs client-side, ensuring no sensitive data leaves your browser environment. This local processing guarantees privacy and speed, making it suitable for sensitive environments where data transmission must be minimized.