Files
SnowLuma/.pnpm-store/v11/files/f6/e4dfb01854696a954aaa3724b142daccdb2ccfe7f9bfc6d229d4ac07fbf50f3fdd13967ff7c4c8aaf36822be765fe004277946fffe4679fe8cfe11b68c64ba
TanTan 2a69b23b47
Dev Build / cleanup (push) Waiting to run
Dev Build / typecheck (push) Waiting to run
docs: 仓库链接指向本镜像仓库
2026-11-13 09:27:07 +08:00

67 lines
1.7 KiB
Plaintext

'use strict';
var utils = require('../../../../scoring/utils.cjs');
const countSubstring = (string, substring) => {
let count = 0;
let pos = string.indexOf(substring);
while (pos >= 0) {
count += 1;
pos = string.indexOf(substring, pos + substring.length);
}
return count;
};
const getCounts = ({
sub,
token
}) => {
// lower-case match.token before calculating: capitalization shouldn't affect l33t calc.
const tokenLower = token.toLowerCase();
// num of subbed chars
const subbedCount = countSubstring(tokenLower, sub.substitution);
// num of unsubbed chars
const unsubbedCount = countSubstring(tokenLower, sub.letter);
return {
subbedCount,
unsubbedCount
};
};
var l33tVariant = ({
l33t,
subs,
token
}) => {
if (!l33t) {
return 1;
}
let variations = 1;
subs.forEach(sub => {
const {
subbedCount,
unsubbedCount
} = getCounts({
sub,
token
});
if (subbedCount === 0 || unsubbedCount === 0) {
// for this sub, password is either fully subbed (444) or fully unsubbed (aaa)
// treat that as doubling the space (attacker needs to try fully subbed chars in addition to
// unsubbed.)
variations *= 2;
} else {
// this case is similar to capitalization:
// with aa44a, U = 3, S = 2, attacker needs to try unsubbed + one sub + two subs
const p = Math.min(unsubbedCount, subbedCount);
let possibilities = 0;
for (let i = 1; i <= p; i += 1) {
possibilities += utils.nCk(unsubbedCount + subbedCount, i);
}
variations *= possibilities;
}
});
return variations;
};
module.exports = l33tVariant;
//# sourceMappingURL=l33t.cjs.map