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.
- package/android/CMakeLists.txt +2 -0
- package/cpp/ed25519/HybridEdKeyPair.cpp +32 -89
- package/cpp/ed25519/HybridEdKeyPair.hpp +24 -54
- package/cpp/hash/HybridHash.cpp +30 -60
- package/cpp/hash/HybridHash.hpp +11 -27
- package/cpp/hmac/HybridHmac.cpp +95 -0
- package/cpp/hmac/HybridHmac.hpp +31 -0
- package/cpp/pbkdf2/HybridPbkdf2.cpp +34 -55
- package/cpp/pbkdf2/HybridPbkdf2.hpp +5 -16
- package/cpp/random/HybridRandom.cpp +5 -16
- package/cpp/random/HybridRandom.hpp +5 -6
- package/cpp/utils/Utils.hpp +1 -2
- package/lib/commonjs/hash.js +41 -18
- package/lib/commonjs/hash.js.map +1 -1
- package/lib/commonjs/hmac.js +109 -0
- package/lib/commonjs/hmac.js.map +1 -0
- package/lib/commonjs/index.js +13 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/specs/hmac.nitro.js +6 -0
- package/lib/commonjs/specs/hmac.nitro.js.map +1 -0
- package/lib/module/hash.js +41 -18
- package/lib/module/hash.js.map +1 -1
- package/lib/module/hmac.js +104 -0
- package/lib/module/hmac.js.map +1 -0
- package/lib/module/index.js +3 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/specs/hmac.nitro.js +4 -0
- package/lib/module/specs/hmac.nitro.js.map +1 -0
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/lib/typescript/hash.d.ts +23 -0
- package/lib/typescript/hash.d.ts.map +1 -1
- package/lib/typescript/hmac.d.ts +67 -0
- package/lib/typescript/hmac.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +2 -0
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/specs/hmac.nitro.d.ts +10 -0
- package/lib/typescript/specs/hmac.nitro.d.ts.map +1 -0
- package/nitrogen/generated/android/QuickCrypto+autolinking.cmake +1 -0
- package/nitrogen/generated/android/QuickCryptoOnLoad.cpp +10 -0
- package/nitrogen/generated/ios/QuickCryptoAutolinking.mm +10 -0
- package/nitrogen/generated/shared/c++/HybridHmacSpec.cpp +23 -0
- package/nitrogen/generated/shared/c++/HybridHmacSpec.hpp +66 -0
- package/package.json +1 -1
- package/src/hash.ts +51 -15
- package/src/hmac.ts +135 -0
- package/src/index.ts +3 -0
- package/src/specs/hmac.nitro.ts +7 -0
package/android/CMakeLists.txt
CHANGED
|
@@ -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
|
-
|
|
10
|
-
|
|
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
|
-
|
|
25
|
-
|
|
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
|
-
|
|
40
|
-
|
|
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::
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
152
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
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
|
package/cpp/hash/HybridHash.cpp
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
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[] = {
|
|
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
|
}
|
package/cpp/hash/HybridHash.hpp
CHANGED
|
@@ -11,42 +11,26 @@ namespace margelo::nitro::crypto {
|
|
|
11
11
|
|
|
12
12
|
using namespace facebook;
|
|
13
13
|
|
|
14
|
-
class HybridHash : public HybridHashSpec
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
HybridHash()
|
|
18
|
-
|
|
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
|
-
|
|
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
|