mirror of
https://github.com/XFox111/PasswordGeneratorExtension.git
synced 2026-04-22 08:08:01 +03:00
Major 4.0 (#380)
- Migrated to WXT - Migrated to NPM - Added Insert & copy action - Added ESLint
This commit is contained in:
@@ -0,0 +1,128 @@
|
||||
import { GeneratorOptions } from "./storage";
|
||||
|
||||
const Characters =
|
||||
{
|
||||
Uppercase: "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
|
||||
Lowercase: "abcdefghijklmnopqrstuvwxyz",
|
||||
Numeric: "1234567890",
|
||||
Special: "!#$%&*+-=?@^_"
|
||||
};
|
||||
|
||||
const Similar: string = "iIl1Lo0O";
|
||||
const Ambiguous: string = "{}[]()/\\'\"`~,;:.<>";
|
||||
|
||||
export const CharacterHints = { ...Characters, Similar, Ambiguous };
|
||||
|
||||
/**
|
||||
* Generates a random password
|
||||
* @param options Options for password generation
|
||||
* @returns Randomly generated password
|
||||
* @throws Error if options are invalid
|
||||
*/
|
||||
export function GeneratePassword(options: GeneratorOptions): string
|
||||
{
|
||||
ValidateOptions(options);
|
||||
|
||||
let password: string = GetRequiredCharacters(options);
|
||||
const availableCharacters: string = GetAvailableCharacters(options);
|
||||
|
||||
for (let i = password.length; i < options.Length; i++)
|
||||
{
|
||||
const character: string = PickRandomFromArray(availableCharacters);
|
||||
|
||||
if (options.ExcludeRepeating && password.includes(character))
|
||||
i--;
|
||||
else
|
||||
password += character;
|
||||
}
|
||||
|
||||
password = ShuffleString(password);
|
||||
return password;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates options for password generation
|
||||
* @param options Options for password generation
|
||||
* @throws Error if options are invalid
|
||||
*/
|
||||
export function ValidateOptions(options: GeneratorOptions): void
|
||||
{
|
||||
if (options.Length < 4)
|
||||
throw new Error(i18n.t("errors.too_short"));
|
||||
|
||||
const availableCharacters: string = GetAvailableCharacters(options);
|
||||
|
||||
if (availableCharacters.length < 1)
|
||||
throw new Error(i18n.t("errors.no_characters"));
|
||||
|
||||
if (options.ExcludeRepeating && options.Length > availableCharacters.length)
|
||||
throw new Error(i18n.t("errors.too_long"));
|
||||
}
|
||||
|
||||
// Returns a string containing all characters that are available for password generation
|
||||
function GetAvailableCharacters(options: GeneratorOptions): string
|
||||
{
|
||||
let availableCharacters: string = "";
|
||||
|
||||
for (const [key, value] of Object.entries(Characters))
|
||||
if (options[key as keyof GeneratorOptions])
|
||||
availableCharacters += value;
|
||||
|
||||
if (options.ExcludeSimilar)
|
||||
availableCharacters = availableCharacters.replace(new RegExp(`[${Similar}]`, "g"), "");
|
||||
|
||||
if (options.Special && !options.ExcludeAmbiguous)
|
||||
availableCharacters += Ambiguous;
|
||||
|
||||
return availableCharacters;
|
||||
}
|
||||
|
||||
// Returns a string containing all characters from every available set that are required for password generation
|
||||
function GetRequiredCharacters(options: GeneratorOptions): string
|
||||
{
|
||||
let result: string = "";
|
||||
const characters: Record<string, string> = Object.assign({}, Characters);
|
||||
|
||||
if (!options.ExcludeAmbiguous)
|
||||
characters.Special += Ambiguous;
|
||||
|
||||
if (options.ExcludeSimilar)
|
||||
for (const key of Object.keys(characters))
|
||||
characters[key] = characters[key].replace(new RegExp(`[${Similar}]`, "g"), "");
|
||||
|
||||
for (const [key, value] of Object.entries(characters))
|
||||
if (options[key as keyof GeneratorOptions])
|
||||
result += PickRandomFromArray(value);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Picks a random character from a string
|
||||
function PickRandomFromArray(array: string): string
|
||||
{
|
||||
return array[GetRandomInt(0, array.length)];
|
||||
}
|
||||
|
||||
// See https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Math/random
|
||||
// min is inclusive, max is exclusive
|
||||
function GetRandomInt(min: number, max: number): number
|
||||
{
|
||||
const arr = new Uint16Array(1);
|
||||
crypto.getRandomValues(arr); // Using crypto instead of Math.random() as a CSPRNG
|
||||
return Math.floor((arr[0] / 65_536) * (max - min)) + min;
|
||||
}
|
||||
|
||||
// Shuffles a string using Fisher-Yates algorithm and CSPRNG
|
||||
// See https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle
|
||||
function ShuffleString(str: string): string
|
||||
{
|
||||
const arr = str.split("");
|
||||
|
||||
for (let i = arr.length - 1; i > 0; i--)
|
||||
{
|
||||
const j = GetRandomInt(0, i + 1);
|
||||
[arr[i], arr[j]] = [arr[j], arr[i]];
|
||||
}
|
||||
|
||||
return arr.join("");
|
||||
}
|
||||
Reference in New Issue
Block a user