react-native-quick-crypto 1.0.0-beta.11 → 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 +4 -0
- package/cpp/ed25519/HybridEdKeyPair.cpp +32 -89
- package/cpp/ed25519/HybridEdKeyPair.hpp +24 -54
- package/cpp/hash/HybridHash.cpp +151 -0
- package/cpp/hash/HybridHash.hpp +41 -0
- 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 +168 -0
- package/lib/commonjs/hash.js.map +1 -0
- package/lib/commonjs/hmac.js +109 -0
- package/lib/commonjs/hmac.js.map +1 -0
- package/lib/commonjs/index.js +26 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/specs/hash.nitro.js +6 -0
- package/lib/commonjs/specs/hash.nitro.js.map +1 -0
- package/lib/commonjs/specs/hmac.nitro.js +6 -0
- package/lib/commonjs/specs/hmac.nitro.js.map +1 -0
- package/lib/module/hash.js +162 -0
- package/lib/module/hash.js.map +1 -0
- package/lib/module/hmac.js +104 -0
- package/lib/module/hmac.js.map +1 -0
- package/lib/module/index.js +6 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/specs/hash.nitro.js +4 -0
- package/lib/module/specs/hash.nitro.js.map +1 -0
- 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 +110 -0
- package/lib/typescript/hash.d.ts.map +1 -0
- package/lib/typescript/hmac.d.ts +67 -0
- package/lib/typescript/hmac.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +5 -0
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/specs/hash.nitro.d.ts +12 -0
- package/lib/typescript/specs/hash.nitro.d.ts.map +1 -0
- package/lib/typescript/specs/hmac.nitro.d.ts +10 -0
- package/lib/typescript/specs/hmac.nitro.d.ts.map +1 -0
- package/lib/typescript/utils/types.d.ts +4 -0
- package/lib/typescript/utils/types.d.ts.map +1 -1
- package/nitrogen/generated/android/QuickCrypto+autolinking.cmake +2 -0
- package/nitrogen/generated/android/QuickCryptoOnLoad.cpp +20 -0
- package/nitrogen/generated/ios/QuickCryptoAutolinking.mm +20 -0
- package/nitrogen/generated/shared/c++/HybridHashSpec.cpp +25 -0
- package/nitrogen/generated/shared/c++/HybridHashSpec.hpp +74 -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 +208 -0
- package/src/hmac.ts +135 -0
- package/src/index.ts +6 -0
- package/src/specs/hash.nitro.ts +9 -0
- package/src/specs/hmac.nitro.ts +7 -0
- package/src/utils/types.ts +9 -0
package/android/CMakeLists.txt
CHANGED
|
@@ -9,6 +9,8 @@ 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
|
|
13
|
+
../cpp/hash/HybridHash.cpp
|
|
12
14
|
../cpp/ed25519/HybridEdKeyPair.cpp
|
|
13
15
|
../cpp/pbkdf2/HybridPbkdf2.cpp
|
|
14
16
|
../cpp/random/HybridRandom.cpp
|
|
@@ -21,6 +23,8 @@ include(${CMAKE_SOURCE_DIR}/../nitrogen/generated/android/QuickCrypto+autolinkin
|
|
|
21
23
|
# local includes
|
|
22
24
|
include_directories(
|
|
23
25
|
"src/main/cpp"
|
|
26
|
+
"../cpp/hmac"
|
|
27
|
+
"../cpp/hash"
|
|
24
28
|
"../cpp/ed25519"
|
|
25
29
|
"../cpp/pbkdf2"
|
|
26
30
|
"../cpp/random"
|
|
@@ -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
|
|
@@ -0,0 +1,151 @@
|
|
|
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 "HybridHash.hpp"
|
|
10
|
+
|
|
11
|
+
namespace margelo::nitro::crypto {
|
|
12
|
+
|
|
13
|
+
HybridHash::~HybridHash() {
|
|
14
|
+
if (ctx) {
|
|
15
|
+
EVP_MD_CTX_free(ctx);
|
|
16
|
+
ctx = nullptr;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
void HybridHash::createHash(const std::string& hashAlgorithmArg, const std::optional<double> outputLengthArg) {
|
|
21
|
+
algorithm = hashAlgorithmArg;
|
|
22
|
+
outputLength = outputLengthArg;
|
|
23
|
+
|
|
24
|
+
// Create hash context
|
|
25
|
+
ctx = EVP_MD_CTX_new();
|
|
26
|
+
if (!ctx) {
|
|
27
|
+
throw std::runtime_error("Failed to create hash context: " + std::to_string(ERR_get_error()));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Get the message digest by name
|
|
31
|
+
md = EVP_get_digestbyname(algorithm.c_str());
|
|
32
|
+
if (!md) {
|
|
33
|
+
EVP_MD_CTX_free(ctx);
|
|
34
|
+
ctx = nullptr;
|
|
35
|
+
throw std::runtime_error("Unknown hash algorithm: " + algorithm);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Initialize the digest
|
|
39
|
+
if (EVP_DigestInit_ex(ctx, md, nullptr) != 1) {
|
|
40
|
+
EVP_MD_CTX_free(ctx);
|
|
41
|
+
ctx = nullptr;
|
|
42
|
+
throw std::runtime_error("Failed to initialize hash digest: " + std::to_string(ERR_get_error()));
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
void HybridHash::update(const std::shared_ptr<ArrayBuffer>& data) {
|
|
47
|
+
if (!ctx) {
|
|
48
|
+
throw std::runtime_error("Hash context not initialized");
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Update the digest with the data
|
|
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()));
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
std::shared_ptr<ArrayBuffer> HybridHash::digest(const std::optional<std::string>& encoding) {
|
|
58
|
+
if (!ctx) {
|
|
59
|
+
throw std::runtime_error("Hash context not initialized");
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
setParams();
|
|
63
|
+
|
|
64
|
+
// Get the default digest size
|
|
65
|
+
const size_t defaultLen = EVP_MD_CTX_size(ctx);
|
|
66
|
+
const size_t digestSize = (outputLength.has_value()) ? static_cast<int>(*outputLength) : defaultLen;
|
|
67
|
+
|
|
68
|
+
if (digestSize < 0) {
|
|
69
|
+
throw std::runtime_error("Invalid digest size: " + std::to_string(digestSize));
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Create a buffer for the hash output
|
|
73
|
+
uint8_t* hashBuffer = new uint8_t[digestSize];
|
|
74
|
+
size_t hashLength = digestSize;
|
|
75
|
+
|
|
76
|
+
// Finalize the digest
|
|
77
|
+
int ret;
|
|
78
|
+
if (digestSize == defaultLen) {
|
|
79
|
+
ret = EVP_DigestFinal_ex(ctx, hashBuffer, reinterpret_cast<unsigned int*>(&hashLength));
|
|
80
|
+
} else {
|
|
81
|
+
ret = EVP_DigestFinalXOF(ctx, hashBuffer, hashLength);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (ret != 1) {
|
|
85
|
+
delete[] hashBuffer;
|
|
86
|
+
throw std::runtime_error("Failed to finalize hash digest: " + std::to_string(ERR_get_error()));
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return std::make_shared<NativeArrayBuffer>(hashBuffer, hashLength, [=]() { delete[] hashBuffer; });
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
std::shared_ptr<margelo::nitro::crypto::HybridHashSpec> HybridHash::copy(const std::optional<double> outputLengthArg) {
|
|
93
|
+
if (!ctx) {
|
|
94
|
+
throw std::runtime_error("Hash context not initialized");
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Create a new context
|
|
98
|
+
EVP_MD_CTX* newCtx = EVP_MD_CTX_new();
|
|
99
|
+
if (!newCtx) {
|
|
100
|
+
throw std::runtime_error("Failed to create new hash context: " + std::to_string(ERR_get_error()));
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Copy the existing context to the new one
|
|
104
|
+
if (EVP_MD_CTX_copy(newCtx, ctx) != 1) {
|
|
105
|
+
EVP_MD_CTX_free(newCtx);
|
|
106
|
+
throw std::runtime_error("Failed to copy hash context: " + std::to_string(ERR_get_error()));
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return std::make_shared<HybridHash>(newCtx, md, algorithm, outputLengthArg);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
std::vector<std::string> HybridHash::getSupportedHashAlgorithms() {
|
|
113
|
+
std::vector<std::string> hashAlgorithms;
|
|
114
|
+
|
|
115
|
+
EVP_MD_do_all_provided(
|
|
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);
|
|
125
|
+
|
|
126
|
+
return hashAlgorithms;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
void HybridHash::setParams() {
|
|
130
|
+
// Handle algorithm parameters (like XOF length for SHAKE)
|
|
131
|
+
if (outputLength.has_value()) {
|
|
132
|
+
uint32_t xoflen = outputLength.value();
|
|
133
|
+
|
|
134
|
+
// Add a reasonable maximum output length
|
|
135
|
+
const int MAX_OUTPUT_LENGTH = 16 * 1024 * 1024; // 16MB
|
|
136
|
+
if (xoflen > MAX_OUTPUT_LENGTH) {
|
|
137
|
+
throw std::runtime_error("Output length " + std::to_string(xoflen) + " exceeds maximum allowed size of " +
|
|
138
|
+
std::to_string(MAX_OUTPUT_LENGTH));
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
OSSL_PARAM params[] = {OSSL_PARAM_construct_uint("xoflen", &xoflen), OSSL_PARAM_END};
|
|
142
|
+
|
|
143
|
+
if (EVP_MD_CTX_set_params(ctx, params) != 1) {
|
|
144
|
+
EVP_MD_CTX_free(ctx);
|
|
145
|
+
ctx = nullptr;
|
|
146
|
+
throw std::runtime_error("Failed to set XOF length (outputLength) parameter: " + std::to_string(ERR_get_error()));
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
} // namespace margelo::nitro::crypto
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
#include <NitroModules/ArrayBuffer.hpp>
|
|
2
|
+
#include <memory>
|
|
3
|
+
#include <openssl/evp.h>
|
|
4
|
+
#include <optional>
|
|
5
|
+
#include <string>
|
|
6
|
+
#include <vector>
|
|
7
|
+
|
|
8
|
+
#include "HybridHashSpec.hpp"
|
|
9
|
+
|
|
10
|
+
namespace margelo::nitro::crypto {
|
|
11
|
+
|
|
12
|
+
using namespace facebook;
|
|
13
|
+
|
|
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) {}
|
|
19
|
+
~HybridHash();
|
|
20
|
+
|
|
21
|
+
public:
|
|
22
|
+
// Methods
|
|
23
|
+
void createHash(const std::string& algorithm, const std::optional<double> outputLength) override;
|
|
24
|
+
void update(const std::shared_ptr<ArrayBuffer>& data) 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;
|
|
27
|
+
std::vector<std::string> getSupportedHashAlgorithms() override;
|
|
28
|
+
|
|
29
|
+
private:
|
|
30
|
+
// Methods
|
|
31
|
+
void setParams();
|
|
32
|
+
|
|
33
|
+
private:
|
|
34
|
+
// Properties
|
|
35
|
+
EVP_MD_CTX* ctx = nullptr;
|
|
36
|
+
const EVP_MD* md = nullptr;
|
|
37
|
+
std::string algorithm = "";
|
|
38
|
+
std::optional<double> outputLength = std::nullopt;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
} // namespace margelo::nitro::crypto
|
|
@@ -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
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
#include <NitroModules/ArrayBuffer.hpp>
|
|
2
|
+
#include <memory>
|
|
3
|
+
#include <openssl/evp.h>
|
|
4
|
+
#include <optional>
|
|
5
|
+
#include <string>
|
|
6
|
+
#include <vector>
|
|
7
|
+
|
|
8
|
+
#include "HybridHmacSpec.hpp"
|
|
9
|
+
|
|
10
|
+
namespace margelo::nitro::crypto {
|
|
11
|
+
|
|
12
|
+
using namespace facebook;
|
|
13
|
+
|
|
14
|
+
class HybridHmac : public HybridHmacSpec {
|
|
15
|
+
public:
|
|
16
|
+
HybridHmac() : HybridObject(TAG) {}
|
|
17
|
+
~HybridHmac();
|
|
18
|
+
|
|
19
|
+
public:
|
|
20
|
+
// Methods
|
|
21
|
+
void createHmac(const std::string& algorithm, const std::shared_ptr<ArrayBuffer>& key) override;
|
|
22
|
+
void update(const std::shared_ptr<ArrayBuffer>& data) override;
|
|
23
|
+
std::shared_ptr<ArrayBuffer> digest() override;
|
|
24
|
+
|
|
25
|
+
private:
|
|
26
|
+
// Properties
|
|
27
|
+
EVP_MAC_CTX* ctx = nullptr;
|
|
28
|
+
std::string algorithm = "";
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
} // namespace margelo::nitro::crypto
|