mirror of
https://github.com/nodejs/node.git
synced 2025-04-28 13:40:37 +00:00
crypto: make timingSafeEqual faster for Uint8Array
Add a fast API that V8 can use if the user supplies Uint8Arrays (including Buffers) to timingSafeEqual. PR-URL: https://github.com/nodejs/node/pull/52341 Reviewed-By: Yagiz Nizipli <yagiz.nizipli@sentry.io> Reviewed-By: Vinícius Lourenço Claro Cardoso <contact@viniciusl.com.br> Reviewed-By: Daniel Lemire <daniel@lemire.me> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
This commit is contained in:
parent
9ef724bc81
commit
08609b5222
22
benchmark/crypto/timingSafeEqual.js
Normal file
22
benchmark/crypto/timingSafeEqual.js
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const common = require('../common.js');
|
||||||
|
const assert = require('node:assert');
|
||||||
|
const { randomBytes, timingSafeEqual } = require('node:crypto');
|
||||||
|
|
||||||
|
const bench = common.createBenchmark(main, {
|
||||||
|
n: [1e5],
|
||||||
|
bufferSize: [10, 100, 200, 2_100, 22_023],
|
||||||
|
});
|
||||||
|
|
||||||
|
function main({ n, bufferSize }) {
|
||||||
|
const bufs = [randomBytes(bufferSize), randomBytes(bufferSize)];
|
||||||
|
bench.start();
|
||||||
|
let count = 0;
|
||||||
|
for (let i = 0; i < n; i++) {
|
||||||
|
const ret = timingSafeEqual(bufs[i % 2], bufs[1]);
|
||||||
|
if (ret) count++;
|
||||||
|
}
|
||||||
|
bench.end(n);
|
||||||
|
assert.strictEqual(count, Math.floor(n / 2));
|
||||||
|
}
|
@ -9,6 +9,8 @@
|
|||||||
|
|
||||||
namespace node {
|
namespace node {
|
||||||
|
|
||||||
|
using v8::FastApiCallbackOptions;
|
||||||
|
using v8::FastApiTypedArray;
|
||||||
using v8::FunctionCallbackInfo;
|
using v8::FunctionCallbackInfo;
|
||||||
using v8::Local;
|
using v8::Local;
|
||||||
using v8::Object;
|
using v8::Object;
|
||||||
@ -46,12 +48,32 @@ void TimingSafeEqual(const FunctionCallbackInfo<Value>& args) {
|
|||||||
CRYPTO_memcmp(buf1.data(), buf2.data(), buf1.size()) == 0);
|
CRYPTO_memcmp(buf1.data(), buf2.data(), buf1.size()) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FastTimingSafeEqual(Local<Value> receiver,
|
||||||
|
const FastApiTypedArray<uint8_t>& a,
|
||||||
|
const FastApiTypedArray<uint8_t>& b,
|
||||||
|
// NOLINTNEXTLINE(runtime/references)
|
||||||
|
FastApiCallbackOptions& options) {
|
||||||
|
uint8_t* data_a;
|
||||||
|
uint8_t* data_b;
|
||||||
|
if (a.length() != b.length() || !a.getStorageIfAligned(&data_a) ||
|
||||||
|
!b.getStorageIfAligned(&data_b)) {
|
||||||
|
options.fallback = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CRYPTO_memcmp(data_a, data_b, a.length()) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static v8::CFunction fast_equal(v8::CFunction::Make(FastTimingSafeEqual));
|
||||||
|
|
||||||
void Initialize(Environment* env, Local<Object> target) {
|
void Initialize(Environment* env, Local<Object> target) {
|
||||||
SetMethodNoSideEffect(
|
SetFastMethodNoSideEffect(
|
||||||
env->context(), target, "timingSafeEqual", TimingSafeEqual);
|
env->context(), target, "timingSafeEqual", TimingSafeEqual, &fast_equal);
|
||||||
}
|
}
|
||||||
void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
|
void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
|
||||||
registry->Register(TimingSafeEqual);
|
registry->Register(TimingSafeEqual);
|
||||||
|
registry->Register(FastTimingSafeEqual);
|
||||||
|
registry->Register(fast_equal.GetTypeInfo());
|
||||||
}
|
}
|
||||||
} // namespace Timing
|
} // namespace Timing
|
||||||
|
|
||||||
|
@ -27,6 +27,11 @@ using CFunctionCallbackWithStrings =
|
|||||||
bool (*)(v8::Local<v8::Value>,
|
bool (*)(v8::Local<v8::Value>,
|
||||||
const v8::FastOneByteString& input,
|
const v8::FastOneByteString& input,
|
||||||
const v8::FastOneByteString& base);
|
const v8::FastOneByteString& base);
|
||||||
|
using CFunctionCallbackWithTwoUint8ArraysFallback =
|
||||||
|
bool (*)(v8::Local<v8::Value>,
|
||||||
|
const v8::FastApiTypedArray<uint8_t>&,
|
||||||
|
const v8::FastApiTypedArray<uint8_t>&,
|
||||||
|
v8::FastApiCallbackOptions&);
|
||||||
using CFunctionWithUint32 = uint32_t (*)(v8::Local<v8::Value>,
|
using CFunctionWithUint32 = uint32_t (*)(v8::Local<v8::Value>,
|
||||||
const uint32_t input);
|
const uint32_t input);
|
||||||
using CFunctionWithDoubleReturnDouble = double (*)(v8::Local<v8::Value>,
|
using CFunctionWithDoubleReturnDouble = double (*)(v8::Local<v8::Value>,
|
||||||
@ -51,6 +56,7 @@ class ExternalReferenceRegistry {
|
|||||||
V(CFunctionCallbackWithBool) \
|
V(CFunctionCallbackWithBool) \
|
||||||
V(CFunctionCallbackWithString) \
|
V(CFunctionCallbackWithString) \
|
||||||
V(CFunctionCallbackWithStrings) \
|
V(CFunctionCallbackWithStrings) \
|
||||||
|
V(CFunctionCallbackWithTwoUint8ArraysFallback) \
|
||||||
V(CFunctionWithUint32) \
|
V(CFunctionWithUint32) \
|
||||||
V(CFunctionWithDoubleReturnDouble) \
|
V(CFunctionWithDoubleReturnDouble) \
|
||||||
V(CFunctionWithInt64Fallback) \
|
V(CFunctionWithInt64Fallback) \
|
||||||
|
Loading…
Reference in New Issue
Block a user