在讨论了有关base64对于Firestore ID不安全here的问题进行讨论之后,我想知道如何将字符串编码为Firestore“安全”文档ID。
这是问题所在:
/
,对于声明为here 我在另一个问题中询问了base64,它不安全,因为它包含/
因此,在不丢失外部服务提供的用户名的熵的情况下,对字符串进行编码的一种安全方法可能是安全的。这意味着可能会有一个用户名,例如dimi/test1
,另一个用户名是dimitest1
,因此仅去除字符是不可行的。
此外,由于该服务提供了开放的API,并且我的服务通过URL公开了文档ID,因此我不希望通过我的应用程序URLS公开其他服务的用户名。
有什么建议吗?
答案 0 :(得分:2)
使用encodeURI()后跟SHA256。这会将文档ID限制为
Must be valid UTF-8 characters Must be no longer than 1,500 bytes Cannot contain a forward slash (/) Cannot solely consist of a single period (.) or double periods (..) Cannot match the regular expression __.*__
encodeURI用于有效的UTF-8字符。
SHA256的固定长度为256位(或32个字节),因此不超过1,500个字节限制。
根据https://stackoverflow.com/a/12618366/3073280,SHA256个字符为[a-fA-F0-9]。
最后,您提到它将需要熵。 SHA256扩散良好。
答案 1 :(得分:1)
编辑
要非常快速地将字符串转换为uniqueID,请使用crypto.createHash()
。对于给定的字符串输入,结果将是相同的。
您可以使用MD5或SHA256,因为两者都需要相同的时间(平均2.2秒)来计算100万个唯一ID。
代码如下:
const crypto = require('crypto');
function uniqueId(string, algorithm = 'md5') {
return crypto.createHash(algorithm).update(string).digest('hex');
}
console.log('started');
console.time('generateIDsMD5')
for (let i = 0; i < 1000000; i++) {
uniqueId('a string ' + i);
}
console.timeEnd('generateIDsMD5');
console.time('generateIDsSHA256')
for (let i = 0; i < 1000000; i++) {
uniqueId('a string ' + i, 'sha256');
}
console.timeEnd('generateIDsSHA256');
// For instance, It will take around 2.2s average
// to generate 1Million Unique IDs with MD5 or SHA256 encryption
console.log('MD5 string ', uniqueId('a string ' + 1));
console.log('MD5 sameString ', uniqueId('a string ' + 2));
console.log('MD5 sameString ', uniqueId('a string ' + 2));
console.log('SHA256 string ', uniqueId('a string ' + 1, 'sha256'));
console.log('SHA256 sameString ', uniqueId('a string ' + 2, 'sha256'));
console.log('SHA256 sameString ', uniqueId('a string ' + 2, 'sha256'));
console.log('finished');
上级答案
我改编了Firebase中的代码,并通过一些自定义测试将其直接在您的node.js上可用。 100万个ID最多需要3s,100.000个ID最多需要300ms,这是您考虑的日常使用方法。
如果在node.js环境中运行,它使用crypto
被认为非常安全。
下面是使用示例包装的函数:
const crypto = require('crypto');
function autoId(bytesLength) {
const chars =
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
let autoId = '';
while (autoId.length < bytesLength) {
const bytes = crypto.randomBytes(40);
bytes.forEach(b => {
// Length of `chars` is 62. We only take bytes between 0 and 62*4-1
// (both inclusive). The value is then evenly mapped to indices of `char`
// via a modulo operation.
const maxValue = 62 * 4 - 1;
if (autoId.length < bytesLength && b <= maxValue) {
autoId += chars.charAt(b % 62);
}
});
}
return autoId;
}
console.log('started');
console.time('generateIDs')
for (let i = 0; i < 1000000; i++) {
autoId(20);
}
console.timeEnd('generateIDs');
// For instance, It will take around 3s average
// to generate 1 Million Unique IDs with 20 bytes length
console.log('example 20bytes ', autoId(20));
console.log('example 40bytes ', autoId(40));
console.log('example 60bytes ', autoId(60));
console.log('finished');
只需使用node thisfile.js
,您就会看到结果。
由于firebase主要是开源的,我们可以在node.js
中找到用于在此处生成ID的官方uniqueId生成器:https://github.com/googleapis/nodejs-firestore/blob/4f4574afaa8cf817d06b5965492791c2eff01ed5/dev/src/util.ts#L52
重要
如果您要加入2个ID,请不要使用任何斜杠/
,因为您知道这是不允许的,而应使用下划线_
或根本不使用斜杠,因为您可以控制长度ID,因此您应该知道如何相应地拆分ID(40字节包含2个ID,例如20字节)。
Document Ids中的firestore限制为1500个字节,因此您有很多玩法。
更多信息:https://firebase.google.com/docs/firestore/quotas#limits
答案 2 :(得分:0)
我使用Base58,这是我能研究的最安全的