react-native-quick-crypto 1.0.0-beta.12 → 1.0.0-beta.13

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 (47) hide show
  1. package/android/CMakeLists.txt +2 -0
  2. package/cpp/ed25519/HybridEdKeyPair.cpp +32 -89
  3. package/cpp/ed25519/HybridEdKeyPair.hpp +24 -54
  4. package/cpp/hash/HybridHash.cpp +30 -60
  5. package/cpp/hash/HybridHash.hpp +11 -27
  6. package/cpp/hmac/HybridHmac.cpp +95 -0
  7. package/cpp/hmac/HybridHmac.hpp +31 -0
  8. package/cpp/pbkdf2/HybridPbkdf2.cpp +34 -55
  9. package/cpp/pbkdf2/HybridPbkdf2.hpp +5 -16
  10. package/cpp/random/HybridRandom.cpp +5 -16
  11. package/cpp/random/HybridRandom.hpp +5 -6
  12. package/cpp/utils/Utils.hpp +1 -2
  13. package/lib/commonjs/hash.js +41 -18
  14. package/lib/commonjs/hash.js.map +1 -1
  15. package/lib/commonjs/hmac.js +109 -0
  16. package/lib/commonjs/hmac.js.map +1 -0
  17. package/lib/commonjs/index.js +13 -0
  18. package/lib/commonjs/index.js.map +1 -1
  19. package/lib/commonjs/specs/hmac.nitro.js +6 -0
  20. package/lib/commonjs/specs/hmac.nitro.js.map +1 -0
  21. package/lib/module/hash.js +41 -18
  22. package/lib/module/hash.js.map +1 -1
  23. package/lib/module/hmac.js +104 -0
  24. package/lib/module/hmac.js.map +1 -0
  25. package/lib/module/index.js +3 -0
  26. package/lib/module/index.js.map +1 -1
  27. package/lib/module/specs/hmac.nitro.js +4 -0
  28. package/lib/module/specs/hmac.nitro.js.map +1 -0
  29. package/lib/tsconfig.tsbuildinfo +1 -1
  30. package/lib/typescript/hash.d.ts +23 -0
  31. package/lib/typescript/hash.d.ts.map +1 -1
  32. package/lib/typescript/hmac.d.ts +67 -0
  33. package/lib/typescript/hmac.d.ts.map +1 -0
  34. package/lib/typescript/index.d.ts +2 -0
  35. package/lib/typescript/index.d.ts.map +1 -1
  36. package/lib/typescript/specs/hmac.nitro.d.ts +10 -0
  37. package/lib/typescript/specs/hmac.nitro.d.ts.map +1 -0
  38. package/nitrogen/generated/android/QuickCrypto+autolinking.cmake +1 -0
  39. package/nitrogen/generated/android/QuickCryptoOnLoad.cpp +10 -0
  40. package/nitrogen/generated/ios/QuickCryptoAutolinking.mm +10 -0
  41. package/nitrogen/generated/shared/c++/HybridHmacSpec.cpp +23 -0
  42. package/nitrogen/generated/shared/c++/HybridHmacSpec.hpp +66 -0
  43. package/package.json +1 -1
  44. package/src/hash.ts +51 -15
  45. package/src/hmac.ts +135 -0
  46. package/src/index.ts +3 -0
  47. package/src/specs/hmac.nitro.ts +7 -0
@@ -9,6 +9,7 @@ set(CMAKE_CXX_STANDARD 20)
9
9
  add_library(
10
10
  ${PACKAGE_NAME} SHARED
11
11
  src/main/cpp/cpp-adapter.cpp
12
+ ../cpp/hmac/HybridHmac.cpp
12
13
  ../cpp/hash/HybridHash.cpp
13
14
  ../cpp/ed25519/HybridEdKeyPair.cpp
14
15
  ../cpp/pbkdf2/HybridPbkdf2.cpp
@@ -22,6 +23,7 @@ include(${CMAKE_SOURCE_DIR}/../nitrogen/generated/android/QuickCrypto+autolinkin
22
23
  # local includes
23
24
  include_directories(
24
25
  "src/main/cpp"
26
+ "../cpp/hmac"
25
27
  "../cpp/hash"
26
28
  "../cpp/ed25519"
27
29
  "../cpp/pbkdf2"
@@ -5,45 +5,23 @@
5
5
 
6
6
  namespace margelo::nitro::crypto {
7
7
 
8
- std::shared_ptr<Promise<void>>
9
- HybridEdKeyPair::generateKeyPair(
10
- double publicFormat,
11
- double publicType,
12
- double privateFormat,
13
- double privateType,
14
- const std::optional<std::string>& cipher,
15
- const std::optional<std::shared_ptr<ArrayBuffer>>& passphrase
16
- ) {
8
+ std::shared_ptr<Promise<void>> HybridEdKeyPair::generateKeyPair(double publicFormat, double publicType, double privateFormat,
9
+ double privateType, const std::optional<std::string>& cipher,
10
+ const std::optional<std::shared_ptr<ArrayBuffer>>& passphrase) {
17
11
  // get owned NativeArrayBuffers before passing to sync function
18
12
  std::optional<std::shared_ptr<ArrayBuffer>> nativePassphrase = std::nullopt;
19
13
  if (passphrase.has_value()) {
20
14
  nativePassphrase = ToNativeArrayBuffer(passphrase.value());
21
15
  }
22
16
 
23
- return Promise<void>::async(
24
- [this, publicFormat, publicType, privateFormat, privateType, cipher,
25
- nativePassphrase]() {
26
- this->generateKeyPairSync(
27
- publicFormat,
28
- publicType,
29
- privateFormat,
30
- privateType,
31
- cipher,
32
- nativePassphrase
33
- );
34
- }
35
- );
17
+ return Promise<void>::async([this, publicFormat, publicType, privateFormat, privateType, cipher, nativePassphrase]() {
18
+ this->generateKeyPairSync(publicFormat, publicType, privateFormat, privateType, cipher, nativePassphrase);
19
+ });
36
20
  }
37
21
 
38
- void
39
- HybridEdKeyPair::generateKeyPairSync(
40
- double publicFormat,
41
- double publicType,
42
- double privateFormat,
43
- double privateType,
44
- const std::optional<std::string>& cipher,
45
- const std::optional<std::shared_ptr<ArrayBuffer>>& passphrase
46
- ) {
22
+ void HybridEdKeyPair::generateKeyPairSync(double publicFormat, double publicType, double privateFormat, double privateType,
23
+ const std::optional<std::string>& cipher,
24
+ const std::optional<std::shared_ptr<ArrayBuffer>>& passphrase) {
47
25
  EVP_PKEY_CTX* pctx;
48
26
 
49
27
  // key context
@@ -69,12 +47,8 @@ HybridEdKeyPair::generateKeyPairSync(
69
47
  EVP_PKEY_CTX_free(pctx);
70
48
  }
71
49
 
72
-
73
- std::shared_ptr<Promise<std::shared_ptr<ArrayBuffer>>>
74
- HybridEdKeyPair::sign(
75
- const std::shared_ptr<ArrayBuffer>& message,
76
- const std::optional<std::shared_ptr<ArrayBuffer>>& key
77
- ) {
50
+ std::shared_ptr<Promise<std::shared_ptr<ArrayBuffer>>> HybridEdKeyPair::sign(const std::shared_ptr<ArrayBuffer>& message,
51
+ const std::optional<std::shared_ptr<ArrayBuffer>>& key) {
78
52
  // get owned NativeArrayBuffer before passing to sync function
79
53
  auto nativeMessage = ToNativeArrayBuffer(message);
80
54
  std::optional<std::shared_ptr<ArrayBuffer>> nativeKey = std::nullopt;
@@ -82,17 +56,12 @@ HybridEdKeyPair::sign(
82
56
  nativeKey = ToNativeArrayBuffer(key.value());
83
57
  }
84
58
 
85
- return Promise<std::shared_ptr<ArrayBuffer>>::async([this, nativeMessage, nativeKey]() {
86
- return this->signSync(nativeMessage, nativeKey);
87
- }
88
- );
59
+ return Promise<std::shared_ptr<ArrayBuffer>>::async(
60
+ [this, nativeMessage, nativeKey]() { return this->signSync(nativeMessage, nativeKey); });
89
61
  }
90
62
 
91
- std::shared_ptr<ArrayBuffer>
92
- HybridEdKeyPair::signSync(
93
- const std::shared_ptr<ArrayBuffer>& message,
94
- const std::optional<std::shared_ptr<ArrayBuffer>>& key
95
- ) {
63
+ std::shared_ptr<ArrayBuffer> HybridEdKeyPair::signSync(const std::shared_ptr<ArrayBuffer>& message,
64
+ const std::optional<std::shared_ptr<ArrayBuffer>>& key) {
96
65
 
97
66
  size_t sig_len = 0;
98
67
  uint8_t* sig = NULL;
@@ -135,11 +104,7 @@ HybridEdKeyPair::signSync(
135
104
  }
136
105
 
137
106
  // return value for JS
138
- std::shared_ptr<ArrayBuffer> signature = std::make_shared<NativeArrayBuffer>(
139
- sig,
140
- sig_len,
141
- [=]() { delete[] sig; }
142
- );
107
+ std::shared_ptr<ArrayBuffer> signature = std::make_shared<NativeArrayBuffer>(sig, sig_len, [=]() { delete[] sig; });
143
108
 
144
109
  // Clean up
145
110
  EVP_MD_CTX_free(md_ctx);
@@ -147,12 +112,9 @@ HybridEdKeyPair::signSync(
147
112
  return signature;
148
113
  }
149
114
 
150
- std::shared_ptr<Promise<bool>>
151
- HybridEdKeyPair::verify(
152
- const std::shared_ptr<ArrayBuffer>& signature,
153
- const std::shared_ptr<ArrayBuffer>& message,
154
- const std::optional<std::shared_ptr<ArrayBuffer>>& key
155
- ) {
115
+ std::shared_ptr<Promise<bool>> HybridEdKeyPair::verify(const std::shared_ptr<ArrayBuffer>& signature,
116
+ const std::shared_ptr<ArrayBuffer>& message,
117
+ const std::optional<std::shared_ptr<ArrayBuffer>>& key) {
156
118
  // get owned NativeArrayBuffers before passing to sync function
157
119
  auto nativeSignature = ToNativeArrayBuffer(signature);
158
120
  auto nativeMessage = ToNativeArrayBuffer(message);
@@ -161,18 +123,12 @@ HybridEdKeyPair::verify(
161
123
  nativeKey = ToNativeArrayBuffer(key.value());
162
124
  }
163
125
 
164
- return Promise<bool>::async([this, nativeSignature, nativeMessage, nativeKey]() {
165
- return this->verifySync(nativeSignature, nativeMessage, nativeKey);
166
- }
167
- );
126
+ return Promise<bool>::async(
127
+ [this, nativeSignature, nativeMessage, nativeKey]() { return this->verifySync(nativeSignature, nativeMessage, nativeKey); });
168
128
  }
169
129
 
170
- bool
171
- HybridEdKeyPair::verifySync(
172
- const std::shared_ptr<ArrayBuffer>& signature,
173
- const std::shared_ptr<ArrayBuffer>& message,
174
- const std::optional<std::shared_ptr<ArrayBuffer>>& key
175
- ) {
130
+ bool HybridEdKeyPair::verifySync(const std::shared_ptr<ArrayBuffer>& signature, const std::shared_ptr<ArrayBuffer>& message,
131
+ const std::optional<std::shared_ptr<ArrayBuffer>>& key) {
176
132
  // get key to use for verifying
177
133
  EVP_PKEY* pkey = this->importPrivateKey(key);
178
134
 
@@ -199,13 +155,9 @@ HybridEdKeyPair::verifySync(
199
155
  }
200
156
 
201
157
  // verify
202
- auto res = EVP_DigestVerify(
203
- md_ctx,
204
- signature.get()->data(), signature.get()->size(),
205
- message.get()->data(), message.get()->size()
206
- );
158
+ auto res = EVP_DigestVerify(md_ctx, signature.get()->data(), signature.get()->size(), message.get()->data(), message.get()->size());
207
159
 
208
- //return value for JS
160
+ // return value for JS
209
161
  if (res < 0) {
210
162
  EVP_MD_CTX_free(md_ctx);
211
163
  throw std::runtime_error("Failed to verify");
@@ -213,8 +165,7 @@ HybridEdKeyPair::verifySync(
213
165
  return res == 1; // true if 1, false if 0
214
166
  }
215
167
 
216
- std::shared_ptr<ArrayBuffer>
217
- HybridEdKeyPair::getPublicKey() {
168
+ std::shared_ptr<ArrayBuffer> HybridEdKeyPair::getPublicKey() {
218
169
  this->checkKeyPair();
219
170
  size_t len = 32;
220
171
  uint8_t* publ = new uint8_t[len];
@@ -223,8 +174,7 @@ HybridEdKeyPair::getPublicKey() {
223
174
  return std::make_shared<NativeArrayBuffer>(publ, len, [=]() { delete[] publ; });
224
175
  }
225
176
 
226
- std::shared_ptr<ArrayBuffer>
227
- HybridEdKeyPair::getPrivateKey() {
177
+ std::shared_ptr<ArrayBuffer> HybridEdKeyPair::getPrivateKey() {
228
178
  this->checkKeyPair();
229
179
  size_t len = 32;
230
180
  uint8_t* priv = new uint8_t[len];
@@ -233,28 +183,21 @@ HybridEdKeyPair::getPrivateKey() {
233
183
  return std::make_shared<NativeArrayBuffer>(priv, len, [=]() { delete[] priv; });
234
184
  }
235
185
 
236
- void
237
- HybridEdKeyPair::checkKeyPair() {
186
+ void HybridEdKeyPair::checkKeyPair() {
238
187
  if (this->pkey == nullptr) {
239
188
  throw std::runtime_error("Keypair not initialized");
240
189
  }
241
190
  }
242
191
 
243
- void
244
- HybridEdKeyPair::setCurve(const std::string& curve) {
192
+ void HybridEdKeyPair::setCurve(const std::string& curve) {
245
193
  this->curve = curve;
246
194
  }
247
195
 
248
- EVP_PKEY*
249
- HybridEdKeyPair::importPrivateKey(const std::optional<std::shared_ptr<ArrayBuffer>>& key) {
196
+ EVP_PKEY* HybridEdKeyPair::importPrivateKey(const std::optional<std::shared_ptr<ArrayBuffer>>& key) {
250
197
  EVP_PKEY* pkey = nullptr;
251
198
  if (key.has_value()) {
252
- pkey = EVP_PKEY_new_raw_private_key(
253
- EVP_PKEY_ED25519, // TODO: use this->curve somehow
254
- NULL,
255
- key.value()->data(),
256
- 32
257
- );
199
+ pkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_ED25519, // TODO: use this->curve somehow
200
+ NULL, key.value()->data(), 32);
258
201
  if (pkey == nullptr) {
259
202
  throw std::runtime_error("Failed to read private key");
260
203
  }
@@ -1,6 +1,6 @@
1
- #include <openssl/evp.h>
2
- #include <openssl/err.h>
3
1
  #include <memory>
2
+ #include <openssl/err.h>
3
+ #include <openssl/evp.h>
4
4
  #include <string>
5
5
 
6
6
  #include "HybridEdKeyPairSpec.hpp"
@@ -16,58 +16,30 @@ class HybridEdKeyPair : public HybridEdKeyPairSpec {
16
16
 
17
17
  public:
18
18
  // Methods
19
- std::shared_ptr<Promise<void>>
20
- generateKeyPair(
21
- double publicFormat,
22
- double publicType,
23
- double privateFormat,
24
- double privateType,
25
- const std::optional<std::string>& cipher,
26
- const std::optional<std::shared_ptr<ArrayBuffer>>& passphrase
27
- ) override;
28
-
29
- void
30
- generateKeyPairSync(
31
- double publicFormat,
32
- double publicType,
33
- double privateFormat,
34
- double privateType,
35
- const std::optional<std::string>& cipher,
36
- const std::optional<std::shared_ptr<ArrayBuffer>>& passphrase
37
- ) override;
38
-
39
- std::shared_ptr<Promise<std::shared_ptr<ArrayBuffer>>>
40
- sign(
41
- const std::shared_ptr<ArrayBuffer>& message,
42
- const std::optional<std::shared_ptr<ArrayBuffer>>& key
43
- ) override;
44
-
45
- std::shared_ptr<ArrayBuffer>
46
- signSync(
47
- const std::shared_ptr<ArrayBuffer>& message,
48
- const std::optional<std::shared_ptr<ArrayBuffer>>& key
49
- ) override;
50
-
51
- std::shared_ptr<Promise<bool>>
52
- verify(
53
- const std::shared_ptr<ArrayBuffer>& signature,
54
- const std::shared_ptr<ArrayBuffer>& message,
55
- const std::optional<std::shared_ptr<ArrayBuffer>>& key
56
- ) override;
57
-
58
- bool
59
- verifySync(
60
- const std::shared_ptr<ArrayBuffer>& signature,
61
- const std::shared_ptr<ArrayBuffer>& message,
62
- const std::optional<std::shared_ptr<ArrayBuffer>>& key
63
- ) override;
19
+ std::shared_ptr<Promise<void>> generateKeyPair(double publicFormat, double publicType, double privateFormat, double privateType,
20
+ const std::optional<std::string>& cipher,
21
+ const std::optional<std::shared_ptr<ArrayBuffer>>& passphrase) override;
22
+
23
+ void generateKeyPairSync(double publicFormat, double publicType, double privateFormat, double privateType,
24
+ const std::optional<std::string>& cipher,
25
+ const std::optional<std::shared_ptr<ArrayBuffer>>& passphrase) override;
26
+
27
+ std::shared_ptr<Promise<std::shared_ptr<ArrayBuffer>>> sign(const std::shared_ptr<ArrayBuffer>& message,
28
+ const std::optional<std::shared_ptr<ArrayBuffer>>& key) override;
29
+
30
+ std::shared_ptr<ArrayBuffer> signSync(const std::shared_ptr<ArrayBuffer>& message,
31
+ const std::optional<std::shared_ptr<ArrayBuffer>>& key) override;
32
+
33
+ std::shared_ptr<Promise<bool>> verify(const std::shared_ptr<ArrayBuffer>& signature, const std::shared_ptr<ArrayBuffer>& message,
34
+ const std::optional<std::shared_ptr<ArrayBuffer>>& key) override;
35
+
36
+ bool verifySync(const std::shared_ptr<ArrayBuffer>& signature, const std::shared_ptr<ArrayBuffer>& message,
37
+ const std::optional<std::shared_ptr<ArrayBuffer>>& key) override;
64
38
 
65
39
  protected:
66
- std::shared_ptr<ArrayBuffer>
67
- getPublicKey() override;
40
+ std::shared_ptr<ArrayBuffer> getPublicKey() override;
68
41
 
69
- std::shared_ptr<ArrayBuffer>
70
- getPrivateKey() override;
42
+ std::shared_ptr<ArrayBuffer> getPrivateKey() override;
71
43
 
72
44
  void checkKeyPair();
73
45
 
@@ -77,9 +49,7 @@ class HybridEdKeyPair : public HybridEdKeyPairSpec {
77
49
  std::string curve;
78
50
  EVP_PKEY* pkey = nullptr;
79
51
 
80
- EVP_PKEY* importPrivateKey(
81
- const std::optional<std::shared_ptr<ArrayBuffer>>& key
82
- );
52
+ EVP_PKEY* importPrivateKey(const std::optional<std::shared_ptr<ArrayBuffer>>& key);
83
53
  };
84
54
 
85
55
  } // namespace margelo::nitro::crypto
@@ -10,26 +10,21 @@
10
10
 
11
11
  namespace margelo::nitro::crypto {
12
12
 
13
- HybridHash::~HybridHash()
14
- {
13
+ HybridHash::~HybridHash() {
15
14
  if (ctx) {
16
15
  EVP_MD_CTX_free(ctx);
17
16
  ctx = nullptr;
18
17
  }
19
18
  }
20
19
 
21
- void
22
- HybridHash::createHash(const std::string& hashAlgorithmArg,
23
- const std::optional<double> outputLengthArg)
24
- {
20
+ void HybridHash::createHash(const std::string& hashAlgorithmArg, const std::optional<double> outputLengthArg) {
25
21
  algorithm = hashAlgorithmArg;
26
22
  outputLength = outputLengthArg;
27
23
 
28
24
  // Create hash context
29
25
  ctx = EVP_MD_CTX_new();
30
26
  if (!ctx) {
31
- throw std::runtime_error("Failed to create hash context: " +
32
- std::to_string(ERR_get_error()));
27
+ throw std::runtime_error("Failed to create hash context: " + std::to_string(ERR_get_error()));
33
28
  }
34
29
 
35
30
  // Get the message digest by name
@@ -44,30 +39,22 @@ HybridHash::createHash(const std::string& hashAlgorithmArg,
44
39
  if (EVP_DigestInit_ex(ctx, md, nullptr) != 1) {
45
40
  EVP_MD_CTX_free(ctx);
46
41
  ctx = nullptr;
47
- throw std::runtime_error("Failed to initialize hash digest: " +
48
- std::to_string(ERR_get_error()));
42
+ throw std::runtime_error("Failed to initialize hash digest: " + std::to_string(ERR_get_error()));
49
43
  }
50
44
  }
51
45
 
52
- void
53
- HybridHash::update(const std::shared_ptr<ArrayBuffer>& data)
54
- {
46
+ void HybridHash::update(const std::shared_ptr<ArrayBuffer>& data) {
55
47
  if (!ctx) {
56
48
  throw std::runtime_error("Hash context not initialized");
57
49
  }
58
50
 
59
51
  // Update the digest with the data
60
- if (EVP_DigestUpdate(ctx,
61
- reinterpret_cast<const uint8_t*>(data->data()),
62
- data->size()) != 1) {
63
- throw std::runtime_error("Failed to update hash digest: " +
64
- std::to_string(ERR_get_error()));
52
+ if (EVP_DigestUpdate(ctx, reinterpret_cast<const uint8_t*>(data->data()), data->size()) != 1) {
53
+ throw std::runtime_error("Failed to update hash digest: " + std::to_string(ERR_get_error()));
65
54
  }
66
55
  }
67
56
 
68
- std::shared_ptr<ArrayBuffer>
69
- HybridHash::digest(const std::optional<std::string>& encoding)
70
- {
57
+ std::shared_ptr<ArrayBuffer> HybridHash::digest(const std::optional<std::string>& encoding) {
71
58
  if (!ctx) {
72
59
  throw std::runtime_error("Hash context not initialized");
73
60
  }
@@ -76,12 +63,10 @@ HybridHash::digest(const std::optional<std::string>& encoding)
76
63
 
77
64
  // Get the default digest size
78
65
  const size_t defaultLen = EVP_MD_CTX_size(ctx);
79
- const size_t digestSize =
80
- (outputLength.has_value()) ? static_cast<int>(*outputLength) : defaultLen;
66
+ const size_t digestSize = (outputLength.has_value()) ? static_cast<int>(*outputLength) : defaultLen;
81
67
 
82
68
  if (digestSize < 0) {
83
- throw std::runtime_error("Invalid digest size: " +
84
- std::to_string(digestSize));
69
+ throw std::runtime_error("Invalid digest size: " + std::to_string(digestSize));
85
70
  }
86
71
 
87
72
  // Create a buffer for the hash output
@@ -91,25 +76,20 @@ HybridHash::digest(const std::optional<std::string>& encoding)
91
76
  // Finalize the digest
92
77
  int ret;
93
78
  if (digestSize == defaultLen) {
94
- ret = EVP_DigestFinal_ex(
95
- ctx, hashBuffer, reinterpret_cast<unsigned int*>(&hashLength));
79
+ ret = EVP_DigestFinal_ex(ctx, hashBuffer, reinterpret_cast<unsigned int*>(&hashLength));
96
80
  } else {
97
81
  ret = EVP_DigestFinalXOF(ctx, hashBuffer, hashLength);
98
82
  }
99
83
 
100
84
  if (ret != 1) {
101
85
  delete[] hashBuffer;
102
- throw std::runtime_error("Failed to finalize hash digest: " +
103
- std::to_string(ERR_get_error()));
86
+ throw std::runtime_error("Failed to finalize hash digest: " + std::to_string(ERR_get_error()));
104
87
  }
105
88
 
106
- return std::make_shared<NativeArrayBuffer>(
107
- hashBuffer, hashLength, [=]() { delete[] hashBuffer; });
89
+ return std::make_shared<NativeArrayBuffer>(hashBuffer, hashLength, [=]() { delete[] hashBuffer; });
108
90
  }
109
91
 
110
- std::shared_ptr<margelo::nitro::crypto::HybridHashSpec>
111
- HybridHash::copy(const std::optional<double> outputLengthArg)
112
- {
92
+ std::shared_ptr<margelo::nitro::crypto::HybridHashSpec> HybridHash::copy(const std::optional<double> outputLengthArg) {
113
93
  if (!ctx) {
114
94
  throw std::runtime_error("Hash context not initialized");
115
95
  }
@@ -117,42 +97,36 @@ HybridHash::copy(const std::optional<double> outputLengthArg)
117
97
  // Create a new context
118
98
  EVP_MD_CTX* newCtx = EVP_MD_CTX_new();
119
99
  if (!newCtx) {
120
- throw std::runtime_error("Failed to create new hash context: " +
121
- std::to_string(ERR_get_error()));
100
+ throw std::runtime_error("Failed to create new hash context: " + std::to_string(ERR_get_error()));
122
101
  }
123
102
 
124
103
  // Copy the existing context to the new one
125
104
  if (EVP_MD_CTX_copy(newCtx, ctx) != 1) {
126
105
  EVP_MD_CTX_free(newCtx);
127
- throw std::runtime_error("Failed to copy hash context: " +
128
- std::to_string(ERR_get_error()));
106
+ throw std::runtime_error("Failed to copy hash context: " + std::to_string(ERR_get_error()));
129
107
  }
130
108
 
131
109
  return std::make_shared<HybridHash>(newCtx, md, algorithm, outputLengthArg);
132
110
  }
133
111
 
134
- std::vector<std::string>
135
- HybridHash::getSupportedHashAlgorithms()
136
- {
112
+ std::vector<std::string> HybridHash::getSupportedHashAlgorithms() {
137
113
  std::vector<std::string> hashAlgorithms;
138
114
 
139
115
  EVP_MD_do_all_provided(
140
- nullptr,
141
- [](EVP_MD* md, void* arg) {
142
- auto* algorithms = static_cast<std::vector<std::string>*>(arg);
143
- const char* name = EVP_MD_get0_name(md);
144
- if (name) {
145
- algorithms->push_back(name);
146
- }
147
- },
148
- &hashAlgorithms);
116
+ nullptr,
117
+ [](EVP_MD* md, void* arg) {
118
+ auto* algorithms = static_cast<std::vector<std::string>*>(arg);
119
+ const char* name = EVP_MD_get0_name(md);
120
+ if (name) {
121
+ algorithms->push_back(name);
122
+ }
123
+ },
124
+ &hashAlgorithms);
149
125
 
150
126
  return hashAlgorithms;
151
127
  }
152
128
 
153
- void
154
- HybridHash::setParams()
155
- {
129
+ void HybridHash::setParams() {
156
130
  // Handle algorithm parameters (like XOF length for SHAKE)
157
131
  if (outputLength.has_value()) {
158
132
  uint32_t xoflen = outputLength.value();
@@ -160,20 +134,16 @@ HybridHash::setParams()
160
134
  // Add a reasonable maximum output length
161
135
  const int MAX_OUTPUT_LENGTH = 16 * 1024 * 1024; // 16MB
162
136
  if (xoflen > MAX_OUTPUT_LENGTH) {
163
- throw std::runtime_error("Output length " + std::to_string(xoflen) +
164
- " exceeds maximum allowed size of " +
137
+ throw std::runtime_error("Output length " + std::to_string(xoflen) + " exceeds maximum allowed size of " +
165
138
  std::to_string(MAX_OUTPUT_LENGTH));
166
139
  }
167
140
 
168
- OSSL_PARAM params[] = { OSSL_PARAM_construct_uint("xoflen", &xoflen),
169
- OSSL_PARAM_END };
141
+ OSSL_PARAM params[] = {OSSL_PARAM_construct_uint("xoflen", &xoflen), OSSL_PARAM_END};
170
142
 
171
143
  if (EVP_MD_CTX_set_params(ctx, params) != 1) {
172
144
  EVP_MD_CTX_free(ctx);
173
145
  ctx = nullptr;
174
- throw std::runtime_error(
175
- "Failed to set XOF length (outputLength) parameter: " +
176
- std::to_string(ERR_get_error()));
146
+ throw std::runtime_error("Failed to set XOF length (outputLength) parameter: " + std::to_string(ERR_get_error()));
177
147
  }
178
148
  }
179
149
  }
@@ -11,42 +11,26 @@ namespace margelo::nitro::crypto {
11
11
 
12
12
  using namespace facebook;
13
13
 
14
- class HybridHash : public HybridHashSpec
15
- {
16
- public:
17
- HybridHash()
18
- : HybridObject(TAG)
19
- {
20
- }
21
- HybridHash(EVP_MD_CTX* ctx,
22
- const EVP_MD* md,
23
- const std::string& algorithm,
24
- const std::optional<double> outputLength)
25
- : HybridObject(TAG)
26
- , ctx(ctx)
27
- , md(md)
28
- , algorithm(algorithm)
29
- , outputLength(outputLength)
30
- {
31
- }
14
+ class HybridHash : public HybridHashSpec {
15
+ public:
16
+ HybridHash() : HybridObject(TAG) {}
17
+ HybridHash(EVP_MD_CTX* ctx, const EVP_MD* md, const std::string& algorithm, const std::optional<double> outputLength)
18
+ : HybridObject(TAG), ctx(ctx), md(md), algorithm(algorithm), outputLength(outputLength) {}
32
19
  ~HybridHash();
33
20
 
34
- public:
21
+ public:
35
22
  // Methods
36
- void createHash(const std::string& algorithm,
37
- const std::optional<double> outputLength) override;
23
+ void createHash(const std::string& algorithm, const std::optional<double> outputLength) override;
38
24
  void update(const std::shared_ptr<ArrayBuffer>& data) override;
39
- std::shared_ptr<ArrayBuffer> digest(
40
- const std::optional<std::string>& encoding = std::nullopt) override;
41
- std::shared_ptr<margelo::nitro::crypto::HybridHashSpec> copy(
42
- const std::optional<double> outputLength) override;
25
+ std::shared_ptr<ArrayBuffer> digest(const std::optional<std::string>& encoding = std::nullopt) override;
26
+ std::shared_ptr<margelo::nitro::crypto::HybridHashSpec> copy(const std::optional<double> outputLength) override;
43
27
  std::vector<std::string> getSupportedHashAlgorithms() override;
44
28
 
45
- private:
29
+ private:
46
30
  // Methods
47
31
  void setParams();
48
32
 
49
- private:
33
+ private:
50
34
  // Properties
51
35
  EVP_MD_CTX* ctx = nullptr;
52
36
  const EVP_MD* md = nullptr;
@@ -0,0 +1,95 @@
1
+ #include <NitroModules/ArrayBuffer.hpp>
2
+ #include <memory>
3
+ #include <openssl/err.h>
4
+ #include <openssl/evp.h>
5
+ #include <optional>
6
+ #include <string>
7
+ #include <vector>
8
+
9
+ #include "HybridHmac.hpp"
10
+
11
+ namespace margelo::nitro::crypto {
12
+
13
+ HybridHmac::~HybridHmac() {
14
+ if (ctx) {
15
+ EVP_MAC_CTX_free(ctx);
16
+ ctx = nullptr;
17
+ }
18
+ }
19
+
20
+ void HybridHmac::createHmac(const std::string& hmacAlgorithm, const std::shared_ptr<ArrayBuffer>& secretKey) {
21
+ algorithm = hmacAlgorithm;
22
+
23
+ // Create and use EVP_MAC locally
24
+ EVP_MAC* mac = EVP_MAC_fetch(nullptr, "HMAC", nullptr);
25
+ if (!mac) {
26
+ throw std::runtime_error("Failed to fetch HMAC implementation: " + std::to_string(ERR_get_error()));
27
+ }
28
+
29
+ // Create HMAC context
30
+ ctx = EVP_MAC_CTX_new(mac);
31
+ EVP_MAC_free(mac); // Free immediately after creating the context
32
+ if (!ctx) {
33
+ throw std::runtime_error("Failed to create HMAC context: " + std::to_string(ERR_get_error()));
34
+ }
35
+
36
+ // Validate algorithm
37
+ const EVP_MD* md = EVP_get_digestbyname(algorithm.c_str());
38
+ if (!md) {
39
+ throw std::runtime_error("Unknown HMAC algorithm: " + algorithm);
40
+ }
41
+
42
+ // Set up parameters for HMAC
43
+ OSSL_PARAM params[2];
44
+ params[0] = OSSL_PARAM_construct_utf8_string("digest", const_cast<char*>(algorithm.c_str()), 0);
45
+ params[1] = OSSL_PARAM_construct_end();
46
+
47
+ const uint8_t* keyData = reinterpret_cast<const uint8_t*>(secretKey->data());
48
+ size_t keySize = secretKey->size();
49
+
50
+ // Handle empty key case by providing a dummy key
51
+ static const uint8_t dummyKey = 0;
52
+ if (keySize == 0) {
53
+ keyData = &dummyKey;
54
+ keySize = 1;
55
+ }
56
+
57
+ // Initialize HMAC
58
+ if (EVP_MAC_init(ctx, keyData, keySize, params) != 1) {
59
+ throw std::runtime_error("Failed to initialize HMAC: " + std::to_string(ERR_get_error()));
60
+ }
61
+ }
62
+
63
+ void HybridHmac::update(const std::shared_ptr<ArrayBuffer>& data) {
64
+ if (!ctx) {
65
+ throw std::runtime_error("HMAC context not initialized");
66
+ }
67
+
68
+ // Update HMAC with new data
69
+ if (EVP_MAC_update(ctx, reinterpret_cast<const uint8_t*>(data->data()), data->size()) != 1) {
70
+ throw std::runtime_error("Failed to update HMAC: " + std::to_string(ERR_get_error()));
71
+ }
72
+ }
73
+
74
+ std::shared_ptr<ArrayBuffer> HybridHmac::digest() {
75
+ if (!ctx) {
76
+ throw std::runtime_error("HMAC context not initialized");
77
+ }
78
+
79
+ // Determine the maximum possible size of the HMAC output
80
+ const EVP_MD* md = EVP_get_digestbyname(algorithm.c_str());
81
+ const size_t hmacLength = EVP_MD_get_size(md);
82
+
83
+ // Allocate buffer with the exact required size
84
+ uint8_t* hmacBuffer = new uint8_t[hmacLength];
85
+
86
+ // Finalize the HMAC computation directly into the final buffer
87
+ if (EVP_MAC_final(ctx, hmacBuffer, nullptr, hmacLength) != 1) {
88
+ delete[] hmacBuffer;
89
+ throw std::runtime_error("Failed to finalize HMAC digest: " + std::to_string(ERR_get_error()));
90
+ }
91
+
92
+ return std::make_shared<NativeArrayBuffer>(hmacBuffer, hmacLength, [=]() { delete[] hmacBuffer; });
93
+ }
94
+
95
+ } // namespace margelo::nitro::crypto