3

我正在使用 NodeJS 编写一个应用程序,它使用两个 Base64 编码的令牌来验证用户身份。这两个标记在异或时应该与存储在数据库中的第三个标记匹配。

这就是我现在所拥有的:

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);
}

我相信这对定时攻击是不安全的,因为加 1similarity可能比什么都不做要花费更多的时间。我也不知道 JavaScript 相等运算符有多安全。

另一个引起我注意的处理缓冲区的解决方案是node-buffertools,但它用于memcmp比较缓冲区(我知道这不安全)。

将两个 XORed 缓冲区与避免定时攻击的第三个缓冲区进行比较的最佳方法是什么?与 C++ 扩展相比,我更喜欢纯 JavaScript 解决方案。

4

3 回答 3

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)先测试一下。

于 2013-08-09T15:03:05.837 回答
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;
}

可能是同一件事,但人们通常不信任比较运算符。

于 2013-10-04T14:18:19.667 回答
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;
  }
}
于 2013-08-09T14:59:54.933 回答