76 lines
4.2 KiB
JavaScript
76 lines
4.2 KiB
JavaScript
// casegen/rng.js — детермінована випадковість, шифри, паролі
|
||
const crypto = require('crypto');
|
||
const N = require('./names');
|
||
|
||
// ---------- RNG ----------
|
||
function hashSeed(str) {
|
||
let h = 2166136261 >>> 0;
|
||
for (const c of String(str)) { h ^= c.codePointAt(0); h = Math.imul(h, 16777619); }
|
||
return h >>> 0;
|
||
}
|
||
function mulberry32(a) {
|
||
return function () {
|
||
a |= 0; a = (a + 0x6D2B79F5) | 0;
|
||
let t = Math.imul(a ^ (a >>> 15), 1 | a);
|
||
t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;
|
||
return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
|
||
};
|
||
}
|
||
const ri = (r, a, b) => a + Math.floor(r() * (b - a + 1));
|
||
const estRange = (r, actual, lo = 3, hi = 5) => `${actual - ri(r, lo, hi)}–${actual + ri(r, lo, hi)}`;
|
||
const pick = (r, arr) => arr[Math.floor(r() * arr.length)];
|
||
const chance = (r, p) => r() < p;
|
||
function shuffle(r, arr) {
|
||
const a = arr.slice();
|
||
for (let i = a.length - 1; i > 0; i--) { const j = Math.floor(r() * (i + 1)); [a[i], a[j]] = [a[j], a[i]]; }
|
||
return a;
|
||
}
|
||
|
||
// ---------- Шифри ----------
|
||
const UKR = 'абвгґдеєжзиіїйклмнопрстуфхцчшщьюя';
|
||
function caesar(text, k) {
|
||
return [...text].map(ch => {
|
||
const lower = ch.toLowerCase(), i = UKR.indexOf(lower);
|
||
if (i < 0) return ch;
|
||
const out = UKR[(i + k + UKR.length) % UKR.length];
|
||
return ch === lower ? out : out.toUpperCase();
|
||
}).join('');
|
||
}
|
||
const b64 = t => Buffer.from(t, 'utf8').toString('base64');
|
||
const md5 = t => crypto.createHash('md5').update(t, 'utf8').digest('hex');
|
||
|
||
// ---------- Паролі ----------
|
||
const TRANSLIT = { а:'a',б:'b',в:'v',г:'h',ґ:'g',д:'d',е:'e',є:'ie',ж:'zh',з:'z',и:'y',і:'i',ї:'i',й:'i',к:'k',л:'l',м:'m',н:'n',о:'o',п:'p',р:'r',с:'s',т:'t',у:'u',ф:'f',х:'kh',ц:'ts',ч:'ch',ш:'sh',щ:'shch',ь:'',ю:'iu',я:'ia' };
|
||
const translit = s => [...String(s).toLowerCase()].map(c => TRANSLIT[c] ?? c).join('').replace(/[^a-z0-9]/g, '');
|
||
|
||
const COMMON_PASSWORDS = ['sunshine', 'dragon', 'monkey', 'princess', 'football', 'iloveyou',
|
||
'superman', 'batman', 'master', 'hunter', 'freedom', 'trustno1', 'whatever', 'ginger',
|
||
'flower', 'summer', 'winter', 'orange', 'purple', 'silver', 'letmein', 'qwerty', 'pepper',
|
||
'cookie', 'tigger', 'jasmine', 'soccer', 'maggie', 'hannah', 'ashley', 'chelsea', 'butterfly',
|
||
'password', 'shadow', 'michael', 'jessica', 'charlie', 'daniel', 'jordan', 'matrix', 'falcon',
|
||
'phoenix', 'rainbow', 'diamond', 'banana', 'cheese', 'coffee', 'chocolate', 'midnight',
|
||
'october', 'november', 'chester', 'oliver', 'ranger', 'harley', 'buster', 'george', 'sammy',
|
||
'pumpkin', 'muffin', 'peanut', 'smokey', 'bandit', 'lucky', 'angel', 'lovely', 'sunflower',
|
||
'babygirl', 'bubbles', 'snickers', 'chicken', 'turtle', 'rabbit', 'dolphin', 'junior',
|
||
'dexter', 'guitar', 'hammer', 'winner', 'copper', 'marina', 'sierra', 'tucker', 'willow',
|
||
'zombie', 'viking', 'thunder', 'topgun', 'maverick', 'eclipse', 'scorpion', 'panther'];
|
||
|
||
function genPassword(r, victim) {
|
||
const yr = String(victim.birthYear), yr2 = yr.slice(2);
|
||
const personal = [];
|
||
if (victim.dog) personal.push(
|
||
{ answer: translit(victim.dog), hint: 'кличка собаки латиницею (див. досьє)' },
|
||
{ answer: translit(victim.dog) + yr, hint: 'кличка собаки латиницею + повний рік народження' });
|
||
personal.push(
|
||
{ answer: translit(victim.first) + yr, hint: `ім'я латиницею + повний рік народження` },
|
||
{ answer: translit(victim.last) + yr2, hint: 'прізвище латиницею + дві цифри року народження' },
|
||
{ answer: translit(victim.first) + translit(victim.last), hint: `ім'я та прізвище латиницею разом` });
|
||
if (chance(r, 0.5)) {
|
||
const p = pick(r, personal);
|
||
return { ...p, style: 'personal', personal: true };
|
||
}
|
||
return { answer: pick(r, COMMON_PASSWORDS), style: 'random', personal: false,
|
||
hint: 'жодного зв\'язку з жертвою — тільки перебір за словником (rockyou.txt)' };
|
||
}
|
||
|
||
module.exports = { hashSeed, mulberry32, ri, estRange, pick, chance, shuffle, UKR, caesar, b64, md5, translit, COMMON_PASSWORDS, genPassword };
|