'use strict'; const common = require('../common'); if (!common.hasCrypto) common.skip('missing crypto'); const assert = require('assert'); const crypto = require('crypto'); // 'should consider equal strings to be equal' assert.strictEqual( crypto.timingSafeEqual(Buffer.from('foo'), Buffer.from('foo')), true ); // 'should consider unequal strings to be unequal' assert.strictEqual( crypto.timingSafeEqual(Buffer.from('foo'), Buffer.from('bar')), false ); { // Test TypedArrays with different lengths but equal byteLengths. const buf = crypto.randomBytes(16).buffer; const a1 = new Uint8Array(buf); const a2 = new Uint16Array(buf); const a3 = new Uint32Array(buf); for (const left of [a1, a2, a3]) { for (const right of [a1, a2, a3]) { assert.strictEqual(crypto.timingSafeEqual(left, right), true); } } } { // When the inputs are floating-point numbers, timingSafeEqual neither has // equality nor SameValue semantics. It just compares the underlying bytes, // ignoring the TypedArray type completely. 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); function test(a, b, { equal, sameValue, timingSafeEqual }) { assert.strictEqual(eq(a, b), equal); assert.strictEqual(is(a, b), sameValue); assert.strictEqual(crypto.timingSafeEqual(a, b), timingSafeEqual); } test(new Float32Array([NaN]), new Float32Array([NaN]), { equal: false, sameValue: true, timingSafeEqual: true }); test(new Float64Array([0]), new Float64Array([-0]), { equal: true, sameValue: false, timingSafeEqual: false }); const x = new BigInt64Array([0x7ff0000000000001n, 0xfff0000000000001n]); test(new Float64Array(x.buffer), new Float64Array([NaN, NaN]), { equal: false, sameValue: true, timingSafeEqual: false }); } assert.throws( () => crypto.timingSafeEqual(Buffer.from([1, 2, 3]), Buffer.from([1, 2])), { code: 'ERR_CRYPTO_TIMING_SAFE_EQUAL_LENGTH', name: 'RangeError', message: 'Input buffers must have the same byte length' } ); assert.throws( () => crypto.timingSafeEqual('not a buffer', Buffer.from([1, 2])), { code: 'ERR_INVALID_ARG_TYPE', name: 'TypeError', } ); assert.throws( () => crypto.timingSafeEqual(Buffer.from([1, 2]), 'not a buffer'), { code: 'ERR_INVALID_ARG_TYPE', name: 'TypeError', } );