summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDivy Srivastava <dj.srivastava23@gmail.com>2024-10-16 14:27:28 +0530
committerGitHub <noreply@github.com>2024-10-16 14:27:28 +0530
commit21fa953f320c66a897822c4c731b2fae5f07c78b (patch)
treeff12dcf66b5712b493042e171309514d09856d23
parent661882f10df198faf0df8f85493ee53ab64fbc97 (diff)
fix(ext/node): timingSafeEqual account for AB byteOffset (#26292)
Fixes https://github.com/denoland/deno/issues/26276
-rw-r--r--ext/node/polyfills/internal_binding/_timingSafeEqual.ts21
-rw-r--r--tests/unit_node/crypto/crypto_misc_test.ts10
2 files changed, 21 insertions, 10 deletions
diff --git a/ext/node/polyfills/internal_binding/_timingSafeEqual.ts b/ext/node/polyfills/internal_binding/_timingSafeEqual.ts
index ff141fdbf..559b7685b 100644
--- a/ext/node/polyfills/internal_binding/_timingSafeEqual.ts
+++ b/ext/node/polyfills/internal_binding/_timingSafeEqual.ts
@@ -5,10 +5,11 @@
import { Buffer } from "node:buffer";
-function assert(cond) {
- if (!cond) {
- throw new Error("assertion failed");
+function toDataView(ab: ArrayBufferLike | ArrayBufferView): DataView {
+ if (ArrayBuffer.isView(ab)) {
+ return new DataView(ab.buffer, ab.byteOffset, ab.byteLength);
}
+ return new DataView(ab);
}
/** Compare to array buffers or data views in a way that timing based attacks
@@ -21,13 +22,11 @@ function stdTimingSafeEqual(
return false;
}
if (!(a instanceof DataView)) {
- a = new DataView(ArrayBuffer.isView(a) ? a.buffer : a);
+ a = toDataView(a);
}
if (!(b instanceof DataView)) {
- b = new DataView(ArrayBuffer.isView(b) ? b.buffer : b);
+ b = toDataView(b);
}
- assert(a instanceof DataView);
- assert(b instanceof DataView);
const length = a.byteLength;
let out = 0;
let i = -1;
@@ -41,7 +40,11 @@ export const timingSafeEqual = (
a: Buffer | DataView | ArrayBuffer,
b: Buffer | DataView | ArrayBuffer,
): boolean => {
- if (a instanceof Buffer) a = new DataView(a.buffer);
- if (a instanceof Buffer) b = new DataView(a.buffer);
+ if (a instanceof Buffer) {
+ a = new DataView(a.buffer, a.byteOffset, a.byteLength);
+ }
+ if (b instanceof Buffer) {
+ b = new DataView(b.buffer, b.byteOffset, b.byteLength);
+ }
return stdTimingSafeEqual(a, b);
};
diff --git a/tests/unit_node/crypto/crypto_misc_test.ts b/tests/unit_node/crypto/crypto_misc_test.ts
index 47a48b1bf..007009339 100644
--- a/tests/unit_node/crypto/crypto_misc_test.ts
+++ b/tests/unit_node/crypto/crypto_misc_test.ts
@@ -1,5 +1,6 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
-import { randomFillSync, randomUUID } from "node:crypto";
+import { randomFillSync, randomUUID, timingSafeEqual } from "node:crypto";
+import { Buffer } from "node:buffer";
import { assert, assertEquals } from "../../unit/test_util.ts";
import { assertNotEquals } from "@std/assert";
@@ -28,3 +29,10 @@ Deno.test("[node/crypto.randomFillSync] array buffer view", () => {
assertEquals(buf.subarray(0, 8), new Uint8Array(8));
assertEquals(buf.subarray(24, 32), new Uint8Array(8));
});
+
+Deno.test("[node/crypto.timingSafeEqual] compares equal Buffer with different byteOffset", () => {
+ const a = Buffer.from([212, 213]);
+ const b = Buffer.from([0, 0, 0, 0, 0, 0, 0, 0, 212, 213]).subarray(8);
+
+ assert(timingSafeEqual(a, b));
+});