我正在使用NodeJS编写一个应用程序,该应用程序使用两个Base64编码的令牌来验证用户身份。 XORed时,两个标记应与存储在数据库中的第三个标记匹配。
这就是我现在所拥有的:
function verifyTokens(encodedTokens) {
var similarity = 0;
var buffers = encodedTokens.map(base64.decode);
for (i = 0; i < TOKEN_LENGTH; i++) {
if ((buffers[0][i] ^ buffers[1][i]) === buffers[2][i]) {
similarity += 1;
}
}
return (similarity === TOKEN_LENGTH);
}
我认为这对时间攻击是不安全的,因为向similarity
添加1可能比无所事事花费更多时间。我也不知道JavaScript相等运算符的安全性。
使用引起我注意的缓冲区的另一个解决方案是node-buffertools,但它使用memcmp
来比较缓冲区(我理解这不安全)。
将两个XORed缓冲区与第三个缓冲区进行比较以避免计时攻击的最佳方法是什么?我更喜欢仅基于JavaScript的解决方案,而不是C ++扩展。
答案 0 :(得分:3)
您可以添加结果布尔值:
function verifyTokens(encodedTokens) {
var buffers = encodedTokens.map(base64.decode);
var similarity = 0;
for (var i = 0; i < TOKEN_LENGTH; i++) {
similarity += (buffers[0][i] ^ buffers[1][i]) === buffers[2][i]);
}
return similarity === TOKEN_LENGTH;
}
虽然V8可能会对此进行优化并使结果出现偏差。你可以自己测试一下。我先测试encodedTokens.map(base64.decode)
。
答案 1 :(得分:3)
function verifyTokens(encodedTokens) {
var similarity = 0;
var buffers = encodedTokens.map(base64.decode);
for (i = 0; i < TOKEN_LENGTH; i++) {
similarity |= (buffers[0][i] ^ buffers[1][i]) | (buffers[1][i] ^ buffers[2][i]);
}
return similarity === 0;
}
可能是同样的事情,但人们通常don't trust比较运算符。
答案 2 :(得分:0)
你可以对所有三个令牌进行异或并比较为零吗?
var zeroes = new Buffer(Array(32)); // zero fills, not sure encoding
function verifyTokens(encodedTokens) {
var buffers = encodedTokens.map(base64.decode);
var xor1 = buffers[0] ^ buffers[1];
var xor2 = xor1 ^ buffers[2];
if(xor2.toString() === zeroes.toString()){
// there may be a better comparison operator
// buf1 === buf2 seems to always return false with different encodings
return true;
} else {
return false;
}
}