从36个字符的字母表密码安全的string?
我正在尝试生成一些令牌。 他们必须是字母表中的26个字符[a-z0-9]
。
我find的最接近的解决scheme是从这个答案的第2部分,但string将不会均匀分布。
如果我的字母是一个2的长度的权力,这不会是那么难,但现在,我不知道如何正确地做到这一点。
具体来说,这是我到目前为止:
export function createSessionId() { const len = 26; let bytes = new Crypto.randomBytes(len); let result = new Array(len); const alphabet = 'abcdefghijklmnopqrstuvwxyz0123456789'; for(let i=0; i<len; ++i) { result[i] = alphabet[bytes[i]%alphabet.length]; } return result.join(''); }
但是我敢肯定,由于模数的原因,不能正确分配。
让我们看看你在这里:
一个由36个字符组成的36个字符的string,其中每个字符都是用模36一次随机select的,实际上并不是均匀分布的。
你有几个select:
1)select一系列字节来表示总string。 这意味着,您需要select足够的字节来表示0 – 36 ^ 26范围内的数字。 这样,你的价值将会平均分配(只要encryption提供者允许)。
2)如果你坚持每次select一个数字,你想确保它的价值将被均匀分配,使用模36不做你的工作,正如你正确的假设。 在这种情况下,你也可以
- a)将8个字节解释为浮点数并将结果乘以36
- b)用大于26的幂来模数。然后,search比2的幂低的36的最大倍数,丢弃该值空间以外的任何值并以有效值为模36。
对于2a)来说,分布并不是完全平坦的,但是非常接近偶然,假定encryption提供者是公平的。
对于2b),分配是均匀的。 但是,当抛弃不需要的结果时,这将由更高的(特别是不可预知的)运行时支付。 当然,你可以统计计算运行时间,但最坏的情况是无限的,如果你的RNG永远产生无效的结果(这是非常非常不可能,但在理论上是可能的)。
我的build议是2a)。 采取一系列的字节,将它们解释为浮点值并将结果乘以36。
这是我执行Psi的答案,2b。
export function createSessionId() { const len = 26; let bytes = Crypto.randomBytes(30); // a few extra in case we're unlucky let result = new Array(len); const alphabet = 'abcdefghijklmnopqrstuvwxyz0123456789'; let i =0; let j = 0; for(;;) { if(i >= bytes.length) { bytes = Crypto.randomBytes(((len-j)*1.2)|0); // we got unlucky, gather up some more entropy i = 0; } let value = bytes[i++]; if(value >= 252) { // we need a multiple of 36 for an even distribution continue; } result[j++] = alphabet[value % alphabet.length]; if(j >= len) { break; } } return result.join(''); }
有不到2%的机会需要重新注册(4/255),所以我认为这应该是有效的。
很难unit testing这样的事情,但这通过:
test(createSessionId.name, () => { let ids = new Set(); let dist = Array.apply(null,new Array(26)).map(() => ({})); for(let i=0; i<1500; ++i) { let id = createSessionId(); if(ids.has(id)) { throw new Error(`Not unique`); } ids.add(id); for(let j=0; j<id.length; ++j) { dist[j][id[j]] = true; } } for(let i=0; i<26; ++i) { expect(Object.keys(dist[i]).length).toEqual(36); } });
- 我可以通过npm分发非javascript文件吗?
- 使用Express与NodeJS结合REST API的最佳实践
- 为什么webpack的输出path需要是绝对的?
- Postman和一个简单的Http请求之间的差异与superagent
- onClick处理程序不注册ReactDOMServer.renderToString
- 使用JavaScript创build.json文件并在其中存储数据?
- 使用Catberry Framework构build独特组件ID的最佳实践是什么?
- WebSocket错误:在WebSocket握手期间出错:没有在状态行中find响应代码
- ExpressJS发布数据validation并强制执行数据types