3

ユーザーを認証するために 2 つの Base64 でエンコードされたトークンを使用する NodeJS を使用してアプリケーションを作成しています。2 つのトークンが XOR されると、データベースに格納されている 3 番目のトークンと一致する必要があります。

これは私が今持っているものです:

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

これは、タイミング攻撃に対して安全ではないと思います。なぜなら、 に 1 を追加すると、similarityおそらく何もしないよりも時間がかかるからです。また、JavaScript の等値演算子がどれほど安全なのかもわかりません。

私の目を引いたバッファを操作するための別のソリューションはnode-buffertoolsですが、これはバッファを比較するために使用memcmpされます (これは安全ではないことを理解しています)。

タイミング攻撃を回避するために、XOR された 2 つのバッファーと 3 番目のバッファーを比較する最良の方法は何ですか? 私は、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 に答える
0

3 つのトークンすべてを XOR し、ゼロと比較できますか?

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 に答える