react-native-quick-crypto 1.0.0-beta.21 → 1.0.0-beta.22

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/QuickCrypto.podspec +11 -1
  2. package/android/CMakeLists.txt +2 -0
  3. package/cpp/cipher/GCMCipher.cpp +68 -0
  4. package/cpp/cipher/GCMCipher.hpp +14 -0
  5. package/cpp/cipher/HybridCipherFactory.hpp +8 -0
  6. package/cpp/cipher/HybridRsaCipher.cpp +229 -0
  7. package/cpp/cipher/HybridRsaCipher.hpp +23 -0
  8. package/cpp/keys/HybridKeyObjectHandle.cpp +508 -9
  9. package/cpp/keys/HybridKeyObjectHandle.hpp +10 -1
  10. package/cpp/utils/base64.h +309 -0
  11. package/lib/commonjs/ec.js +85 -17
  12. package/lib/commonjs/ec.js.map +1 -1
  13. package/lib/commonjs/specs/rsaCipher.nitro.js +6 -0
  14. package/lib/commonjs/specs/rsaCipher.nitro.js.map +1 -0
  15. package/lib/commonjs/subtle.js +420 -17
  16. package/lib/commonjs/subtle.js.map +1 -1
  17. package/lib/commonjs/utils/conversion.js +1 -1
  18. package/lib/commonjs/utils/conversion.js.map +1 -1
  19. package/lib/module/ec.js +86 -18
  20. package/lib/module/ec.js.map +1 -1
  21. package/lib/module/specs/rsaCipher.nitro.js +4 -0
  22. package/lib/module/specs/rsaCipher.nitro.js.map +1 -0
  23. package/lib/module/subtle.js +421 -18
  24. package/lib/module/subtle.js.map +1 -1
  25. package/lib/module/utils/conversion.js +1 -1
  26. package/lib/module/utils/conversion.js.map +1 -1
  27. package/lib/tsconfig.tsbuildinfo +1 -1
  28. package/lib/typescript/ec.d.ts.map +1 -1
  29. package/lib/typescript/specs/keyObjectHandle.nitro.d.ts +1 -0
  30. package/lib/typescript/specs/keyObjectHandle.nitro.d.ts.map +1 -1
  31. package/lib/typescript/specs/rsaCipher.nitro.d.ts +26 -0
  32. package/lib/typescript/specs/rsaCipher.nitro.d.ts.map +1 -0
  33. package/lib/typescript/subtle.d.ts.map +1 -1
  34. package/lib/typescript/utils/conversion.d.ts.map +1 -1
  35. package/lib/typescript/utils/types.d.ts +1 -1
  36. package/lib/typescript/utils/types.d.ts.map +1 -1
  37. package/nitrogen/generated/android/QuickCrypto+autolinking.cmake +1 -0
  38. package/nitrogen/generated/android/QuickCryptoOnLoad.cpp +10 -0
  39. package/nitrogen/generated/ios/QuickCryptoAutolinking.mm +10 -0
  40. package/nitrogen/generated/shared/c++/AsymmetricKeyType.hpp +104 -0
  41. package/nitrogen/generated/shared/c++/HybridKeyObjectHandleSpec.cpp +1 -0
  42. package/nitrogen/generated/shared/c++/HybridKeyObjectHandleSpec.hpp +5 -4
  43. package/nitrogen/generated/shared/c++/HybridRsaCipherSpec.cpp +22 -0
  44. package/nitrogen/generated/shared/c++/HybridRsaCipherSpec.hpp +70 -0
  45. package/package.json +1 -1
  46. package/src/ec.ts +122 -20
  47. package/src/specs/keyObjectHandle.nitro.ts +1 -0
  48. package/src/specs/rsaCipher.nitro.ts +35 -0
  49. package/src/subtle.ts +550 -45
  50. package/src/utils/conversion.ts +3 -1
  51. package/src/utils/types.ts +6 -6
  52. package/nitrogen/generated/shared/c++/CFRGKeyPairType.hpp +0 -84
@@ -145,6 +145,14 @@ Pod::Spec.new do |s|
145
145
  "CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES" => "YES"
146
146
  }
147
147
 
148
+ # Add cpp subdirectories to header search paths
149
+ cpp_headers = [
150
+ "\"$(PODS_TARGET_SRCROOT)/cpp/utils\"",
151
+ "\"$(PODS_TARGET_SRCROOT)/deps/ncrypto\"",
152
+ "\"$(PODS_TARGET_SRCROOT)/deps/blake3/c\"",
153
+ "\"$(PODS_TARGET_SRCROOT)/deps/fastpbkdf2\""
154
+ ]
155
+
148
156
  if sodium_enabled
149
157
  sodium_headers = [
150
158
  "\"$(PODS_TARGET_SRCROOT)/ios/libsodium-stable/src/libsodium/include\"",
@@ -153,8 +161,10 @@ Pod::Spec.new do |s|
153
161
  "\"$(PODS_ROOT)/../../packages/react-native-quick-crypto/ios/libsodium-stable/src/libsodium/include\"",
154
162
  "\"$(PODS_ROOT)/../../packages/react-native-quick-crypto/ios/libsodium-stable/src/libsodium/include/sodium\""
155
163
  ]
156
- xcconfig["HEADER_SEARCH_PATHS"] = sodium_headers.join(' ')
164
+ xcconfig["HEADER_SEARCH_PATHS"] = (cpp_headers + sodium_headers).join(' ')
157
165
  xcconfig["GCC_PREPROCESSOR_DEFINITIONS"] = "$(inherited) BLSALLOC_SODIUM=1"
166
+ else
167
+ xcconfig["HEADER_SEARCH_PATHS"] = cpp_headers.join(' ')
158
168
  end
159
169
 
160
170
  s.pod_target_xcconfig = xcconfig
@@ -27,7 +27,9 @@ add_library(
27
27
  src/main/cpp/cpp-adapter.cpp
28
28
  ../cpp/blake3/HybridBlake3.cpp
29
29
  ../cpp/cipher/CCMCipher.cpp
30
+ ../cpp/cipher/GCMCipher.cpp
30
31
  ../cpp/cipher/HybridCipher.cpp
32
+ ../cpp/cipher/HybridRsaCipher.cpp
31
33
  ../cpp/cipher/OCBCipher.cpp
32
34
  ../cpp/cipher/XSalsa20Cipher.cpp
33
35
  ../cpp/cipher/ChaCha20Cipher.cpp
@@ -0,0 +1,68 @@
1
+ #include "GCMCipher.hpp"
2
+ #include "Utils.hpp"
3
+ #include <openssl/err.h>
4
+ #include <openssl/evp.h>
5
+ #include <stdexcept>
6
+
7
+ namespace margelo::nitro::crypto {
8
+
9
+ void GCMCipher::init(const std::shared_ptr<ArrayBuffer> cipher_key, const std::shared_ptr<ArrayBuffer> iv) {
10
+ // Clean up any existing context
11
+ if (ctx) {
12
+ EVP_CIPHER_CTX_free(ctx);
13
+ ctx = nullptr;
14
+ }
15
+
16
+ // 1. Get cipher implementation by name
17
+ const EVP_CIPHER* cipher = EVP_get_cipherbyname(cipher_type.c_str());
18
+ if (!cipher) {
19
+ throw std::runtime_error("Unknown cipher " + cipher_type);
20
+ }
21
+
22
+ // 2. Create a new context
23
+ ctx = EVP_CIPHER_CTX_new();
24
+ if (!ctx) {
25
+ throw std::runtime_error("Failed to create cipher context");
26
+ }
27
+
28
+ // 3. Initialize with cipher type only (no key/IV yet)
29
+ if (EVP_CipherInit_ex(ctx, cipher, nullptr, nullptr, nullptr, is_cipher) != 1) {
30
+ unsigned long err = ERR_get_error();
31
+ char err_buf[256];
32
+ ERR_error_string_n(err, err_buf, sizeof(err_buf));
33
+ EVP_CIPHER_CTX_free(ctx);
34
+ ctx = nullptr;
35
+ throw std::runtime_error("GCMCipher: Failed initial CipherInit setup: " + std::string(err_buf));
36
+ }
37
+
38
+ // 4. Set IV length for non-standard IV sizes (GCM default is 96 bits/12 bytes)
39
+ auto native_iv = ToNativeArrayBuffer(iv);
40
+ size_t iv_len = native_iv->size();
41
+
42
+ if (iv_len != 12) { // Only set if not the default length
43
+ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, static_cast<int>(iv_len), nullptr) != 1) {
44
+ unsigned long err = ERR_get_error();
45
+ char err_buf[256];
46
+ ERR_error_string_n(err, err_buf, sizeof(err_buf));
47
+ EVP_CIPHER_CTX_free(ctx);
48
+ ctx = nullptr;
49
+ throw std::runtime_error("GCMCipher: Failed to set IV length: " + std::string(err_buf));
50
+ }
51
+ }
52
+
53
+ // 5. Now set the key and IV
54
+ auto native_key = ToNativeArrayBuffer(cipher_key);
55
+ const unsigned char* key_ptr = reinterpret_cast<const unsigned char*>(native_key->data());
56
+ const unsigned char* iv_ptr = reinterpret_cast<const unsigned char*>(native_iv->data());
57
+
58
+ if (EVP_CipherInit_ex(ctx, nullptr, nullptr, key_ptr, iv_ptr, is_cipher) != 1) {
59
+ unsigned long err = ERR_get_error();
60
+ char err_buf[256];
61
+ ERR_error_string_n(err, err_buf, sizeof(err_buf));
62
+ EVP_CIPHER_CTX_free(ctx);
63
+ ctx = nullptr;
64
+ throw std::runtime_error("GCMCipher: Failed to set key/IV: " + std::string(err_buf));
65
+ }
66
+ }
67
+
68
+ } // namespace margelo::nitro::crypto
@@ -0,0 +1,14 @@
1
+ #pragma once
2
+
3
+ #include "HybridCipher.hpp"
4
+
5
+ namespace margelo::nitro::crypto {
6
+
7
+ class GCMCipher : public HybridCipher {
8
+ public:
9
+ GCMCipher() : HybridObject(TAG) {}
10
+
11
+ void init(const std::shared_ptr<ArrayBuffer> cipher_key, const std::shared_ptr<ArrayBuffer> iv) override;
12
+ };
13
+
14
+ } // namespace margelo::nitro::crypto
@@ -7,6 +7,7 @@
7
7
  #include "CCMCipher.hpp"
8
8
  #include "ChaCha20Cipher.hpp"
9
9
  #include "ChaCha20Poly1305Cipher.hpp"
10
+ #include "GCMCipher.hpp"
10
11
  #include "HybridCipherFactorySpec.hpp"
11
12
  #include "OCBCipher.hpp"
12
13
  #include "Utils.hpp"
@@ -50,6 +51,13 @@ class HybridCipherFactory : public HybridCipherFactorySpec {
50
51
  EVP_CIPHER_free(cipher);
51
52
  return cipherInstance;
52
53
  }
54
+ case EVP_CIPH_GCM_MODE: {
55
+ cipherInstance = std::make_shared<GCMCipher>();
56
+ cipherInstance->setArgs(args);
57
+ cipherInstance->init(args.cipherKey, args.iv);
58
+ EVP_CIPHER_free(cipher);
59
+ return cipherInstance;
60
+ }
53
61
  case EVP_CIPH_STREAM_CIPHER: {
54
62
  // Check for ChaCha20 variants specifically
55
63
  std::string cipherName = toLower(args.cipherType);
@@ -0,0 +1,229 @@
1
+ #include "HybridRsaCipher.hpp"
2
+ #include "../keys/HybridKeyObjectHandle.hpp"
3
+ #include "Utils.hpp"
4
+
5
+ #include <cstring>
6
+ #include <openssl/err.h>
7
+ #include <openssl/evp.h>
8
+ #include <openssl/rsa.h>
9
+
10
+ namespace margelo::nitro::crypto {
11
+
12
+ using margelo::nitro::NativeArrayBuffer;
13
+
14
+ // Helper to get OpenSSL digest from hash algorithm name
15
+ const EVP_MD* getDigestByName(const std::string& hashAlgorithm) {
16
+ if (hashAlgorithm == "SHA-1" || hashAlgorithm == "SHA1" || hashAlgorithm == "sha1" || hashAlgorithm == "sha-1") {
17
+ return EVP_sha1();
18
+ } else if (hashAlgorithm == "SHA-256" || hashAlgorithm == "SHA256" || hashAlgorithm == "sha256" || hashAlgorithm == "sha-256") {
19
+ return EVP_sha256();
20
+ } else if (hashAlgorithm == "SHA-384" || hashAlgorithm == "SHA384" || hashAlgorithm == "sha384" || hashAlgorithm == "sha-384") {
21
+ return EVP_sha384();
22
+ } else if (hashAlgorithm == "SHA-512" || hashAlgorithm == "SHA512" || hashAlgorithm == "sha512" || hashAlgorithm == "sha-512") {
23
+ return EVP_sha512();
24
+ }
25
+ throw std::runtime_error("Unsupported hash algorithm: " + hashAlgorithm);
26
+ }
27
+
28
+ std::shared_ptr<ArrayBuffer> HybridRsaCipher::encrypt(const std::shared_ptr<HybridKeyObjectHandleSpec>& keyHandle,
29
+ const std::shared_ptr<ArrayBuffer>& data, const std::string& hashAlgorithm,
30
+ const std::optional<std::shared_ptr<ArrayBuffer>>& label) {
31
+ // Get the EVP_PKEY from the key handle
32
+ auto keyHandleImpl = std::static_pointer_cast<HybridKeyObjectHandle>(keyHandle);
33
+ EVP_PKEY* pkey = keyHandleImpl->getKeyObjectData().GetAsymmetricKey().get();
34
+
35
+ if (!pkey) {
36
+ throw std::runtime_error("Invalid key for RSA encryption");
37
+ }
38
+
39
+ // Create context for encryption
40
+ EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new(pkey, nullptr);
41
+ if (!ctx) {
42
+ throw std::runtime_error("Failed to create EVP_PKEY_CTX");
43
+ }
44
+
45
+ // Initialize encryption
46
+ if (EVP_PKEY_encrypt_init(ctx) <= 0) {
47
+ EVP_PKEY_CTX_free(ctx);
48
+ unsigned long err = ERR_get_error();
49
+ char err_buf[256];
50
+ ERR_error_string_n(err, err_buf, sizeof(err_buf));
51
+ throw std::runtime_error("Failed to initialize encryption: " + std::string(err_buf));
52
+ }
53
+
54
+ // Set padding to OAEP
55
+ if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) <= 0) {
56
+ EVP_PKEY_CTX_free(ctx);
57
+ throw std::runtime_error("Failed to set RSA OAEP padding");
58
+ }
59
+
60
+ // Set OAEP hash algorithm
61
+ const EVP_MD* md = getDigestByName(hashAlgorithm);
62
+ if (EVP_PKEY_CTX_set_rsa_oaep_md(ctx, md) <= 0) {
63
+ EVP_PKEY_CTX_free(ctx);
64
+ throw std::runtime_error("Failed to set OAEP hash algorithm");
65
+ }
66
+
67
+ // Set MGF1 hash (same as OAEP hash per WebCrypto spec)
68
+ if (EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, md) <= 0) {
69
+ EVP_PKEY_CTX_free(ctx);
70
+ throw std::runtime_error("Failed to set MGF1 hash algorithm");
71
+ }
72
+
73
+ // Set OAEP label if provided
74
+ if (label.has_value() && label.value()->size() > 0) {
75
+ auto native_label = ToNativeArrayBuffer(label.value());
76
+ // OpenSSL takes ownership of the label, so we need to allocate a copy
77
+ unsigned char* label_copy = (unsigned char*)OPENSSL_malloc(native_label->size());
78
+ if (!label_copy) {
79
+ EVP_PKEY_CTX_free(ctx);
80
+ throw std::runtime_error("Failed to allocate memory for label");
81
+ }
82
+ std::memcpy(label_copy, native_label->data(), native_label->size());
83
+
84
+ if (EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, label_copy, native_label->size()) <= 0) {
85
+ OPENSSL_free(label_copy);
86
+ EVP_PKEY_CTX_free(ctx);
87
+ throw std::runtime_error("Failed to set OAEP label");
88
+ }
89
+ }
90
+
91
+ // Get input data
92
+ auto native_data = ToNativeArrayBuffer(data);
93
+ const unsigned char* in = native_data->data();
94
+ size_t inlen = native_data->size();
95
+
96
+ // Determine output length
97
+ size_t outlen;
98
+ if (EVP_PKEY_encrypt(ctx, nullptr, &outlen, in, inlen) <= 0) {
99
+ EVP_PKEY_CTX_free(ctx);
100
+ unsigned long err = ERR_get_error();
101
+ char err_buf[256];
102
+ ERR_error_string_n(err, err_buf, sizeof(err_buf));
103
+ throw std::runtime_error("Failed to determine output length: " + std::string(err_buf));
104
+ }
105
+
106
+ // Allocate output buffer
107
+ auto out_buf = std::make_unique<uint8_t[]>(outlen);
108
+
109
+ // Perform encryption
110
+ if (EVP_PKEY_encrypt(ctx, out_buf.get(), &outlen, in, inlen) <= 0) {
111
+ EVP_PKEY_CTX_free(ctx);
112
+ unsigned long err = ERR_get_error();
113
+ char err_buf[256];
114
+ ERR_error_string_n(err, err_buf, sizeof(err_buf));
115
+ throw std::runtime_error("Encryption failed: " + std::string(err_buf));
116
+ }
117
+
118
+ EVP_PKEY_CTX_free(ctx);
119
+
120
+ // Create ArrayBuffer from result
121
+ uint8_t* raw_ptr = out_buf.get();
122
+ return std::make_shared<NativeArrayBuffer>(out_buf.release(), outlen, [raw_ptr]() { delete[] raw_ptr; });
123
+ }
124
+
125
+ std::shared_ptr<ArrayBuffer> HybridRsaCipher::decrypt(const std::shared_ptr<HybridKeyObjectHandleSpec>& keyHandle,
126
+ const std::shared_ptr<ArrayBuffer>& data, const std::string& hashAlgorithm,
127
+ const std::optional<std::shared_ptr<ArrayBuffer>>& label) {
128
+ // Get the EVP_PKEY from the key handle
129
+ auto keyHandleImpl = std::static_pointer_cast<HybridKeyObjectHandle>(keyHandle);
130
+ EVP_PKEY* pkey = keyHandleImpl->getKeyObjectData().GetAsymmetricKey().get();
131
+
132
+ if (!pkey) {
133
+ throw std::runtime_error("Invalid key for RSA decryption");
134
+ }
135
+
136
+ // Create context for decryption
137
+ EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new(pkey, nullptr);
138
+ if (!ctx) {
139
+ throw std::runtime_error("Failed to create EVP_PKEY_CTX");
140
+ }
141
+
142
+ // Initialize decryption
143
+ if (EVP_PKEY_decrypt_init(ctx) <= 0) {
144
+ EVP_PKEY_CTX_free(ctx);
145
+ unsigned long err = ERR_get_error();
146
+ char err_buf[256];
147
+ ERR_error_string_n(err, err_buf, sizeof(err_buf));
148
+ throw std::runtime_error("Failed to initialize decryption: " + std::string(err_buf));
149
+ }
150
+
151
+ // Set padding to OAEP
152
+ if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) <= 0) {
153
+ EVP_PKEY_CTX_free(ctx);
154
+ throw std::runtime_error("Failed to set RSA OAEP padding");
155
+ }
156
+
157
+ // Set OAEP hash algorithm
158
+ const EVP_MD* md = getDigestByName(hashAlgorithm);
159
+ if (EVP_PKEY_CTX_set_rsa_oaep_md(ctx, md) <= 0) {
160
+ EVP_PKEY_CTX_free(ctx);
161
+ throw std::runtime_error("Failed to set OAEP hash algorithm");
162
+ }
163
+
164
+ // Set MGF1 hash (same as OAEP hash per WebCrypto spec)
165
+ if (EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, md) <= 0) {
166
+ EVP_PKEY_CTX_free(ctx);
167
+ throw std::runtime_error("Failed to set MGF1 hash algorithm");
168
+ }
169
+
170
+ // Set OAEP label if provided
171
+ if (label.has_value() && label.value()->size() > 0) {
172
+ auto native_label = ToNativeArrayBuffer(label.value());
173
+ // OpenSSL takes ownership of the label, so we need to allocate a copy
174
+ unsigned char* label_copy = (unsigned char*)OPENSSL_malloc(native_label->size());
175
+ if (!label_copy) {
176
+ EVP_PKEY_CTX_free(ctx);
177
+ throw std::runtime_error("Failed to allocate memory for label");
178
+ }
179
+ std::memcpy(label_copy, native_label->data(), native_label->size());
180
+
181
+ if (EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, label_copy, native_label->size()) <= 0) {
182
+ OPENSSL_free(label_copy);
183
+ EVP_PKEY_CTX_free(ctx);
184
+ throw std::runtime_error("Failed to set OAEP label");
185
+ }
186
+ }
187
+
188
+ // Get input data
189
+ auto native_data = ToNativeArrayBuffer(data);
190
+ const unsigned char* in = native_data->data();
191
+ size_t inlen = native_data->size();
192
+
193
+ // Determine output length
194
+ size_t outlen;
195
+ if (EVP_PKEY_decrypt(ctx, nullptr, &outlen, in, inlen) <= 0) {
196
+ EVP_PKEY_CTX_free(ctx);
197
+ unsigned long err = ERR_get_error();
198
+ char err_buf[256];
199
+ ERR_error_string_n(err, err_buf, sizeof(err_buf));
200
+ throw std::runtime_error("Failed to determine output length: " + std::string(err_buf));
201
+ }
202
+
203
+ // Allocate output buffer
204
+ auto out_buf = std::make_unique<uint8_t[]>(outlen);
205
+
206
+ // Perform decryption
207
+ if (EVP_PKEY_decrypt(ctx, out_buf.get(), &outlen, in, inlen) <= 0) {
208
+ EVP_PKEY_CTX_free(ctx);
209
+ unsigned long err = ERR_get_error();
210
+ char err_buf[256];
211
+ ERR_error_string_n(err, err_buf, sizeof(err_buf));
212
+ throw std::runtime_error("Decryption failed: " + std::string(err_buf));
213
+ }
214
+
215
+ EVP_PKEY_CTX_free(ctx);
216
+
217
+ // Create ArrayBuffer from result
218
+ uint8_t* raw_ptr = out_buf.get();
219
+ return std::make_shared<NativeArrayBuffer>(out_buf.release(), outlen, [raw_ptr]() { delete[] raw_ptr; });
220
+ }
221
+
222
+ void HybridRsaCipher::loadHybridMethods() {
223
+ registerHybrids(this, [](Prototype& prototype) {
224
+ prototype.registerHybridMethod("encrypt", &HybridRsaCipher::encrypt);
225
+ prototype.registerHybridMethod("decrypt", &HybridRsaCipher::decrypt);
226
+ });
227
+ }
228
+
229
+ } // namespace margelo::nitro::crypto
@@ -0,0 +1,23 @@
1
+ #pragma once
2
+
3
+ #include "HybridRsaCipherSpec.hpp"
4
+ #include <memory>
5
+
6
+ namespace margelo::nitro::crypto {
7
+
8
+ class HybridRsaCipher : public HybridRsaCipherSpec {
9
+ public:
10
+ HybridRsaCipher() : HybridObject(TAG) {}
11
+
12
+ std::shared_ptr<ArrayBuffer> encrypt(const std::shared_ptr<HybridKeyObjectHandleSpec>& keyHandle,
13
+ const std::shared_ptr<ArrayBuffer>& data, const std::string& hashAlgorithm,
14
+ const std::optional<std::shared_ptr<ArrayBuffer>>& label) override;
15
+
16
+ std::shared_ptr<ArrayBuffer> decrypt(const std::shared_ptr<HybridKeyObjectHandleSpec>& keyHandle,
17
+ const std::shared_ptr<ArrayBuffer>& data, const std::string& hashAlgorithm,
18
+ const std::optional<std::shared_ptr<ArrayBuffer>>& label) override;
19
+
20
+ void loadHybridMethods() override;
21
+ };
22
+
23
+ } // namespace margelo::nitro::crypto