diff --git a/ext/node/polyfills/internal/errors.ts b/ext/node/polyfills/internal/errors.ts index 61b53fa968..d79232aed7 100644 --- a/ext/node/polyfills/internal/errors.ts +++ b/ext/node/polyfills/internal/errors.ts @@ -624,6 +624,15 @@ function createInvalidArgType( return msg; } +export class ERR_CRYPTO_TIMING_SAFE_EQUAL_LENGTH extends NodeRangeError { + constructor() { + super( + "ERR_CRYPTO_TIMING_SAFE_EQUAL_LENGTH", + "Input buffers must have the same length", + ); + } +} + export class ERR_INVALID_ARG_TYPE_RANGE extends NodeRangeError { constructor(name: string, expected: string | string[], actual: unknown) { const msg = createInvalidArgType(name, expected); @@ -2842,6 +2851,7 @@ export default { ERR_INVALID_ADDRESS_FAMILY, ERR_INVALID_ARG_TYPE, ERR_INVALID_ARG_TYPE_RANGE, + ERR_CRYPTO_TIMING_SAFE_EQUAL_LENGTH, ERR_INVALID_ARG_VALUE, ERR_INVALID_ARG_VALUE_RANGE, ERR_INVALID_ASYNC_ID, diff --git a/ext/node/polyfills/internal_binding/_timingSafeEqual.ts b/ext/node/polyfills/internal_binding/_timingSafeEqual.ts index 559b7685b8..d9811c5505 100644 --- a/ext/node/polyfills/internal_binding/_timingSafeEqual.ts +++ b/ext/node/polyfills/internal_binding/_timingSafeEqual.ts @@ -4,6 +4,7 @@ // deno-lint-ignore-file prefer-primordials import { Buffer } from "node:buffer"; +import { ERR_CRYPTO_TIMING_SAFE_EQUAL_LENGTH } from "ext:deno_node/internal/errors.ts"; function toDataView(ab: ArrayBufferLike | ArrayBufferView): DataView { if (ArrayBuffer.isView(ab)) { @@ -19,7 +20,7 @@ function stdTimingSafeEqual( b: ArrayBufferView | ArrayBufferLike | DataView, ): boolean { if (a.byteLength !== b.byteLength) { - return false; + throw new ERR_CRYPTO_TIMING_SAFE_EQUAL_LENGTH(); } if (!(a instanceof DataView)) { a = toDataView(a); diff --git a/tests/unit_node/crypto/crypto_misc_test.ts b/tests/unit_node/crypto/crypto_misc_test.ts index 007009339d..9f72683398 100644 --- a/tests/unit_node/crypto/crypto_misc_test.ts +++ b/tests/unit_node/crypto/crypto_misc_test.ts @@ -1,7 +1,7 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. import { randomFillSync, randomUUID, timingSafeEqual } from "node:crypto"; import { Buffer } from "node:buffer"; -import { assert, assertEquals } from "../../unit/test_util.ts"; +import { assert, assertEquals, assertThrows } from "../../unit/test_util.ts"; import { assertNotEquals } from "@std/assert"; Deno.test("[node/crypto.getRandomUUID] works the same way as Web Crypto API", () => { @@ -36,3 +36,10 @@ Deno.test("[node/crypto.timingSafeEqual] compares equal Buffer with different by assert(timingSafeEqual(a, b)); }); + +Deno.test("[node/crypto.timingSafeEqual] RangeError on Buffer with different byteLength", () => { + const a = Buffer.from([212, 213]); + const b = Buffer.from([0, 0, 0, 0, 0, 0, 0, 0, 212, 213, 0]); + + assertThrows(() => timingSafeEqual(a, b), RangeError); +});