-
Notifications
You must be signed in to change notification settings - Fork 0
/
dicelist_password_generator.js
executable file
·163 lines (143 loc) · 4.54 KB
/
dicelist_password_generator.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
require('dotenv').config();
const apiKey = process.env.RANDOMORG_API_KEY;
const apiURL = 'https://api.random.org/json-rpc/2/invoke';
// const apiURL = 'http://localhost:3000/invoke' // mock url
const headers = { 'Content-Type': 'application/json' };
const axios = require('axios');
const fs = require('fs');
const fsPromises = fs.promises;
// Globals
let REMAINING_API_REQUESTS = null;
let REROLL_LIMIT = 5;
let PASSWORD_LENGTH_LIMIT = 7;
//
// ─── UTILITY FUNCTIONS ──────────────────────────────────────────────────────────
//
async function readWordlistFile(filename) {
const fh = await fsPromises.open(filename, 'r');
let result = await fh.readFile({ encoding: 'utf-8', flag: 'r' });
// map file contents into indexable object
result = Object.assign(
{},
...result.split('\n').map((row) => {
return { [row.split(' ')[0]]: row.split(' ').slice(1) };
})
);
await fh.close();
return result;
}
async function selectWordlists(numWords) {
// get list of wordlist files from local folder
let fileNames = await fsPromises.readdir('wordlists/');
// roll to select a random wordlist from list of files
let wordlistRes = await axios.post(
apiURL,
{
jsonrpc: '2.0',
method: 'generateIntegers',
params: {
apiKey: apiKey,
n: numWords,
min: 0,
max: fileNames.length - 1
},
id: 1
},
{ headers }
);
let wordlistRoll = wordlistRes.data.result.random.data;
return wordlistRoll.map((index) => fileNames[index]);
}
async function selectWord(words) {
let result = undefined;
let rollCount = 0;
while (!result) {
if (rollCount >= REROLL_LIMIT) {
throw Error('Max re-rolls exceeded, try rerunning the generator');
}
// 'diceroll' random number scheme
let wordRes = await axios.post(
apiURL,
{
jsonrpc: '2.0',
method: 'generateIntegers',
params: {
apiKey: apiKey,
n: 5,
min: 1,
max: 6
},
id: 2
},
{ headers }
);
REMAINING_API_REQUESTS = wordRes.data.result.requestsLeft;
++rollCount;
let diceroll = wordRes.data.result.random.data.join('');
console.log('Diceroll: ', diceroll);
result = words[diceroll];
// roll until a word match is found
if (!result) {
console.log(`No word(s) found at ${diceroll}, re-rolling...`);
}
}
// if there are multiple words mapped to a roll, pick one randomly
if (result.length > 1) {
let multiWordRes = await axios.post(
apiURL,
{
jsonrpc: '2.0',
method: 'generateIntegers',
params: {
apiKey: apiKey,
n: 1,
min: 0,
max: result.length - 1
},
id: 3
},
{ headers }
);
REMAINING_API_REQUESTS = multiWordRes.data.result.requestsLeft;
result = result[multiWordRes.data.result.random.data[0]];
} else {
result = result[0]; // flatten single word array
}
return result;
}
//
// ─── PASSWORD GENERATOR MAIN ────────────────────────────────────────────────────────
//
(async function main() {
try {
if (!apiKey) {
throw Error('No API key, please add one to .env in the root directory');
}
let pLength = process.argv[2];
if (!Number(pLength)) {
pLength = 3;
} else if (pLength > PASSWORD_LENGTH_LIMIT) {
console.log(`Password length limit is set to ${PASSWORD_LENGTH_LIMIT}`);
pLength = PASSWORD_LENGTH_LIMIT;
}
console.log(`Generating random password length ${pLength}...`);
// Get a wordlist for each word to be used in the password
let passwordWordlists = await selectWordlists(pLength);
console.log('Wordlists:\n', passwordWordlists);
// For each word list, select a randomly chosen word
let passwordPS = await passwordWordlists.map(async (wordlist) => {
let words = await readWordlistFile(`wordlists/${wordlist}`);
let word = await selectWord(words);
return word;
});
// wait for async map functions to finish
const password = await Promise.all(passwordPS);
// print results
console.log('\nYour randomly generated password:');
console.log('\x1b[36m', password.join(' '), '\x1b[37m');
console.log('\nRemaining API Requests:');
console.log('\x1b[33m', `${REMAINING_API_REQUESTS}\n`);
} catch (e) {
console.error(e);
}
})();