Skip to content

Commit

Permalink
doc,test: clarify timingSafeEqual semantics
Browse files Browse the repository at this point in the history
  • Loading branch information
tniessen committed May 28, 2022
1 parent 0818b52 commit ad12313
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 2 deletions.
9 changes: 7 additions & 2 deletions doc/api/crypto.md
Original file line number Diff line number Diff line change
Expand Up @@ -5443,8 +5443,12 @@ changes:
* `b` {ArrayBuffer|Buffer|TypedArray|DataView}
* Returns: {boolean}

This function is based on a constant-time algorithm.
Returns true if `a` is equal to `b`, without leaking timing information that
This function compares the underlying bytes that represent the given
`ArrayBuffer`, `TypedArray`, or `DataView` instances using a constant-time
algorithm. If `a` and `b` are instances of the same `TypedArray` class, this is
equivalent to an element-wise [SameValue comparison][].

This function does not leak timing information that
would allow an attacker to guess one of the values. This is suitable for
comparing HMAC digests or secret values like authentication cookies or
[capability urls](https://www.w3.org/TR/capability-urls/).
Expand Down Expand Up @@ -6104,6 +6108,7 @@ See the [list of SSL OP Flags][] for details.
[RFC 4122]: https://www.rfc-editor.org/rfc/rfc4122.txt
[RFC 5208]: https://www.rfc-editor.org/rfc/rfc5208.txt
[RFC 5280]: https://www.rfc-editor.org/rfc/rfc5280.txt
[SameValue comparison]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Equality_comparisons_and_sameness
[Web Crypto API documentation]: webcrypto.md
[`BN_is_prime_ex`]: https://www.openssl.org/docs/man1.1.1/man3/BN_is_prime_ex.html
[`Buffer`]: buffer.md
Expand Down
22 changes: 22 additions & 0 deletions test/sequential/test-crypto-timing-safe-equal.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,28 @@ assert.strictEqual(
}
}

{
// timingSafeEqual has SameValue semantics, not equality semantics, when the
// inputs are floating-point numbers.

const cmp = (fn) => (a, b) => a.every((x, i) => fn(x, b[i]));
const eq = cmp((a, b) => a === b);
const is = cmp(Object.is);

// NaN !== NaN, but Object.is(NaN, NaN) === true.
const a = new Float32Array(10).fill(NaN);
assert.strictEqual(eq(a, a), false);
assert.strictEqual(is(a, a), true);
assert.strictEqual(crypto.timingSafeEqual(a, a), true);

// 0 === -0, but Object.is(0, -0) === false.
const pos0 = new Float64Array(10).fill(0);
const neg0 = new Float64Array(10).fill(-0);
assert.strictEqual(eq(pos0, neg0), true);
assert.strictEqual(is(pos0, neg0), false);
assert.strictEqual(crypto.timingSafeEqual(pos0, neg0), false);
}

assert.throws(
() => crypto.timingSafeEqual(Buffer.from([1, 2, 3]), Buffer.from([1, 2])),
{
Expand Down

0 comments on commit ad12313

Please sign in to comment.