Imaging you had a list of silly requirements that a password must adhere to before it was accepted. Lets say we need to have a password that has at least 3 characters that are upper case, 3 that are lower, and 3 that are of a special case. Oh and how about also 3 numbers.
This one is fairly simple as far as complexity and runtime. First, for every requirement we want to add a placeholder to an array. Next.. for each of these placeholders you choose a random character from a predetermined set. Next we want to shuffle our array to make sure our distribution is even. This should produce our new password per our requirements.
The important bit here is the use of the NodeJS crypto library. Using this we can generate a random integer in a range. With that, we can now randomly select our character sets.
1import * as crypto from "node:crypto";
2
3const LOWER_CASE = "abcdefghijklmnopqrstuvwxyz";
4const UPPER_CASE = LOWER_CASE.toLocaleUpperCase();
5const SPECIAL_CHARACTERS = "~!@#$%^&*()_-+=";
6
7function shuffle(arrayToShuffle) {
8 for (let i = 0; i < arrayToShuffle.length; i++) {
9 const j = crypto.randomInt(0, arrayToShuffle.length);
10 const temp = arrayToShuffle[i]
11 arrayToShuffle[i] = arrayToShuffle[j];
12 arrayToShuffle[j] = temp;
13 }
14}
15
16function passwordGenerator({
17 numSpecial = 3,
18 numUpper = 3,
19 numLower = 3,
20 numNumbers = 3,
21}) {
22 let password = [];
23
24 if (numSpecial) {
25 password.push(...[...new Array(numSpecial)].map(()=>'S'))
26 }
27 if (numUpper) {
28 password.push(...[...new Array(numUpper)].map(() => 'A'))
29 }
30 if (numLower) {
31 password.push(...[...new Array(numLower)].map(() => 'a'))
32 }
33 if (numNumbers) {
34 password.push(...[...new Array(numNumbers)].map(() => 'N'))
35 }
36
37 for (let i = 0; i < password.length; i++) {
38 switch (password[i]) {
39 case "A":
40 password[i] = LOWER_CASE.charAt(crypto.randomInt(0, LOWER_CASE.length));
41 break;
42 case "a":
43 password[i] = UPPER_CASE.charAt(crypto.randomInt(0, UPPER_CASE.length));
44 break;
45 case "S":
46 password[i] = SPECIAL_CHARACTERS.charAt(crypto.randomInt(0, SPECIAL_CHARACTERS.length));
47 break;
48 case "N":
49 password[i] = crypto.randomInt(0, 10)
50 break;
51 }
52 }
53
54 shuffle(password)
55
56 return password.join('');
57}
58
You can see the finished demo over on the tools page. It uses Material UI to render sliders, buttons, and typography.