shuffrand
Version:
Cryptographically secure randomness and shuffling — with soul.
109 lines (108 loc) • 3.64 kB
JavaScript
import { cryptoStringParamsSchema as f } from "./types.es.js";
import { cryptoRandom as y } from "./random.es.js";
import { cryptoShuffle as m } from "./shuffle.es.js";
import { Constants as i } from "./constants.es.js";
/**
* shuffrand - Cryptographically Secure Random String Generation
*
* This file contains the core logic for generating cryptographically secure random strings,
* adhering to a flat, dot-categorized structure for clarity.
*
* @author Doron Brayer <doronbrayer@outlook.com>
* @license MIT
*/
const p = {
alphanumeric: i.ALPHANUMERIC_CHARS,
numeric: i.DIGITS,
alpha: i.LATIN_LETTERS,
hex: i.HEX_CHARS,
uppercase: i.LATIN_UPPERCASE_LETTERS,
lowercase: i.LATIN_LOWERCASE_LETTERS
};
function C(t = {}) {
if (t === null)
throw new TypeError(
"Invalid cryptoString parameters: 'rawParams' cannot be null. Please provide an object or omit it."
);
try {
f.assert(t);
} catch (e) {
throw new TypeError(`Invalid cryptoString parameters: ${e.summary || e.message}`);
}
const r = t.length ?? 16, n = t.characterSet ?? "alphanumeric", h = t.noRepeat ?? !1;
if (r > 1e6)
throw new TypeError(
"Invalid cryptoString parameters: 'length' exceeds maximum safe limit of 1,000,000 characters."
);
let a;
if (typeof n == "string" && Object.prototype.hasOwnProperty.call(p, n))
a = p[n];
else {
a = n;
const e = Array.from(a);
if (new Set(e).size !== e.length)
throw new TypeError(
"Invalid cryptoString parameters: Custom character set contains duplicate characters, which would skew randomness distribution."
);
}
if (a.length === 0 && r > 0)
throw new TypeError("Invalid cryptoString parameters: The resolved 'characterSet' cannot be empty.");
const s = Array.from(new Set(Array.from(a)));
if (s.length < 2 && r > 1)
throw new TypeError(
"Invalid cryptoString parameters: Character set must contain at least 2 unique characters to generate a string longer than 1."
);
if (h && r > s.length)
throw new TypeError(
`Invalid cryptoString parameters: Cannot generate a string of length ${r} with no repeats from a character set with only ${s.length} unique characters.`
);
if (r === 0)
return "";
if (h)
return m(s).slice(0, r).join("");
{
const e = new Array(r), o = Array.from(a), l = o.length;
for (let c = 0; c < r; c++) {
const u = y({
lowerBound: 0,
upperBound: l - 1,
typeOfNum: "integer",
exclusion: "none"
});
e[c] = o[u];
}
return e.join("");
}
}
function d(t = {}) {
try {
f.assert(t);
} catch (o) {
throw new TypeError(`Invalid calculateStringEntropy parameters: ${o.summary || o.message}`);
}
const r = t.length ?? 16, n = t.characterSet ?? "alphanumeric", h = t.noRepeat ?? !1;
let a;
typeof n == "string" && Object.prototype.hasOwnProperty.call(p, n) ? a = p[n] : a = n;
const e = new Set(Array.from(a)).size;
if (h) {
if (r > e)
throw new TypeError(
`Invalid calculateStringEntropy parameters: Cannot calculate entropy for a length of ${r} with no repeats from a character set with only ${e} unique characters.`
);
let o = 0;
for (let l = 0; l < r; l++) {
const c = e - l;
c > 0 && (o += Math.log2(c));
}
return o;
}
if (e < 2 && r > 1)
throw new TypeError(
"Invalid calculateStringEntropy parameters: Character set must contain at least 2 unique characters to calculate meaningful entropy."
);
return e === 0 ? 0 : Math.log2(e) * r;
}
export {
d as calculateStringEntropy,
C as cryptoString
};