Files
SnowLuma/.pnpm-store/v11/files/40/a99f7b3ec4ba05f1608b3b699cdf21a29e1272a6eaafade30c8c66489db427d6cf8a915a14db5be8dac1b017e3803e9d9fd41b4272444997a089d804966cea
TanTan 2a69b23b47
Dev Build / cleanup (push) Canceled after 0s
Dev Build / typecheck (push) Canceled after 0s
Dev Build / build (linux-arm64, ubuntu-24.04-arm, linux-arm64) (push) Canceled after 0s
Dev Build / build (linux-x64, ubuntu-latest, linux-x64) (push) Canceled after 0s
Dev Build / build (win-x64, windows-latest, win32-x64) (push) Canceled after 0s
Dev Build / dispatch-dev-docker (push) Canceled after 0s
docs: 仓库链接指向本镜像仓库
2026-11-13 09:27:07 +08:00

65 lines
1.7 KiB
Plaintext

import utils from '../../../../scoring/utils.mjs';
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;
};
export { l33tVariant as default };
//# sourceMappingURL=l33t.mjs.map