GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | ||||||||||||||||||||||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | ||||||||||||||||||||||
GeezerVison is showing github.com — doc,test: clarify timingSafeEqual semantics by tniessen · Pull Request #43228 · nodejs/node Conversation
Member
Example of a false positive: const a = new Float32Array(10).fill(NaN); a.every((x, i) => a[i] === x) // false crypto.timingSafeEqual(a, a) // true Example of a false negative: const p0 = new Float32Array(10).fill(0); const m0 = new Float32Array(10).fill(-0); p0.every((x, i) => m0[i] === x) // true crypto.timingSafeEqual(p0, m0) // false (We should probably consider doc-deprecating this or at least we should be more careful about what
Sorry, something went wrong. Uh oh!
There was an error while loading. Please reload this page. All reactions
Member
All reactions
Sorry, something went wrong. Uh oh!
There was an error while loading. Please reload this page.
|
There was an error while loading. Please reload this page.
|
I don't understand the problem here. The two examples given have to do with the larger "problem" of JavaScript equality operator behavior ( On a related note, you could use |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
@mscdex The current documentation does not explicitly say so, and that's exactly what this PR is trying to address.
This would apply to any language that implements a subset of IEE 754.
Sure, but this function is specifically for constant-time comparisons, which |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
Perhaps we should say exactly that then, as the current language this PR adds doesn't make that obvious IMO. Something like "This method compares the underlying bytes that represent any typed array or Buffer."
I was referring to the equality checks inside the |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
289bf9e to
6569cdc
Compare
6569cdc to
2f626d3
Compare
|
Added a test and reworded to closer match JS's understanding of equal versus same. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
What I meant before was adding the note about "underlying bytes" instead of adding this text. If we state we're comparing the underlying bytes, then this text isn't very useful and makes things more confusing.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
I agree. I'd just leave it at "compares bytes" and give it one or two examples. 0 vs. -0 is probably the easiest to understand but different NaNs could work too, e.g.:
const x = new BigInt64Array(["0x7ff0000000000001", "0xfff0000000000001"]) const a = new Float64Array(x.buffer) const b = new Float64Array([NaN, NaN]) Number.isNaN(a[0]) // true Number.isNaN(a[1]) // true crypto.timingSafeEqual(a, b) // false
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
On a related note, you could use
Object.is()instead, which should give you the equality checking you're looking for.
Then I guess this earlier comment wasn't correct? Object.is() is true, unlike timingSafeEqual.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Then I guess this earlier comment wasn't correct? Object.is() is true, unlike timingSafeEqual.
As I said:
I was referring to the equality checks inside the .every() callbacks.
To clarify further:
Object.is(0, -0) === false // so of course `timingSafeEqual()` returns `false` Object.is(NaN, NaN) === true // so of course `timingSafeEqual()` returns `true`
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
@mscdex Your comment appears to imply some (obvious) connection between Object.is() and timingSafeEqual(), but @bnoordhuis' example seems to contradict that:
const a = new Float64Array(new BigInt64Array([0x7ff0000000000001n]).buffer); const b = new Float64Array(new BigInt64Array([0xfff0000000000001n]).buffer); Object.is(a[0], b[0]); // true crypto.timingSafeEqual(a, b); // false
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
LGTM but pinging some other folks on these questions:
@nodejs/documentation @nodejs/crypto @nodejs/testing |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
2f626d3 to
ad12313
Compare
There was an error while loading. Please reload this page.
|
Edit: Reworded and extended again since this does not match @Trott I wouldn't consider it a bug, just a very unusual and permissive function signature... for example, comparing a Edit: As @bnoordhuis pointed out, the semantics are neither equality nor same value. Accepting |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
ad12313 to
20e007c
Compare
| entry, such as `Uint16Array`, the result will be computed using the platform | ||
| byte order. | ||
|
|
||
| <strong class="critical">When both of the inputs are `Float32Array`s or |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
This section is still incorrect and misleading. If the float/double values are the same, then timingSafeEqual() will return true. If the values differ, then timingSafeEqual() will return false.
0 and -0 are different values. The fact that the === operator treats them as being equal is a language "issue", much like how == can return true for two different value types due to type coercion.
timingSafeEqual() is doing the correct and expected comparison here.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Which part is incorrect? The test that's added in this PR demonstrates that timingSafeEqual() can return false even when Object.is() returns true.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
ping @mscdex
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
ping @mscdex @nodejs/documentation @nodejs/crypto |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Landed in 800cff1 |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
PR-URL: #43228 Reviewed-By: Ben Noordhuis <[email protected]> Reviewed-By: Rich Trott <[email protected]>
PR-URL: #43228 Reviewed-By: Ben Noordhuis <[email protected]> Reviewed-By: Rich Trott <[email protected]>
PR-URL: #43228 Reviewed-By: Ben Noordhuis <[email protected]> Reviewed-By: Rich Trott <[email protected]>
PR-URL: nodejs/node#43228 Reviewed-By: Ben Noordhuis <[email protected]> Reviewed-By: Rich Trott <[email protected]>
There was an error while loading. Please reload this page.
Successfully merging this pull request may close these issues.
There was an error while loading. Please reload this page.