修复商品规则适配与安全随机密码生成
This commit is contained in:
1 parent
c1c8bf2696
commit
51a496822e
3 files changed
+448
-58
No files matched your search
+16
-5
@@ -1,10 +1,20 @@
|
||||
/**
|
||||
* 生成便于辨认的随机密码建议:至少含小写、大写和数字各一位,排除易混字符。
|
||||
* 现有实现使用 Math.random(非密码学随机源),不能当作高强度密钥/令牌生成器;
|
||||
* 即使 e 小于 3,三个必选字符也会保留。此处注释如实说明现有行为,不改变协议。
|
||||
* 使用浏览器安全随机源生成密码:至少含小写、大写和数字各一位,排除易混字符。
|
||||
* 即使要求长度小于 3,三个必选字符也会保留;安全随机源不可用时明确失败,不降级。
|
||||
*/
|
||||
function e(e = 12) {
|
||||
let t = (e) => e[Math.floor(Math.random() * e.length)],
|
||||
const source = globalThis.crypto;
|
||||
if (typeof source?.getRandomValues !== `function`)
|
||||
throw Error(`当前环境不支持安全随机密码生成`);
|
||||
const buffer = new Uint32Array(1);
|
||||
// 只接受能均分为 upperBound 份的区间,避免直接取模让某些字符/洗牌位置概率偏高。
|
||||
function randomIndex(upperBound) {
|
||||
const limit = 2 ** 32 - (2 ** 32 % upperBound);
|
||||
do source.getRandomValues(buffer);
|
||||
while (buffer[0] >= limit);
|
||||
return buffer[0] % upperBound;
|
||||
}
|
||||
let t = (e) => e[randomIndex(e.length)],
|
||||
n = [
|
||||
t(`abcdefghjkmnpqrstuvwxyz`),
|
||||
t(`ABCDEFGHJKMNPQRSTUVWXYZ`),
|
||||
@@ -18,7 +28,8 @@ function e(e = 12) {
|
||||
),
|
||||
i = [...n, ...r];
|
||||
for (let e = i.length - 1; e > 0; e--) {
|
||||
let t = Math.floor(Math.random() * (e + 1));
|
||||
// Fisher–Yates 与字符选取共用无偏采样,不能在打乱阶段重新引入非安全随机源。
|
||||
let t = randomIndex(e + 1);
|
||||
[i[e], i[t]] = [i[t], i[e]];
|
||||
}
|
||||
return i.join(``);
|
||||
|
||||
Reference in new issue
Block a user