react-native-quick-crypto 0.3.2 → 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/README.md +10 -6
  2. package/android/CMakeLists.txt +10 -2
  3. package/android/gradle.properties +1 -1
  4. package/android/src/main/cpp/cpp-adapter.cpp +1 -1
  5. package/cpp/Cipher/MGLCipherHostObject.cpp +4 -5
  6. package/cpp/Cipher/MGLCreateCipherInstaller.cpp +1 -3
  7. package/cpp/Cipher/MGLGenerateKeyPairInstaller.h +6 -3
  8. package/cpp/Cipher/MGLGenerateKeyPairSyncInstaller.h +5 -3
  9. package/cpp/Cipher/MGLPublicCipher.h +1 -1
  10. package/cpp/Cipher/MGLPublicCipherInstaller.h +1 -1
  11. package/cpp/Cipher/MGLRsa.h +5 -1
  12. package/cpp/JSIUtils/MGLJSIMacros.h +69 -6
  13. package/cpp/{Cipher/MGLCipherKeys.cpp → MGLKeys.cpp} +47 -49
  14. package/cpp/{Cipher/MGLCipherKeys.h → MGLKeys.h} +29 -30
  15. package/cpp/MGLQuickCryptoHostObject.cpp +12 -0
  16. package/cpp/Sig/MGLSignHostObjects.cpp +889 -0
  17. package/cpp/Sig/MGLSignHostObjects.h +88 -0
  18. package/cpp/Sig/MGLSignInstaller.cpp +24 -0
  19. package/cpp/Sig/MGLSignInstaller.h +29 -0
  20. package/cpp/Sig/MGLVerifyInstaller.cpp +24 -0
  21. package/cpp/Sig/MGLVerifyInstaller.h +22 -0
  22. package/cpp/Utils/MGLUtils.cpp +67 -29
  23. package/cpp/Utils/MGLUtils.h +17 -17
  24. package/lib/commonjs/NativeQuickCrypto/NativeQuickCrypto.js.map +1 -1
  25. package/lib/commonjs/NativeQuickCrypto/sig.js +2 -0
  26. package/lib/commonjs/NativeQuickCrypto/sig.js.map +1 -0
  27. package/lib/commonjs/QuickCrypto.js +4 -0
  28. package/lib/commonjs/QuickCrypto.js.map +1 -1
  29. package/lib/commonjs/keys.js +1 -4
  30. package/lib/commonjs/keys.js.map +1 -1
  31. package/lib/commonjs/sig.js +170 -0
  32. package/lib/commonjs/sig.js.map +1 -0
  33. package/lib/module/NativeQuickCrypto/NativeQuickCrypto.js.map +1 -1
  34. package/lib/module/NativeQuickCrypto/sig.js +2 -0
  35. package/lib/module/NativeQuickCrypto/sig.js.map +1 -0
  36. package/lib/module/QuickCrypto.js +3 -0
  37. package/lib/module/QuickCrypto.js.map +1 -1
  38. package/lib/module/keys.js +1 -4
  39. package/lib/module/keys.js.map +1 -1
  40. package/lib/module/sig.js +155 -0
  41. package/lib/module/sig.js.map +1 -0
  42. package/lib/typescript/NativeQuickCrypto/NativeQuickCrypto.d.ts +3 -0
  43. package/lib/typescript/NativeQuickCrypto/sig.d.ts +12 -0
  44. package/lib/typescript/QuickCrypto.d.ts +3 -0
  45. package/lib/typescript/index.d.ts +2 -3
  46. package/lib/typescript/sig.d.ts +35 -0
  47. package/package.json +3 -3
  48. package/src/NativeQuickCrypto/NativeQuickCrypto.ts +3 -0
  49. package/src/NativeQuickCrypto/sig.ts +17 -0
  50. package/src/QuickCrypto.ts +3 -0
  51. package/src/keys.ts +18 -13
  52. package/src/sig.ts +179 -0
@@ -0,0 +1,889 @@
1
+ #include "MGLSignHostObjects.h"
2
+
3
+ #include <openssl/evp.h>
4
+
5
+ #include <optional>
6
+
7
+ #include "MGLKeys.h"
8
+ #ifdef ANDROID
9
+ #include "JSIUtils/MGLJSIUtils.h"
10
+ #include "JSIUtils/MGLTypedArray.h"
11
+ #include "Utils/MGLUtils.h"
12
+ #else
13
+ #include "MGLJSIUtils.h"
14
+ #include "MGLTypedArray.h"
15
+ #include "MGLUtils.h"
16
+ #endif
17
+
18
+ namespace margelo {
19
+
20
+ bool ValidateDSAParameters(EVP_PKEY* key) {
21
+ /* Validate DSA2 parameters from FIPS 186-4 */
22
+ #if OPENSSL_VERSION_MAJOR >= 3
23
+ if (EVP_default_properties_is_fips_enabled(nullptr) &&
24
+ EVP_PKEY_DSA == EVP_PKEY_base_id(key)) {
25
+ #else
26
+ if (FIPS_mode() && EVP_PKEY_DSA == EVP_PKEY_base_id(key)) {
27
+ #endif
28
+ const DSA* dsa = EVP_PKEY_get0_DSA(key);
29
+ const BIGNUM* p;
30
+ DSA_get0_pqg(dsa, &p, nullptr, nullptr);
31
+ size_t L = BN_num_bits(p);
32
+ const BIGNUM* q;
33
+ DSA_get0_pqg(dsa, nullptr, &q, nullptr);
34
+ size_t N = BN_num_bits(q);
35
+
36
+ return (L == 1024 && N == 160) || (L == 2048 && N == 224) ||
37
+ (L == 2048 && N == 256) || (L == 3072 && N == 256);
38
+ }
39
+
40
+ return true;
41
+ }
42
+
43
+ bool ApplyRSAOptions(const ManagedEVPPKey& pkey, EVP_PKEY_CTX* pkctx,
44
+ int padding, std::optional<int> salt_len) {
45
+ if (EVP_PKEY_id(pkey.get()) == EVP_PKEY_RSA ||
46
+ EVP_PKEY_id(pkey.get()) == EVP_PKEY_RSA2 ||
47
+ EVP_PKEY_id(pkey.get()) == EVP_PKEY_RSA_PSS) {
48
+ if (EVP_PKEY_CTX_set_rsa_padding(pkctx, padding) <= 0) return false;
49
+ if (padding == RSA_PKCS1_PSS_PADDING && salt_len.has_value()) {
50
+ if (EVP_PKEY_CTX_set_rsa_pss_saltlen(pkctx, salt_len.value()) <= 0)
51
+ return false;
52
+ }
53
+ }
54
+
55
+ return true;
56
+ }
57
+
58
+ std::optional<jsi::Value> Node_SignFinal(jsi::Runtime& runtime,
59
+ EVPMDPointer&& mdctx,
60
+ const ManagedEVPPKey& pkey,
61
+ int padding,
62
+ std::optional<int> pss_salt_len) {
63
+ unsigned char m[EVP_MAX_MD_SIZE];
64
+ unsigned int m_len;
65
+
66
+ if (!EVP_DigestFinal_ex(mdctx.get(), m, &m_len)) return {};
67
+
68
+ int signed_sig_len = EVP_PKEY_size(pkey.get());
69
+ CHECK_GE(signed_sig_len, 0);
70
+ size_t sig_len = static_cast<size_t>(signed_sig_len);
71
+
72
+ MGLTypedArray<MGLTypedArrayKind::Uint8Array> sig(runtime, sig_len);
73
+
74
+ EVPKeyCtxPointer pkctx(EVP_PKEY_CTX_new(pkey.get(), nullptr));
75
+ if (pkctx && EVP_PKEY_sign_init(pkctx.get()) &&
76
+ ApplyRSAOptions(pkey, pkctx.get(), padding, pss_salt_len) &&
77
+ EVP_PKEY_CTX_set_signature_md(pkctx.get(), EVP_MD_CTX_md(mdctx.get())) &&
78
+ EVP_PKEY_sign(
79
+ pkctx.get(),
80
+ static_cast<unsigned char*>(sig.getBuffer(runtime).data(runtime)),
81
+ &sig_len, m, m_len)) {
82
+ CHECK_LE(sig_len, sig.size(runtime));
83
+
84
+ // do this bits need to be trimmed? I think so
85
+ // if (sig_len == 0)
86
+ // sig = ArrayBuffer::NewBackingStore(env->isolate(), 0);
87
+ // else
88
+ // sig = BackingStore::Reallocate(env->isolate(), std::move(sig),
89
+ // sig_len);
90
+ return sig;
91
+ }
92
+
93
+ return {};
94
+ }
95
+
96
+ // int GetDefaultSignPadding(const ManagedEVPPKey& m_pkey) {
97
+ // return EVP_PKEY_id(m_pkey.get()) == EVP_PKEY_RSA_PSS ?
98
+ // RSA_PKCS1_PSS_PADDING : RSA_PKCS1_PADDING;
99
+ // }
100
+ //
101
+ unsigned int GetBytesOfRS(const ManagedEVPPKey& pkey) {
102
+ int bits, base_id = EVP_PKEY_base_id(pkey.get());
103
+
104
+ if (base_id == EVP_PKEY_DSA) {
105
+ const DSA* dsa_key = EVP_PKEY_get0_DSA(pkey.get());
106
+ // Both r and s are computed mod q, so their width is limited by that of
107
+ bits = BN_num_bits(DSA_get0_q(dsa_key));
108
+ } else if (base_id == EVP_PKEY_EC) {
109
+ const EC_KEY* ec_key = EVP_PKEY_get0_EC_KEY(pkey.get());
110
+ const EC_GROUP* ec_group = EC_KEY_get0_group(ec_key);
111
+ bits = EC_GROUP_order_bits(ec_group);
112
+ } else {
113
+ return kNoDsaSignature;
114
+ }
115
+
116
+ return (bits + 7) / 8;
117
+ }
118
+ //
119
+ // bool ExtractP1363(
120
+ // const unsigned char* sig_data,
121
+ // unsigned char* out,
122
+ // size_t len,
123
+ // size_t n) {
124
+ // ECDSASigPointer asn1_sig(d2i_ECDSA_SIG(nullptr,
125
+ // &sig_data, len)); if (!asn1_sig)
126
+ // return false;
127
+ //
128
+ // const BIGNUM* pr = ECDSA_SIG_get0_r(asn1_sig.get());
129
+ // const BIGNUM* ps = ECDSA_SIG_get0_s(asn1_sig.get());
130
+ //
131
+ // return BN_bn2binpad(pr, out, n) > 0 && BN_bn2binpad(ps,
132
+ // out + n, n) > 0;
133
+ // }
134
+ //
135
+ // // Returns the maximum size of each of the integers (r, s) of the DSA
136
+ // signature. std::unique_ptr<BackingStore>
137
+ // ConvertSignatureToP1363(Environment* env,
138
+ // const ManagedEVPPKey&
139
+ // pkey,
140
+ // std::unique_ptr<BackingStore>&&
141
+ // signature) {
142
+ // unsigned int n = GetBytesOfRS(pkey);
143
+ // if (n == kNoDsaSignature)
144
+ // return std::move(signature);
145
+ //
146
+ // std::unique_ptr<BackingStore> buf;
147
+ // {
148
+ // NoArrayBufferZeroFillScope no_zero_fill_scope(env->isolate_data());
149
+ // buf = ArrayBuffer::NewBackingStore(env->isolate(), 2 * n);
150
+ // }
151
+ // if (!ExtractP1363(static_cast<unsigned char*>(signature->Data()),
152
+ // static_cast<unsigned char*>(buf->Data()),
153
+ // signature->ByteLength(), n))
154
+ // return std::move(signature);
155
+ //
156
+ // return buf;
157
+ // }
158
+ //
159
+ // // Returns the maximum size of each of the integers (r, s) of the DSA
160
+ // signature. ByteSource ConvertSignatureToP1363(
161
+ // Environment* env,
162
+ // const ManagedEVPPKey& pkey,
163
+ // const ByteSource& signature) {
164
+ // unsigned int n = GetBytesOfRS(pkey);
165
+ // if (n == kNoDsaSignature)
166
+ // return ByteSource();
167
+ //
168
+ // const unsigned char* sig_data =
169
+ // signature.data<unsigned char>();
170
+ //
171
+ // ByteSource::Builder out(n * 2);
172
+ // memset(out.data<void>(), 0, n * 2);
173
+ //
174
+ // if (!ExtractP1363(sig_data,
175
+ // out.data<unsigned char>(),
176
+ // signature.size(), n))
177
+ // return ByteSource();
178
+ //
179
+ // return std::move(out).release();
180
+ // }
181
+ //
182
+ ByteSource ConvertSignatureToDER(const ManagedEVPPKey& pkey, ByteSource&& out) {
183
+ unsigned int n = GetBytesOfRS(pkey);
184
+ if (n == kNoDsaSignature) return std::move(out);
185
+
186
+ const unsigned char* sig_data = out.data<unsigned char>();
187
+
188
+ if (out.size() != 2 * n) return ByteSource();
189
+
190
+ ECDSASigPointer asn1_sig(ECDSA_SIG_new());
191
+ CHECK(asn1_sig);
192
+ BIGNUM* r = BN_new();
193
+ CHECK_NOT_NULL(r);
194
+ BIGNUM* s = BN_new();
195
+ CHECK_NOT_NULL(s);
196
+ CHECK_EQ(r, BN_bin2bn(sig_data, n, r));
197
+ CHECK_EQ(s, BN_bin2bn(sig_data + n, n, s));
198
+ CHECK_EQ(1, ECDSA_SIG_set0(asn1_sig.get(), r, s));
199
+
200
+ unsigned char* data = nullptr;
201
+ int len = i2d_ECDSA_SIG(asn1_sig.get(), &data);
202
+
203
+ if (len <= 0) return ByteSource();
204
+
205
+ CHECK_NOT_NULL(data);
206
+
207
+ return ByteSource::Allocated(reinterpret_cast<char*>(data), len);
208
+ }
209
+
210
+ // void CheckThrow(Environment* env, SignBase::Error error) {
211
+ // HandleScope scope(env->isolate());
212
+ //
213
+ // switch (error) {
214
+ // case SignBase::Error::kSignUnknownDigest:
215
+ // return THROW_ERR_CRYPTO_INVALID_DIGEST(env);
216
+ //
217
+ // case SignBase::Error::kSignNotInitialised:
218
+ // return THROW_ERR_CRYPTO_INVALID_STATE(env, "Not initialised");
219
+ //
220
+ // case SignBase::Error::kSignMalformedSignature:
221
+ // return THROW_ERR_CRYPTO_OPERATION_FAILED(env, "Malformed signature");
222
+ //
223
+ // case SignBase::Error::kSignInit:
224
+ // case SignBase::Error::kSignUpdate:
225
+ // case SignBase::Error::kSignPrivateKey:
226
+ // case SignBase::Error::kSignPublicKey:
227
+ // {
228
+ // unsigned long err = ERR_get_error(); // NOLINT(runtime/int)
229
+ // if (err)
230
+ // return ThrowCryptoError(env, err);
231
+ // switch (error) {
232
+ // case SignBase::Error::kSignInit:
233
+ // return THROW_ERR_CRYPTO_OPERATION_FAILED(env,
234
+ // "EVP_SignInit_ex
235
+ // failed");
236
+ // case SignBase::Error::kSignUpdate:
237
+ // return THROW_ERR_CRYPTO_OPERATION_FAILED(env,
238
+ // "EVP_SignUpdate failed");
239
+ // case SignBase::Error::kSignPrivateKey:
240
+ // return THROW_ERR_CRYPTO_OPERATION_FAILED(env,
241
+ // "PEM_read_bio_PrivateKey
242
+ // failed");
243
+ // case SignBase::Error::kSignPublicKey:
244
+ // return THROW_ERR_CRYPTO_OPERATION_FAILED(env,
245
+ // "PEM_read_bio_PUBKEY
246
+ // failed");
247
+ // default:
248
+ // ABORT();
249
+ // }
250
+ // }
251
+ //
252
+ // case SignBase::Error::kSignOk:
253
+ // return;
254
+ // }
255
+ // }
256
+ //
257
+ // bool IsOneShot(const ManagedEVPPKey& key) {
258
+ // switch (EVP_PKEY_id(key.get())) {
259
+ // case EVP_PKEY_ED25519:
260
+ // case EVP_PKEY_ED448:
261
+ // return true;
262
+ // default:
263
+ // return false;
264
+ // }
265
+ // }
266
+ //
267
+ // bool UseP1363Encoding(const ManagedEVPPKey& key,
268
+ // const DSASigEnc& dsa_encoding) {
269
+ // switch (EVP_PKEY_id(key.get())) {
270
+ // case EVP_PKEY_EC:
271
+ // case EVP_PKEY_DSA:
272
+ // return dsa_encoding == kSigEncP1363;
273
+ // default:
274
+ // return false;
275
+ // }
276
+ // }
277
+
278
+ SignBase::SignResult SignBase::SignFinal(jsi::Runtime& runtime,
279
+ const ManagedEVPPKey& pkey,
280
+ int padding,
281
+ std::optional<int>& salt_len,
282
+ DSASigEnc dsa_sig_enc) {
283
+ if (!mdctx_) return SignResult(kSignNotInitialised);
284
+
285
+ EVPMDPointer mdctx = std::move(mdctx_);
286
+
287
+ if (!ValidateDSAParameters(pkey.get())) return SignResult(kSignPrivateKey);
288
+
289
+ std::optional<jsi::Value> buffer =
290
+ Node_SignFinal(runtime, std::move(mdctx), pkey, padding, salt_len);
291
+ Error error = buffer.has_value() ? kSignOk : kSignPrivateKey;
292
+ // TODO(osp) enable this
293
+ // if (error == kSignOk && dsa_sig_enc == kSigEncP1363) {
294
+ // buffer = ConvertSignatureToP1363(env(), pkey, std::move(buffer));
295
+ // CHECK_NOT_NULL(buffer->Data());
296
+ // }
297
+ return SignResult(error, std::move(buffer.value()));
298
+ }
299
+
300
+ SignBase::Error SignBase::VerifyFinal(const ManagedEVPPKey& pkey,
301
+ const ByteSource& sig, int padding,
302
+ std::optional<int>& saltlen,
303
+ bool* verify_result) {
304
+ if (!mdctx_) return kSignNotInitialised;
305
+
306
+ unsigned char m[EVP_MAX_MD_SIZE];
307
+ unsigned int m_len;
308
+ *verify_result = false;
309
+ EVPMDPointer mdctx = std::move(mdctx_);
310
+
311
+ if (!EVP_DigestFinal_ex(mdctx.get(), m, &m_len)) return kSignPublicKey;
312
+
313
+ EVPKeyCtxPointer pkctx(EVP_PKEY_CTX_new(pkey.get(), nullptr));
314
+ if (pkctx && EVP_PKEY_verify_init(pkctx.get()) > 0 &&
315
+ ApplyRSAOptions(pkey, pkctx.get(), padding, saltlen) &&
316
+ EVP_PKEY_CTX_set_signature_md(pkctx.get(), EVP_MD_CTX_md(mdctx.get())) >
317
+ 0) {
318
+ const unsigned char* s = sig.data<unsigned char>();
319
+ const int r = EVP_PKEY_verify(pkctx.get(), s, sig.size(), m, m_len);
320
+ *verify_result = r == 1;
321
+ }
322
+
323
+ return kSignOk;
324
+ }
325
+
326
+ SignBase::SignBase(std::shared_ptr<react::CallInvoker> jsCallInvoker,
327
+ std::shared_ptr<DispatchQueue::dispatch_queue> workerQueue)
328
+ : MGLSmartHostObject(jsCallInvoker, workerQueue) {}
329
+
330
+ MGLSignHostObject::MGLSignHostObject(
331
+ std::shared_ptr<react::CallInvoker> jsCallInvoker,
332
+ std::shared_ptr<DispatchQueue::dispatch_queue> workerQueue)
333
+ : SignBase(jsCallInvoker, workerQueue) {
334
+ InstallMethods(kModeSign);
335
+ }
336
+
337
+ MGLVerifyHostObject::MGLVerifyHostObject(
338
+ std::shared_ptr<react::CallInvoker> jsCallInvoker,
339
+ std::shared_ptr<DispatchQueue::dispatch_queue> workerQueue)
340
+ : SignBase(jsCallInvoker, workerQueue) {
341
+ InstallMethods(kModeVerify);
342
+ }
343
+
344
+ int GetDefaultSignPadding(const ManagedEVPPKey& m_pkey) {
345
+ return EVP_PKEY_id(m_pkey.get()) == EVP_PKEY_RSA_PSS ? RSA_PKCS1_PSS_PADDING
346
+ : RSA_PKCS1_PADDING;
347
+ }
348
+
349
+ void SignBase::InstallMethods(mode mode) {
350
+ this->fields.push_back(buildPair(
351
+ "init", JSIF([=]) {
352
+ if (count != 1 || !arguments[0].isString()) {
353
+ jsi::detail::throwJSError(runtime, "init requires algorithm param");
354
+ return {};
355
+ }
356
+
357
+ std::string sign_type = arguments[0].asString(runtime).utf8(runtime);
358
+ CHECK_NULL(mdctx_);
359
+
360
+ // Historically, "dss1" and "DSS1" were DSA aliases for SHA-1
361
+ // exposed through the public API.
362
+ if (sign_type.compare("dss1") == 0 || sign_type.compare("DSS1") == 0) {
363
+ sign_type = "SHA1";
364
+ }
365
+
366
+ const EVP_MD* md = EVP_get_digestbyname(sign_type.c_str());
367
+ if (md == nullptr) return jsi::Value((int)kSignUnknownDigest);
368
+
369
+ mdctx_.reset(EVP_MD_CTX_new());
370
+ if (!mdctx_ || !EVP_DigestInit_ex(mdctx_.get(), md, nullptr)) {
371
+ mdctx_.reset();
372
+ return jsi::Value((int)kSignInit);
373
+ }
374
+
375
+ return jsi::Value((int)kSignOk);
376
+ }));
377
+
378
+ this->fields.push_back(buildPair(
379
+ "update", JSIF([=]) {
380
+ if (count != 1) {
381
+ jsi::detail::throwJSError(runtime, "update requires 2 arguments");
382
+ }
383
+
384
+ if (!arguments[0].isObject() ||
385
+ !arguments[0].asObject(runtime).isArrayBuffer(runtime)) {
386
+ jsi::detail::throwJSError(
387
+ runtime, "First argument (data) needs to be an array buffer");
388
+ }
389
+
390
+ auto data = arguments[0].asObject(runtime).getArrayBuffer(runtime);
391
+
392
+ if (!CheckSizeInt32(runtime, data)) {
393
+ jsi::detail::throwJSError(runtime, "data is too large");
394
+ }
395
+
396
+ if (mdctx_ == nullptr) return (int)kSignNotInitialised;
397
+ if (!EVP_DigestUpdate(mdctx_.get(), data.data(runtime),
398
+ data.size(runtime)))
399
+ return (int)kSignUpdate;
400
+ return (int)kSignOk;
401
+ }));
402
+
403
+ if (mode == kModeSign) {
404
+ this->fields.push_back(buildPair(
405
+ "sign", JSIF([=]) {
406
+ unsigned int offset = 0;
407
+ ManagedEVPPKey key = ManagedEVPPKey::GetPrivateKeyFromJs(
408
+ runtime, arguments, &offset, true);
409
+ if (!key) {
410
+ return {};
411
+ }
412
+
413
+ int padding = GetDefaultSignPadding(key);
414
+ if (!arguments[offset].isUndefined()) {
415
+ // TODO(osp) need to add a check for int32
416
+ CHECK(arguments[offset].isNumber());
417
+ padding = static_cast<int>(arguments[offset].asNumber());
418
+ }
419
+
420
+ std::optional<int> salt_len;
421
+ if (!arguments[offset + 1].isUndefined()) {
422
+ // TODO(osp) add check for int32
423
+ CHECK(arguments[offset + 1].isNumber());
424
+ salt_len = static_cast<int>(arguments[offset + 1].asNumber());
425
+ }
426
+
427
+ // TODO(osp) add check for int32
428
+ CHECK(arguments[offset + 2].isNumber());
429
+ DSASigEnc dsa_sig_enc = static_cast<DSASigEnc>(
430
+ static_cast<int>(arguments[offset + 2].asNumber()));
431
+
432
+ SignResult ret =
433
+ this->SignFinal(runtime, key, padding, salt_len, dsa_sig_enc);
434
+
435
+ if (ret.error != kSignOk) {
436
+ jsi::detail::throwJSError(runtime, "Error signing");
437
+ throw new jsi::JSError(runtime, "Error signing");
438
+ }
439
+
440
+ return std::move(ret.signature.value());
441
+ }));
442
+ } else {
443
+ this->fields.push_back(buildPair(
444
+ "verify", JSIF([=]) {
445
+ // Verify* verify;
446
+ // ASSIGN_OR_RETURN_UNWRAP(&verify, args.Holder());
447
+
448
+ unsigned int offset = 0;
449
+ ManagedEVPPKey pkey = ManagedEVPPKey::GetPublicOrPrivateKeyFromJs(
450
+ runtime, arguments, &offset);
451
+ if (!pkey) {
452
+ return {};
453
+ }
454
+
455
+ jsi::ArrayBuffer hbuf =
456
+ arguments[offset].asObject(runtime).getArrayBuffer(runtime);
457
+ if (!CheckSizeInt32(runtime, hbuf)) {
458
+ jsi::detail::throwJSError(runtime, "buffer is too big");
459
+ throw jsi::JSError(runtime, "buffer is too big");
460
+ }
461
+
462
+ int padding = GetDefaultSignPadding(pkey);
463
+ if (!arguments[offset + 1].isUndefined()) {
464
+ CHECK(arguments[offset + 1].isNumber());
465
+ padding = static_cast<int>(arguments[offset + 1].asNumber());
466
+ }
467
+
468
+ std::optional<int> salt_len;
469
+ if (!arguments[offset + 2].isUndefined()) {
470
+ // TODO(osp) add check for int32
471
+ CHECK(arguments[offset + 2].isNumber());
472
+ salt_len = static_cast<int>(arguments[offset + 2].asNumber());
473
+ }
474
+
475
+ // TODO(osp) add check for int32
476
+ CHECK(arguments[offset + 3].isNumber());
477
+ DSASigEnc dsa_sig_enc = static_cast<DSASigEnc>(
478
+ static_cast<int>(arguments[offset + 3].asNumber()));
479
+
480
+ ByteSource signature = ArrayBufferToByteSource(runtime, hbuf);
481
+ if (dsa_sig_enc == kSigEncP1363) {
482
+ signature = ConvertSignatureToDER(
483
+ pkey, ArrayBufferToByteSource(runtime, hbuf));
484
+ if (signature.data() == nullptr) {
485
+ jsi::detail::throwJSError(runtime, "kSignMalformedSignature");
486
+ }
487
+ // return crypto::CheckThrow(env,
488
+ // Error::kSignMalformedSignature);
489
+ }
490
+
491
+ bool verify_result;
492
+ Error err = this->VerifyFinal(pkey, signature, padding, salt_len,
493
+ &verify_result);
494
+ if (err != kSignOk) {
495
+ jsi::detail::throwJSError(runtime, "Error on verify");
496
+ }
497
+
498
+ return verify_result;
499
+ }));
500
+ }
501
+ }
502
+
503
+ // Verify::Verify(Environment* env, Local<Object> wrap)
504
+ //: SignBase(env, wrap) {
505
+ // MakeWeak();
506
+ //}
507
+ //
508
+ // void Verify::Initialize(Environment* env, Local<Object> target) {
509
+ // Local<FunctionTemplate> t = env->NewFunctionTemplate(New);
510
+ //
511
+ // t->InstanceTemplate()->SetInternalFieldCount(
512
+ // SignBase::kInternalFieldCount);
513
+ // t->Inherit(BaseObject::GetConstructorTemplate(env));
514
+ //
515
+ // env->SetProtoMethod(t, "init", VerifyInit);
516
+ // env->SetProtoMethod(t, "update", VerifyUpdate);
517
+ // env->SetProtoMethod(t, "verify", VerifyFinal);
518
+ //
519
+ // env->SetConstructorFunction(target, "Verify", t);
520
+ //}
521
+ //
522
+ // void Verify::RegisterExternalReferences(ExternalReferenceRegistry* registry)
523
+ // {
524
+ // registry->Register(New);
525
+ // registry->Register(VerifyInit);
526
+ // registry->Register(VerifyUpdate);
527
+ // registry->Register(VerifyFinal);
528
+ //}
529
+ //
530
+ // void Verify::New(const FunctionCallbackInfo<Value>& args) {
531
+ // Environment* env = Environment::GetCurrent(args);
532
+ // new Verify(env, args.This());
533
+ //}
534
+ //
535
+ // void Verify::VerifyInit(const FunctionCallbackInfo<Value>& args) {
536
+ // Environment* env = Environment::GetCurrent(args);
537
+ // Verify* verify;
538
+ // ASSIGN_OR_RETURN_UNWRAP(&verify, args.Holder());
539
+ //
540
+ // const node::Utf8Value verify_type(args.GetIsolate(), args[0]);
541
+ // crypto::CheckThrow(env, verify->Init(*verify_type));
542
+ //}
543
+ //
544
+ // void Verify::VerifyUpdate(const FunctionCallbackInfo<Value>& args) {
545
+ // Decode<Verify>(args, [](Verify* verify,
546
+ // const FunctionCallbackInfo<Value>& args,
547
+ // const char* data, size_t size) {
548
+ // Environment* env = Environment::GetCurrent(args);
549
+ // if (UNLIKELY(size > INT_MAX))
550
+ // return THROW_ERR_OUT_OF_RANGE(env, "data is too long");
551
+ // Error err = verify->Update(data, size);
552
+ // crypto::CheckThrow(verify->env(), err);
553
+ // });
554
+ //}
555
+ //
556
+ // SignBase::Error Verify::VerifyFinal(const ManagedEVPPKey& pkey,
557
+ // const ByteSource& sig,
558
+ // int padding,
559
+ // const Maybe<int>& saltlen,
560
+ // bool* verify_result) {
561
+ // if (!mdctx_)
562
+ // return kSignNotInitialised;
563
+ //
564
+ // unsigned char m[EVP_MAX_MD_SIZE];
565
+ // unsigned int m_len;
566
+ // *verify_result = false;
567
+ // EVPMDPointer mdctx = std::move(mdctx_);
568
+ //
569
+ // if (!EVP_DigestFinal_ex(mdctx.get(), m, &m_len))
570
+ // return kSignPublicKey;
571
+ //
572
+ // EVPKeyCtxPointer pkctx(EVP_PKEY_CTX_new(pkey.get(), nullptr));
573
+ // if (pkctx &&
574
+ // EVP_PKEY_verify_init(pkctx.get()) > 0 &&
575
+ // ApplyRSAOptions(pkey, pkctx.get(), padding, saltlen) &&
576
+ // EVP_PKEY_CTX_set_signature_md(pkctx.get(),
577
+ // EVP_MD_CTX_md(mdctx.get())) > 0) {
578
+ // const unsigned char* s = sig.data<unsigned char>();
579
+ // const int r = EVP_PKEY_verify(pkctx.get(), s, sig.size(), m, m_len);
580
+ // *verify_result = r == 1;
581
+ // }
582
+ //
583
+ // return kSignOk;
584
+ //}
585
+ //
586
+ // void Verify::VerifyFinal(const FunctionCallbackInfo<Value>& args) {
587
+ // Environment* env = Environment::GetCurrent(args);
588
+ // ClearErrorOnReturn clear_error_on_return;
589
+ //
590
+ // Verify* verify;
591
+ // ASSIGN_OR_RETURN_UNWRAP(&verify, args.Holder());
592
+ //
593
+ // unsigned int offset = 0;
594
+ // ManagedEVPPKey pkey =
595
+ // ManagedEVPPKey::GetPublicOrPrivateKeyFromJs(args, &offset);
596
+ // if (!pkey)
597
+ // return;
598
+ //
599
+ // ArrayBufferOrViewContents<char> hbuf(args[offset]);
600
+ // if (UNLIKELY(!hbuf.CheckSizeInt32()))
601
+ // return THROW_ERR_OUT_OF_RANGE(env, "buffer is too big");
602
+ //
603
+ // int padding = GetDefaultSignPadding(pkey);
604
+ // if (!args[offset + 1]->IsUndefined()) {
605
+ // CHECK(args[offset + 1]->IsInt32());
606
+ // padding = args[offset + 1].As<Int32>()->Value();
607
+ // }
608
+ //
609
+ // Maybe<int> salt_len = Nothing<int>();
610
+ // if (!args[offset + 2]->IsUndefined()) {
611
+ // CHECK(args[offset + 2]->IsInt32());
612
+ // salt_len = Just<int>(args[offset + 2].As<Int32>()->Value());
613
+ // }
614
+ //
615
+ // CHECK(args[offset + 3]->IsInt32());
616
+ // DSASigEnc dsa_sig_enc =
617
+ // static_cast<DSASigEnc>(args[offset + 3].As<Int32>()->Value());
618
+ //
619
+ // ByteSource signature = hbuf.ToByteSource();
620
+ // if (dsa_sig_enc == kSigEncP1363) {
621
+ // signature = ConvertSignatureToDER(pkey, hbuf.ToByteSource());
622
+ // if (signature.data() == nullptr)
623
+ // return crypto::CheckThrow(env, Error::kSignMalformedSignature);
624
+ // }
625
+ //
626
+ // bool verify_result;
627
+ // Error err = verify->VerifyFinal(pkey, signature, padding,
628
+ // salt_len, &verify_result);
629
+ // if (err != kSignOk)
630
+ // return crypto::CheckThrow(env, err);
631
+ // args.GetReturnValue().Set(verify_result);
632
+ //}
633
+ //
634
+ // SignConfiguration::SignConfiguration(SignConfiguration&& other) noexcept
635
+ //: job_mode(other.job_mode),
636
+ // mode(other.mode),
637
+ // key(std::move(other.key)),
638
+ // data(std::move(other.data)),
639
+ // signature(std::move(other.signature)),
640
+ // digest(other.digest),
641
+ // flags(other.flags),
642
+ // padding(other.padding),
643
+ // salt_length(other.salt_length),
644
+ // dsa_encoding(other.dsa_encoding) {}
645
+ //
646
+ // SignConfiguration& SignConfiguration::operator=(
647
+ // SignConfiguration&& other)
648
+ // noexcept {
649
+ // if (&other == this) return
650
+ // *this;
651
+ // this->~SignConfiguration();
652
+ // return *new (this)
653
+ // SignConfiguration(std::move(other));
654
+ // }
655
+ //
656
+ // void SignConfiguration::MemoryInfo(MemoryTracker* tracker) const {
657
+ // tracker->TrackField("key", key);
658
+ // if (job_mode == kCryptoJobAsync) {
659
+ // tracker->TrackFieldWithSize("data", data.size());
660
+ // tracker->TrackFieldWithSize("signature", signature.size());
661
+ // }
662
+ // }
663
+ //
664
+ // Maybe<bool> SignTraits::AdditionalConfig(
665
+ // CryptoJobMode mode,
666
+ // const FunctionCallbackInfo<Value>&
667
+ // args, unsigned int offset,
668
+ // SignConfiguration* params) {
669
+ // ClearErrorOnReturn clear_error_on_return;
670
+ // Environment* env = Environment::GetCurrent(args);
671
+ //
672
+ // params->job_mode = mode;
673
+ //
674
+ // CHECK(args[offset]->IsUint32()); // Sign Mode
675
+ //
676
+ // params->mode =
677
+ // static_cast<SignConfiguration::Mode>(args[offset].As<Uint32>()->Value());
678
+ //
679
+ // ManagedEVPPKey key;
680
+ // unsigned int keyParamOffset = offset + 1;
681
+ // if (params->mode == SignConfiguration::kVerify) {
682
+ // key = ManagedEVPPKey::GetPublicOrPrivateKeyFromJs(args, &keyParamOffset);
683
+ // } else {
684
+ // key = ManagedEVPPKey::GetPrivateKeyFromJs(args, &keyParamOffset, true);
685
+ // }
686
+ // if (!key)
687
+ // return Nothing<bool>();
688
+ // params->key = key;
689
+ //
690
+ // ArrayBufferOrViewContents<char> data(args[offset + 5]);
691
+ // if (UNLIKELY(!data.CheckSizeInt32())) {
692
+ // THROW_ERR_OUT_OF_RANGE(env, "data is too big");
693
+ // return Nothing<bool>();
694
+ // }
695
+ // params->data = mode == kCryptoJobAsync
696
+ // ? data.ToCopy()
697
+ // : data.ToByteSource();
698
+ //
699
+ // if (args[offset + 6]->IsString()) {
700
+ // Utf8Value digest(env->isolate(), args[offset + 6]);
701
+ // params->digest = EVP_get_digestbyname(*digest);
702
+ // if (params->digest == nullptr) {
703
+ // THROW_ERR_CRYPTO_INVALID_DIGEST(env);
704
+ // return Nothing<bool>();
705
+ // }
706
+ // }
707
+ //
708
+ // if (args[offset + 7]->IsInt32()) { // Salt length
709
+ // params->flags |= SignConfiguration::kHasSaltLength;
710
+ // params->salt_length = args[offset + 7].As<Int32>()->Value();
711
+ // }
712
+ // if (args[offset + 8]->IsUint32()) { // Padding
713
+ // params->flags |= SignConfiguration::kHasPadding;
714
+ // params->padding = args[offset + 8].As<Uint32>()->Value();
715
+ // }
716
+ //
717
+ // if (args[offset + 9]->IsUint32()) { // DSA Encoding
718
+ // params->dsa_encoding =
719
+ // static_cast<DSASigEnc>(args[offset + 9].As<Uint32>()->Value());
720
+ // if (params->dsa_encoding != kSigEncDER &&
721
+ // params->dsa_encoding != kSigEncP1363) {
722
+ // THROW_ERR_OUT_OF_RANGE(env, "invalid signature encoding");
723
+ // return Nothing<bool>();
724
+ // }
725
+ // }
726
+ //
727
+ // if (params->mode == SignConfiguration::kVerify) {
728
+ // ArrayBufferOrViewContents<char> signature(args[offset + 10]);
729
+ // if (UNLIKELY(!signature.CheckSizeInt32())) {
730
+ // THROW_ERR_OUT_OF_RANGE(env, "signature is too big");
731
+ // return Nothing<bool>();
732
+ // }
733
+ // // If this is an EC key (assuming ECDSA) we need to convert the
734
+ // // the signature from WebCrypto format into DER format...
735
+ // ManagedEVPPKey m_pkey = params->key;
736
+ // Mutex::ScopedLock lock(*m_pkey.mutex());
737
+ // if (UseP1363Encoding(m_pkey, params->dsa_encoding)) {
738
+ // params->signature =
739
+ // ConvertSignatureToDER(m_pkey, signature.ToByteSource());
740
+ // } else {
741
+ // params->signature = mode == kCryptoJobAsync
742
+ // ? signature.ToCopy()
743
+ // : signature.ToByteSource();
744
+ // }
745
+ // }
746
+ //
747
+ // return Just(true);
748
+ // }
749
+ //
750
+ // bool SignTraits::DeriveBits(
751
+ // Environment* env,
752
+ // const SignConfiguration& params,
753
+ // ByteSource* out) {
754
+ // ClearErrorOnReturn clear_error_on_return;
755
+ // EVPMDPointer context(EVP_MD_CTX_new());
756
+ // EVP_PKEY_CTX* ctx = nullptr;
757
+ //
758
+ // switch (params.mode) {
759
+ // case SignConfiguration::kSign:
760
+ // if (!EVP_DigestSignInit(
761
+ // context.get(),
762
+ // &ctx,
763
+ // params.digest,
764
+ // nullptr,
765
+ // params.key.get())) {
766
+ // crypto::CheckThrow(env,
767
+ // SignBase::Error::kSignInit); return false;
768
+ // }
769
+ // break;
770
+ // case SignConfiguration::kVerify:
771
+ // if (!EVP_DigestVerifyInit(
772
+ // context.get(),
773
+ // &ctx,
774
+ // params.digest,
775
+ // nullptr,
776
+ // params.key.get())) {
777
+ // crypto::CheckThrow(env,
778
+ // SignBase::Error::kSignInit); return false;
779
+ // }
780
+ // break;
781
+ // }
782
+ //
783
+ // int padding = params.flags & SignConfiguration::kHasPadding
784
+ // ? params.padding
785
+ // : GetDefaultSignPadding(params.key);
786
+ //
787
+ // Maybe<int> salt_length = params.flags & SignConfiguration::kHasSaltLength
788
+ // ? Just<int>(params.salt_length) : Nothing<int>();
789
+ //
790
+ // if (!ApplyRSAOptions(
791
+ // params.key,
792
+ // ctx,
793
+ // padding,
794
+ // salt_length)) {
795
+ // crypto::CheckThrow(env,
796
+ // SignBase::Error::kSignPrivateKey); return false;
797
+ // }
798
+ //
799
+ // switch (params.mode) {
800
+ // case SignConfiguration::kSign: {
801
+ // if (IsOneShot(params.key)) {
802
+ // size_t len;
803
+ // if (!EVP_DigestSign(
804
+ // context.get(),
805
+ // nullptr,
806
+ // &len,
807
+ // params.data.data<unsigned char>(),
808
+ // params.data.size())) {
809
+ // crypto::CheckThrow(env,
810
+ // SignBase::Error::kSignPrivateKey); return
811
+ // false;
812
+ // }
813
+ // ByteSource::Builder buf(len);
814
+ // if (!EVP_DigestSign(context.get(),
815
+ // buf.data<unsigned char>(),
816
+ // &len,
817
+ // params.data.data<unsigned char>(),
818
+ // params.data.size())) {
819
+ // crypto::CheckThrow(env, SignBase::Error::kSignPrivateKey);
820
+ // return false;
821
+ // }
822
+ // *out = std::move(buf).release(len);
823
+ // } else {
824
+ // size_t len;
825
+ // if (!EVP_DigestSignUpdate(
826
+ // context.get(),
827
+ // params.data.data<unsigned char>(),
828
+ // params.data.size()) ||
829
+ // !EVP_DigestSignFinal(context.get(), nullptr, &len)) {
830
+ // crypto::CheckThrow(env, SignBase::Error::kSignPrivateKey);
831
+ // return false;
832
+ // }
833
+ // ByteSource::Builder buf(len);
834
+ // if (!EVP_DigestSignFinal(
835
+ // context.get(), buf.data<unsigned char>(),
836
+ // &len)) {
837
+ // crypto::CheckThrow(env,
838
+ // SignBase::Error::kSignPrivateKey); return
839
+ // false;
840
+ // }
841
+ //
842
+ // if (UseP1363Encoding(params.key, params.dsa_encoding)) {
843
+ // *out = ConvertSignatureToP1363(
844
+ // env, params.key,
845
+ // std::move(buf).release());
846
+ // } else {
847
+ // *out = std::move(buf).release(len);
848
+ // }
849
+ // }
850
+ // break;
851
+ // }
852
+ // case SignConfiguration::kVerify: {
853
+ // ByteSource::Builder buf(1);
854
+ // buf.data<char>()[0] = 0;
855
+ // if (EVP_DigestVerify(
856
+ // context.get(),
857
+ // params.signature.data<unsigned char>(),
858
+ // params.signature.size(),
859
+ // params.data.data<unsigned char>(),
860
+ // params.data.size()) == 1) {
861
+ // buf.data<char>()[0] = 1;
862
+ // }
863
+ // *out = std::move(buf).release();
864
+ // }
865
+ // }
866
+ //
867
+ // return true;
868
+ // }
869
+ //
870
+ // Maybe<bool> SignTraits::EncodeOutput(
871
+ // Environment* env,
872
+ // const SignConfiguration& params,
873
+ // ByteSource* out,
874
+ // Local<Value>* result) {
875
+ // switch (params.mode) {
876
+ // case SignConfiguration::kSign:
877
+ // *result = out->ToArrayBuffer(env);
878
+ // break;
879
+ // case SignConfiguration::kVerify:
880
+ // *result = out->data<char>()[0] == 1 ? v8::True(env->isolate())
881
+ // : v8::False(env->isolate());
882
+ // break;
883
+ // default:
884
+ // UNREACHABLE();
885
+ // }
886
+ // return Just(!result->IsEmpty());
887
+ // }
888
+
889
+ } // namespace margelo