react-native-quick-crypto 1.0.0-beta.4 → 1.0.0-beta.6
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 -4
- package/android/build.gradle +33 -4
- package/cpp/ed25519/HybridEdKeyPair.cpp +233 -0
- package/cpp/ed25519/HybridEdKeyPair.hpp +72 -0
- package/cpp/pbkdf2/HybridPbkdf2.cpp +6 -5
- package/cpp/pbkdf2/HybridPbkdf2.hpp +4 -4
- package/cpp/random/HybridRandom.cpp +6 -5
- package/cpp/random/HybridRandom.hpp +8 -4
- package/lib/commonjs/ed.js +38 -0
- package/lib/commonjs/ed.js.map +1 -0
- package/lib/commonjs/index.js +15 -5
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/keys/classes.js +191 -0
- package/lib/commonjs/keys/classes.js.map +1 -0
- package/lib/commonjs/keys/generateKeyPair.js +148 -0
- package/lib/commonjs/keys/generateKeyPair.js.map +1 -0
- package/lib/commonjs/keys/index.js +48 -72
- package/lib/commonjs/keys/index.js.map +1 -1
- package/lib/commonjs/keys/signVerify.js +41 -0
- package/lib/commonjs/keys/signVerify.js.map +1 -0
- package/lib/commonjs/keys/utils.js +118 -0
- package/lib/commonjs/keys/utils.js.map +1 -0
- package/lib/commonjs/specs/edKeyPair.nitro.js +6 -0
- package/lib/commonjs/specs/edKeyPair.nitro.js.map +1 -0
- package/lib/commonjs/utils/conversion.js +2 -0
- package/lib/commonjs/utils/conversion.js.map +1 -1
- package/lib/commonjs/utils/index.js +11 -0
- package/lib/commonjs/utils/index.js.map +1 -1
- package/lib/commonjs/utils/types.js +12 -1
- package/lib/commonjs/utils/types.js.map +1 -1
- package/lib/commonjs/utils/validation.js +25 -0
- package/lib/commonjs/utils/validation.js.map +1 -0
- package/lib/module/ed.js +33 -0
- package/lib/module/ed.js.map +1 -0
- package/lib/module/index.js +5 -5
- package/lib/module/index.js.map +1 -1
- package/lib/module/keys/classes.js +182 -0
- package/lib/module/keys/classes.js.map +1 -0
- package/lib/module/keys/generateKeyPair.js +148 -0
- package/lib/module/keys/generateKeyPair.js.map +1 -0
- package/lib/module/keys/index.js +25 -77
- package/lib/module/keys/index.js.map +1 -1
- package/lib/module/keys/signVerify.js +41 -0
- package/lib/module/keys/signVerify.js.map +1 -0
- package/lib/module/keys/utils.js +110 -0
- package/lib/module/keys/utils.js.map +1 -0
- package/lib/module/specs/edKeyPair.nitro.js +4 -0
- package/lib/module/specs/edKeyPair.nitro.js.map +1 -0
- package/lib/module/utils/conversion.js +1 -0
- package/lib/module/utils/conversion.js.map +1 -1
- package/lib/module/utils/index.js +1 -0
- package/lib/module/utils/index.js.map +1 -1
- package/lib/module/utils/types.js +14 -0
- package/lib/module/utils/types.js.map +1 -1
- package/lib/module/utils/validation.js +19 -0
- package/lib/module/utils/validation.js.map +1 -0
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/lib/typescript/ed.d.ts +16 -0
- package/lib/typescript/ed.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +27 -5
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/keys/classes.d.ts +38 -0
- package/lib/typescript/keys/classes.d.ts.map +1 -0
- package/lib/typescript/keys/generateKeyPair.d.ts +1 -0
- package/lib/typescript/keys/generateKeyPair.d.ts.map +1 -0
- package/lib/typescript/keys/index.d.ts +3 -21
- package/lib/typescript/keys/index.d.ts.map +1 -1
- package/lib/typescript/keys/signVerify.d.ts +1 -0
- package/lib/typescript/keys/signVerify.d.ts.map +1 -0
- package/lib/typescript/keys/utils.d.ts +32 -0
- package/lib/typescript/keys/utils.d.ts.map +1 -0
- package/lib/typescript/specs/edKeyPair.nitro.d.ts +15 -0
- package/lib/typescript/specs/edKeyPair.nitro.d.ts.map +1 -0
- package/lib/typescript/utils/conversion.d.ts +1 -0
- package/lib/typescript/utils/conversion.d.ts.map +1 -1
- package/lib/typescript/utils/index.d.ts +1 -0
- package/lib/typescript/utils/index.d.ts.map +1 -1
- package/lib/typescript/utils/types.d.ts +60 -4
- package/lib/typescript/utils/types.d.ts.map +1 -1
- package/lib/typescript/utils/validation.d.ts +8 -0
- package/lib/typescript/utils/validation.d.ts.map +1 -0
- package/nitrogen/generated/android/QuickCrypto+autolinking.cmake +1 -0
- package/nitrogen/generated/android/QuickCrypto+autolinking.gradle +2 -0
- package/nitrogen/generated/android/QuickCryptoOnLoad.cpp +10 -0
- package/nitrogen/generated/ios/QuickCrypto+autolinking.rb +1 -1
- package/nitrogen/generated/ios/QuickCrypto-Swift-Cxx-Umbrella.hpp +4 -1
- package/nitrogen/generated/ios/QuickCryptoAutolinking.mm +10 -0
- package/nitrogen/generated/shared/c++/{AsymmetricKeyType.hpp → CFRGKeyPairType.hpp} +25 -25
- package/nitrogen/generated/shared/c++/HybridEdKeyPairSpec.cpp +28 -0
- package/nitrogen/generated/shared/c++/HybridEdKeyPairSpec.hpp +73 -0
- package/nitrogen/generated/shared/c++/HybridKeyObjectHandleSpec.hpp +4 -4
- package/nitrogen/generated/shared/c++/HybridPbkdf2Spec.hpp +2 -2
- package/nitrogen/generated/shared/c++/HybridRandomSpec.hpp +2 -2
- package/package.json +25 -21
- package/src/ed.ts +58 -0
- package/src/index.ts +5 -5
- package/src/keys/classes.ts +211 -0
- package/src/keys/generateKeyPair.ts +146 -0
- package/src/keys/index.ts +42 -99
- package/src/keys/signVerify.ts +39 -0
- package/src/keys/utils.ts +184 -0
- package/src/specs/edKeyPair.nitro.ts +32 -0
- package/src/utils/conversion.ts +2 -0
- package/src/utils/index.ts +1 -0
- package/src/utils/types.ts +84 -4
- package/src/utils/validation.ts +35 -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/ed25519/HybridEdKeyPair.cpp
|
|
12
13
|
../cpp/pbkdf2/HybridPbkdf2.cpp
|
|
13
14
|
../cpp/random/HybridRandom.cpp
|
|
14
15
|
../deps/fastpbkdf2/fastpbkdf2.c
|
|
@@ -20,6 +21,7 @@ include(${CMAKE_SOURCE_DIR}/../nitrogen/generated/android/QuickCrypto+autolinkin
|
|
|
20
21
|
# local includes
|
|
21
22
|
include_directories(
|
|
22
23
|
"src/main/cpp"
|
|
24
|
+
"../cpp/ed25519"
|
|
23
25
|
"../cpp/pbkdf2"
|
|
24
26
|
"../cpp/random"
|
|
25
27
|
"../cpp/utils"
|
|
@@ -29,8 +31,6 @@ include_directories(
|
|
|
29
31
|
# Third party libraries (Prefabs)
|
|
30
32
|
find_library(LOG_LIB log)
|
|
31
33
|
|
|
32
|
-
find_package(ReactAndroid REQUIRED CONFIG)
|
|
33
|
-
find_package(fbjni REQUIRED CONFIG)
|
|
34
34
|
find_package(openssl REQUIRED CONFIG)
|
|
35
35
|
|
|
36
36
|
# Link all libraries together
|
|
@@ -38,9 +38,7 @@ target_link_libraries(
|
|
|
38
38
|
${PACKAGE_NAME}
|
|
39
39
|
${LOG_LIB} # <-- Logcat logger
|
|
40
40
|
android # <-- Android core
|
|
41
|
-
fbjni::fbjni # <-- Facebook C++ JNI helpers
|
|
42
41
|
openssl::crypto # <-- OpenSSL (Crypto)
|
|
43
|
-
ReactAndroid::jsi
|
|
44
42
|
)
|
|
45
43
|
|
|
46
44
|
if(ReactAndroid_VERSION_MINOR GREATER_EQUAL 76)
|
package/android/build.gradle
CHANGED
|
@@ -7,7 +7,7 @@ buildscript {
|
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
dependencies {
|
|
10
|
-
classpath "com.android.tools.build:gradle:8.
|
|
10
|
+
classpath "com.android.tools.build:gradle:8.7.3"
|
|
11
11
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlinVersion}"
|
|
12
12
|
}
|
|
13
13
|
}
|
|
@@ -49,9 +49,18 @@ android {
|
|
|
49
49
|
|
|
50
50
|
externalNativeBuild {
|
|
51
51
|
cmake {
|
|
52
|
-
cppFlags "-
|
|
52
|
+
cppFlags "-frtti -fexceptions -Wall -fstack-protector-all"
|
|
53
53
|
arguments "-DANDROID_STL=c++_shared"
|
|
54
54
|
abiFilters (*reactNativeArchitectures())
|
|
55
|
+
|
|
56
|
+
buildTypes {
|
|
57
|
+
debug {
|
|
58
|
+
cppFlags "-O1 -g"
|
|
59
|
+
}
|
|
60
|
+
release {
|
|
61
|
+
cppFlags "-O2"
|
|
62
|
+
}
|
|
63
|
+
}
|
|
55
64
|
}
|
|
56
65
|
}
|
|
57
66
|
}
|
|
@@ -67,6 +76,27 @@ android {
|
|
|
67
76
|
prefab true
|
|
68
77
|
}
|
|
69
78
|
|
|
79
|
+
packagingOptions {
|
|
80
|
+
excludes = [
|
|
81
|
+
"META-INF",
|
|
82
|
+
"META-INF/**",
|
|
83
|
+
"**/libc++_shared.so",
|
|
84
|
+
"**/libfbjni.so",
|
|
85
|
+
"**/libjsi.so",
|
|
86
|
+
"**/libfolly_json.so",
|
|
87
|
+
"**/libfolly_runtime.so",
|
|
88
|
+
"**/libglog.so",
|
|
89
|
+
"**/libhermes.so",
|
|
90
|
+
"**/libhermes-executor-debug.so",
|
|
91
|
+
"**/libhermes_executor.so",
|
|
92
|
+
"**/libreactnative.so",
|
|
93
|
+
"**/libreactnativejni.so",
|
|
94
|
+
"**/libturbomodulejsijni.so",
|
|
95
|
+
"**/libreact_nativemodule_core.so",
|
|
96
|
+
"**/libjscexecutor.so"
|
|
97
|
+
]
|
|
98
|
+
}
|
|
99
|
+
|
|
70
100
|
buildTypes {
|
|
71
101
|
release {
|
|
72
102
|
minifyEnabled false
|
|
@@ -108,8 +138,7 @@ dependencies {
|
|
|
108
138
|
implementation project(":react-native-nitro-modules")
|
|
109
139
|
|
|
110
140
|
// Add a dependency on OpenSSL
|
|
111
|
-
|
|
112
|
-
implementation "com.android.ndk.thirdparty:openssl:1.1.1q-beta-1"
|
|
141
|
+
implementation 'io.github.ronickg:openssl:3.3.2'
|
|
113
142
|
}
|
|
114
143
|
|
|
115
144
|
if (isNewArchitectureEnabled()) {
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
#include "HybridEdKeyPair.hpp"
|
|
2
|
+
|
|
3
|
+
#include <memory>
|
|
4
|
+
#include <string>
|
|
5
|
+
|
|
6
|
+
namespace margelo::nitro::crypto {
|
|
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
|
+
) {
|
|
17
|
+
// get owned NativeArrayBuffers before passing to sync function
|
|
18
|
+
std::optional<std::shared_ptr<ArrayBuffer>> nativePassphrase = std::nullopt;
|
|
19
|
+
if (passphrase.has_value()) {
|
|
20
|
+
nativePassphrase = ToNativeArrayBuffer(passphrase.value());
|
|
21
|
+
}
|
|
22
|
+
|
|
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
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
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
|
+
) {
|
|
47
|
+
EVP_PKEY_CTX* pctx;
|
|
48
|
+
|
|
49
|
+
// key context
|
|
50
|
+
pctx = EVP_PKEY_CTX_new_from_name(nullptr, this->curve.c_str(), nullptr);
|
|
51
|
+
if (pctx == nullptr) {
|
|
52
|
+
throw std::runtime_error("Invalid curve name: " + this->curve);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// keygen init
|
|
56
|
+
if (EVP_PKEY_keygen_init(pctx) <= 0) {
|
|
57
|
+
EVP_PKEY_CTX_free(pctx);
|
|
58
|
+
throw std::runtime_error("Failed to initialize keygen");
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// generate key
|
|
62
|
+
EVP_PKEY_keygen(pctx, &this->pkey);
|
|
63
|
+
if (this->pkey == nullptr) {
|
|
64
|
+
EVP_PKEY_CTX_free(pctx);
|
|
65
|
+
throw std::runtime_error("Failed to generate key");
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// cleanup
|
|
69
|
+
EVP_PKEY_CTX_free(pctx);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
std::shared_ptr<Promise<std::shared_ptr<ArrayBuffer>>>
|
|
74
|
+
HybridEdKeyPair::sign(
|
|
75
|
+
const std::shared_ptr<ArrayBuffer>& message
|
|
76
|
+
) {
|
|
77
|
+
// get owned NativeArrayBuffer before passing to sync function
|
|
78
|
+
auto nativeMessage = ToNativeArrayBuffer(message);
|
|
79
|
+
|
|
80
|
+
return Promise<std::shared_ptr<ArrayBuffer>>::async([this, nativeMessage]() {
|
|
81
|
+
return this->signSync(nativeMessage);
|
|
82
|
+
}
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
std::shared_ptr<ArrayBuffer>
|
|
87
|
+
HybridEdKeyPair::signSync(
|
|
88
|
+
const std::shared_ptr<ArrayBuffer>& message
|
|
89
|
+
) {
|
|
90
|
+
this->checkKeyPair();
|
|
91
|
+
|
|
92
|
+
size_t sig_len = 0;
|
|
93
|
+
uint8_t* sig = NULL;
|
|
94
|
+
EVP_MD_CTX* md_ctx = nullptr;
|
|
95
|
+
EVP_PKEY_CTX* pkey_ctx = nullptr;
|
|
96
|
+
|
|
97
|
+
// key context
|
|
98
|
+
md_ctx = EVP_MD_CTX_new();
|
|
99
|
+
if (md_ctx == nullptr) {
|
|
100
|
+
EVP_MD_CTX_free(md_ctx);
|
|
101
|
+
throw std::runtime_error("Error creating signing context");
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
pkey_ctx = EVP_PKEY_CTX_new_from_name(nullptr, this->curve.c_str(), nullptr);
|
|
105
|
+
if (pkey_ctx == nullptr) {
|
|
106
|
+
EVP_PKEY_CTX_free(pkey_ctx);
|
|
107
|
+
throw std::runtime_error("Error creating signing context: " + this->curve);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (EVP_DigestSignInit(md_ctx, &pkey_ctx, NULL, NULL, this->pkey) <= 0) {
|
|
111
|
+
EVP_MD_CTX_free(md_ctx);
|
|
112
|
+
char* err = ERR_error_string(ERR_get_error(), NULL);
|
|
113
|
+
throw std::runtime_error("Failed to initialize signing: " + std::string(err));
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Calculate the required size for the signature by passing a NULL buffer.
|
|
117
|
+
if (EVP_DigestSign(md_ctx, NULL, &sig_len, message.get()->data(), message.get()->size()) <= 0) {
|
|
118
|
+
EVP_MD_CTX_free(md_ctx);
|
|
119
|
+
throw std::runtime_error("Failed to calculate signature size");
|
|
120
|
+
}
|
|
121
|
+
sig = new uint8_t[sig_len];
|
|
122
|
+
|
|
123
|
+
// Actually calculate the signature
|
|
124
|
+
if (EVP_DigestSign(md_ctx, sig, &sig_len, message.get()->data(), message.get()->size()) <= 0) {
|
|
125
|
+
EVP_MD_CTX_free(md_ctx);
|
|
126
|
+
throw std::runtime_error("Failed to calculate signature");
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// return value for JS
|
|
130
|
+
std::shared_ptr<ArrayBuffer> signature = std::make_shared<NativeArrayBuffer>(
|
|
131
|
+
sig,
|
|
132
|
+
sig_len,
|
|
133
|
+
[=]() { delete[] sig; }
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
// Clean up
|
|
137
|
+
EVP_MD_CTX_free(md_ctx);
|
|
138
|
+
|
|
139
|
+
return signature;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
std::shared_ptr<Promise<bool>>
|
|
143
|
+
HybridEdKeyPair::verify(
|
|
144
|
+
const std::shared_ptr<ArrayBuffer>& signature,
|
|
145
|
+
const std::shared_ptr<ArrayBuffer>& message
|
|
146
|
+
) {
|
|
147
|
+
// get owned NativeArrayBuffers before passing to sync function
|
|
148
|
+
auto nativeSignature = ToNativeArrayBuffer(signature);
|
|
149
|
+
auto nativeMessage = ToNativeArrayBuffer(message);
|
|
150
|
+
|
|
151
|
+
return Promise<bool>::async([this, nativeSignature, nativeMessage]() {
|
|
152
|
+
return this->verifySync(nativeSignature, nativeMessage);
|
|
153
|
+
}
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
bool
|
|
158
|
+
HybridEdKeyPair::verifySync(
|
|
159
|
+
const std::shared_ptr<ArrayBuffer>& signature,
|
|
160
|
+
const std::shared_ptr<ArrayBuffer>& message
|
|
161
|
+
) {
|
|
162
|
+
this->checkKeyPair();
|
|
163
|
+
|
|
164
|
+
EVP_MD_CTX* md_ctx = nullptr;
|
|
165
|
+
EVP_PKEY_CTX* pkey_ctx = nullptr;
|
|
166
|
+
|
|
167
|
+
// key context
|
|
168
|
+
md_ctx = EVP_MD_CTX_new();
|
|
169
|
+
if (md_ctx == nullptr) {
|
|
170
|
+
EVP_MD_CTX_free(md_ctx);
|
|
171
|
+
throw std::runtime_error("Error creating verify context");
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
pkey_ctx = EVP_PKEY_CTX_new_from_name(nullptr, this->curve.c_str(), nullptr);
|
|
175
|
+
if (pkey_ctx == nullptr) {
|
|
176
|
+
EVP_PKEY_CTX_free(pkey_ctx);
|
|
177
|
+
throw std::runtime_error("Error creating verify context: " + this->curve);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
if (EVP_DigestVerifyInit(md_ctx, &pkey_ctx, NULL, NULL, this->pkey) <= 0) {
|
|
181
|
+
EVP_MD_CTX_free(md_ctx);
|
|
182
|
+
char* err = ERR_error_string(ERR_get_error(), NULL);
|
|
183
|
+
throw std::runtime_error("Failed to initialize verify: " + std::string(err));
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// verify
|
|
187
|
+
auto res = EVP_DigestVerify(
|
|
188
|
+
md_ctx,
|
|
189
|
+
signature.get()->data(), signature.get()->size(),
|
|
190
|
+
message.get()->data(), message.get()->size()
|
|
191
|
+
);
|
|
192
|
+
|
|
193
|
+
//return value for JS
|
|
194
|
+
if (res < 0) {
|
|
195
|
+
EVP_MD_CTX_free(md_ctx);
|
|
196
|
+
throw std::runtime_error("Failed to verify");
|
|
197
|
+
}
|
|
198
|
+
return res == 1; // true if 1, false if 0
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
std::shared_ptr<ArrayBuffer>
|
|
202
|
+
HybridEdKeyPair::getPublicKey() {
|
|
203
|
+
this->checkKeyPair();
|
|
204
|
+
size_t len = 32;
|
|
205
|
+
uint8_t* publ = new uint8_t[len];
|
|
206
|
+
EVP_PKEY_get_raw_public_key(this->pkey, publ, &len);
|
|
207
|
+
|
|
208
|
+
return std::make_shared<NativeArrayBuffer>(publ, len, [=]() { delete[] publ; });
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
std::shared_ptr<ArrayBuffer>
|
|
212
|
+
HybridEdKeyPair::getPrivateKey() {
|
|
213
|
+
this->checkKeyPair();
|
|
214
|
+
size_t len = 32;
|
|
215
|
+
uint8_t* priv = new uint8_t[len];
|
|
216
|
+
EVP_PKEY_get_raw_private_key(this->pkey, priv, &len);
|
|
217
|
+
|
|
218
|
+
return std::make_shared<NativeArrayBuffer>(priv, len, [=]() { delete[] priv; });
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
void
|
|
222
|
+
HybridEdKeyPair::checkKeyPair() {
|
|
223
|
+
if (this->pkey == nullptr) {
|
|
224
|
+
throw std::runtime_error("Keypair not initialized");
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
void
|
|
229
|
+
HybridEdKeyPair::setCurve(const std::string& curve) {
|
|
230
|
+
this->curve = curve;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
} // namespace margelo::nitro::crypto
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
#include <openssl/evp.h>
|
|
2
|
+
#include <openssl/err.h>
|
|
3
|
+
#include <memory>
|
|
4
|
+
#include <string>
|
|
5
|
+
|
|
6
|
+
#include "HybridEdKeyPairSpec.hpp"
|
|
7
|
+
#include "Utils.hpp"
|
|
8
|
+
|
|
9
|
+
namespace margelo::nitro::crypto {
|
|
10
|
+
|
|
11
|
+
using namespace facebook;
|
|
12
|
+
|
|
13
|
+
class HybridEdKeyPair : public HybridEdKeyPairSpec {
|
|
14
|
+
public:
|
|
15
|
+
HybridEdKeyPair() : HybridObject(TAG) {}
|
|
16
|
+
|
|
17
|
+
public:
|
|
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(const std::shared_ptr<ArrayBuffer>& message) override;
|
|
41
|
+
|
|
42
|
+
std::shared_ptr<ArrayBuffer>
|
|
43
|
+
signSync(const std::shared_ptr<ArrayBuffer>& message) override;
|
|
44
|
+
|
|
45
|
+
std::shared_ptr<Promise<bool>>
|
|
46
|
+
verify(
|
|
47
|
+
const std::shared_ptr<ArrayBuffer>& signature,
|
|
48
|
+
const std::shared_ptr<ArrayBuffer>& message
|
|
49
|
+
) override;
|
|
50
|
+
|
|
51
|
+
bool
|
|
52
|
+
verifySync(
|
|
53
|
+
const std::shared_ptr<ArrayBuffer>& signature,
|
|
54
|
+
const std::shared_ptr<ArrayBuffer>& message
|
|
55
|
+
) override;
|
|
56
|
+
|
|
57
|
+
protected:
|
|
58
|
+
std::shared_ptr<ArrayBuffer>
|
|
59
|
+
getPublicKey() override;
|
|
60
|
+
|
|
61
|
+
std::shared_ptr<ArrayBuffer> getPrivateKey();
|
|
62
|
+
|
|
63
|
+
void checkKeyPair();
|
|
64
|
+
|
|
65
|
+
void setCurve(const std::string& curve);
|
|
66
|
+
|
|
67
|
+
private:
|
|
68
|
+
std::string curve;
|
|
69
|
+
EVP_PKEY* pkey = nullptr;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
} // namespace margelo::nitro::crypto
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
namespace margelo::nitro::crypto {
|
|
5
5
|
|
|
6
|
-
std::
|
|
6
|
+
std::shared_ptr<Promise<std::shared_ptr<ArrayBuffer>>>
|
|
7
7
|
HybridPbkdf2::pbkdf2(
|
|
8
8
|
const std::shared_ptr<ArrayBuffer>& password,
|
|
9
9
|
const std::shared_ptr<ArrayBuffer>& salt,
|
|
@@ -15,10 +15,11 @@ HybridPbkdf2::pbkdf2(
|
|
|
15
15
|
auto nativePassword = ToNativeArrayBuffer(password);
|
|
16
16
|
auto nativeSalt = ToNativeArrayBuffer(salt);
|
|
17
17
|
|
|
18
|
-
return std::async(
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
return Promise<std::shared_ptr<ArrayBuffer>>::async(
|
|
19
|
+
[this, nativePassword, nativeSalt, iterations, keylen, digest]() {
|
|
20
|
+
return this->pbkdf2Sync(nativePassword, nativeSalt, iterations, keylen, digest);
|
|
21
|
+
}
|
|
22
|
+
);
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
std::shared_ptr<ArrayBuffer>
|
|
@@ -8,12 +8,12 @@ namespace margelo::nitro::crypto {
|
|
|
8
8
|
using namespace facebook;
|
|
9
9
|
|
|
10
10
|
class HybridPbkdf2 : public HybridPbkdf2Spec {
|
|
11
|
-
public:
|
|
11
|
+
public:
|
|
12
12
|
HybridPbkdf2() : HybridObject(TAG) {}
|
|
13
13
|
|
|
14
|
-
public:
|
|
14
|
+
public:
|
|
15
15
|
// Methods
|
|
16
|
-
|
|
16
|
+
std::shared_ptr<Promise<std::shared_ptr<ArrayBuffer>>>
|
|
17
17
|
pbkdf2(
|
|
18
18
|
const std::shared_ptr<ArrayBuffer>& password,
|
|
19
19
|
const std::shared_ptr<ArrayBuffer>& salt,
|
|
@@ -22,7 +22,7 @@ public:
|
|
|
22
22
|
const std::string& digest
|
|
23
23
|
) override;
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
std::shared_ptr<ArrayBuffer>
|
|
26
26
|
pbkdf2Sync(
|
|
27
27
|
const std::shared_ptr<ArrayBuffer>& password,
|
|
28
28
|
const std::shared_ptr<ArrayBuffer>& salt,
|
|
@@ -28,17 +28,18 @@ size_t checkOffset(double size, double offset) {
|
|
|
28
28
|
|
|
29
29
|
namespace margelo::nitro::crypto {
|
|
30
30
|
|
|
31
|
-
std::
|
|
31
|
+
std::shared_ptr<Promise<std::shared_ptr<ArrayBuffer>>>
|
|
32
32
|
HybridRandom::randomFill(const std::shared_ptr<ArrayBuffer>& buffer,
|
|
33
33
|
double dOffset,
|
|
34
34
|
double dSize) {
|
|
35
35
|
// get owned NativeArrayBuffer before passing to sync function
|
|
36
36
|
auto nativeBuffer = ToNativeArrayBuffer(buffer);
|
|
37
37
|
|
|
38
|
-
return std::async(
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
38
|
+
return Promise<std::shared_ptr<ArrayBuffer>>::async(
|
|
39
|
+
[this, nativeBuffer, dOffset, dSize]() {
|
|
40
|
+
return this->randomFillSync(nativeBuffer, dOffset, dSize);
|
|
41
|
+
}
|
|
42
|
+
);
|
|
42
43
|
};
|
|
43
44
|
|
|
44
45
|
std::shared_ptr<ArrayBuffer>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#include <cmath>
|
|
2
2
|
#include <future>
|
|
3
|
+
#include <memory>
|
|
3
4
|
#include <iostream>
|
|
4
5
|
|
|
5
6
|
#include "HybridRandomSpec.hpp"
|
|
@@ -9,13 +10,16 @@ namespace margelo::nitro::crypto {
|
|
|
9
10
|
using namespace facebook;
|
|
10
11
|
|
|
11
12
|
class HybridRandom : public HybridRandomSpec {
|
|
12
|
-
public:
|
|
13
|
+
public:
|
|
13
14
|
HybridRandom() : HybridObject(TAG) {}
|
|
14
15
|
|
|
15
|
-
public:
|
|
16
|
+
public:
|
|
16
17
|
// Methods
|
|
17
|
-
std::
|
|
18
|
-
|
|
18
|
+
std::shared_ptr<Promise<std::shared_ptr<ArrayBuffer>>>
|
|
19
|
+
randomFill(const std::shared_ptr<ArrayBuffer>& buffer, double dOffset, double dSize) override;
|
|
20
|
+
|
|
21
|
+
std::shared_ptr<ArrayBuffer>
|
|
22
|
+
randomFillSync(const std::shared_ptr<ArrayBuffer>& buffer, double dOffset, double dSize) override;
|
|
19
23
|
};
|
|
20
24
|
|
|
21
25
|
inline void printData(std::string name, uint8_t* data, size_t size) {
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.Ed = void 0;
|
|
7
|
+
var _reactNativeNitroModules = require("react-native-nitro-modules");
|
|
8
|
+
class Ed {
|
|
9
|
+
constructor(type, config) {
|
|
10
|
+
this.type = type;
|
|
11
|
+
this.config = config;
|
|
12
|
+
this.native = _reactNativeNitroModules.NitroModules.createHybridObject('EdKeyPair');
|
|
13
|
+
this.native.setCurve(type);
|
|
14
|
+
}
|
|
15
|
+
async generateKeyPair() {
|
|
16
|
+
this.native.generateKeyPair(this.config.publicFormat || -1, this.config.publicType || -1, this.config.privateFormat || -1, this.config.privateType || -1, this.config.cipher, this.config.passphrase);
|
|
17
|
+
}
|
|
18
|
+
generateKeyPairSync() {
|
|
19
|
+
this.native.generateKeyPairSync(this.config.publicFormat || -1, this.config.publicType || -1, this.config.privateFormat || -1, this.config.privateType || -1, this.config.cipher, this.config.passphrase);
|
|
20
|
+
}
|
|
21
|
+
getPublicKey() {
|
|
22
|
+
return this.native.getPublicKey();
|
|
23
|
+
}
|
|
24
|
+
async sign(message) {
|
|
25
|
+
return this.native.sign(message);
|
|
26
|
+
}
|
|
27
|
+
signSync(message) {
|
|
28
|
+
return this.native.signSync(message);
|
|
29
|
+
}
|
|
30
|
+
async verify(signature, message) {
|
|
31
|
+
return this.native.verify(signature, message);
|
|
32
|
+
}
|
|
33
|
+
verifySync(signature, message) {
|
|
34
|
+
return this.native.verifySync(signature, message);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
exports.Ed = Ed;
|
|
38
|
+
//# sourceMappingURL=ed.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["_reactNativeNitroModules","require","Ed","constructor","type","config","native","NitroModules","createHybridObject","setCurve","generateKeyPair","publicFormat","publicType","privateFormat","privateType","cipher","passphrase","generateKeyPairSync","getPublicKey","sign","message","signSync","verify","signature","verifySync","exports"],"sourceRoot":"../../src","sources":["ed.ts"],"mappings":";;;;;;AAAA,IAAAA,wBAAA,GAAAC,OAAA;AAIO,MAAMC,EAAE,CAAC;EAKdC,WAAWA,CAACC,IAAqB,EAAEC,MAAwB,EAAE;IAC3D,IAAI,CAACD,IAAI,GAAGA,IAAI;IAChB,IAAI,CAACC,MAAM,GAAGA,MAAM;IACpB,IAAI,CAACC,MAAM,GAAGC,qCAAY,CAACC,kBAAkB,CAAY,WAAW,CAAC;IACrE,IAAI,CAACF,MAAM,CAACG,QAAQ,CAACL,IAAI,CAAC;EAC5B;EAEA,MAAMM,eAAeA,CAAA,EAAkB;IACrC,IAAI,CAACJ,MAAM,CAACI,eAAe,CACzB,IAAI,CAACL,MAAM,CAACM,YAAY,IAAK,CAAC,CAAY,EAC1C,IAAI,CAACN,MAAM,CAACO,UAAU,IAAK,CAAC,CAAY,EACxC,IAAI,CAACP,MAAM,CAACQ,aAAa,IAAK,CAAC,CAAY,EAC3C,IAAI,CAACR,MAAM,CAACS,WAAW,IAAK,CAAC,CAAY,EACzC,IAAI,CAACT,MAAM,CAACU,MAAM,EAClB,IAAI,CAACV,MAAM,CAACW,UACd,CAAC;EACH;EAEAC,mBAAmBA,CAAA,EAAS;IAC1B,IAAI,CAACX,MAAM,CAACW,mBAAmB,CAC7B,IAAI,CAACZ,MAAM,CAACM,YAAY,IAAK,CAAC,CAAY,EAC1C,IAAI,CAACN,MAAM,CAACO,UAAU,IAAK,CAAC,CAAY,EACxC,IAAI,CAACP,MAAM,CAACQ,aAAa,IAAK,CAAC,CAAY,EAC3C,IAAI,CAACR,MAAM,CAACS,WAAW,IAAK,CAAC,CAAY,EACzC,IAAI,CAACT,MAAM,CAACU,MAAM,EAClB,IAAI,CAACV,MAAM,CAACW,UACd,CAAC;EACH;EAEAE,YAAYA,CAAA,EAAgB;IAC1B,OAAO,IAAI,CAACZ,MAAM,CAACY,YAAY,CAAC,CAAC;EACnC;EAEA,MAAMC,IAAIA,CAACC,OAAoB,EAAwB;IACrD,OAAO,IAAI,CAACd,MAAM,CAACa,IAAI,CAACC,OAAO,CAAC;EAClC;EAEAC,QAAQA,CAACD,OAAoB,EAAe;IAC1C,OAAO,IAAI,CAACd,MAAM,CAACe,QAAQ,CAACD,OAAO,CAAC;EACtC;EAEA,MAAME,MAAMA,CAACC,SAAsB,EAAEH,OAAoB,EAAoB;IAC3E,OAAO,IAAI,CAACd,MAAM,CAACgB,MAAM,CAACC,SAAS,EAAEH,OAAO,CAAC;EAC/C;EAEAI,UAAUA,CAACD,SAAsB,EAAEH,OAAoB,EAAW;IAChE,OAAO,IAAI,CAACd,MAAM,CAACkB,UAAU,CAACD,SAAS,EAAEH,OAAO,CAAC;EACnD;AACF;AAACK,OAAA,CAAAvB,EAAA,GAAAA,EAAA","ignoreList":[]}
|
package/lib/commonjs/index.js
CHANGED
|
@@ -8,6 +8,19 @@ var _exportNames = {
|
|
|
8
8
|
};
|
|
9
9
|
exports.install = exports.default = void 0;
|
|
10
10
|
var _reactNativeBuffer = require("@craftzdog/react-native-buffer");
|
|
11
|
+
var keys = _interopRequireWildcard(require("./keys"));
|
|
12
|
+
var ed = _interopRequireWildcard(require("./ed"));
|
|
13
|
+
Object.keys(ed).forEach(function (key) {
|
|
14
|
+
if (key === "default" || key === "__esModule") return;
|
|
15
|
+
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
|
|
16
|
+
if (key in exports && exports[key] === ed[key]) return;
|
|
17
|
+
Object.defineProperty(exports, key, {
|
|
18
|
+
enumerable: true,
|
|
19
|
+
get: function () {
|
|
20
|
+
return ed[key];
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
});
|
|
11
24
|
var pbkdf2 = _interopRequireWildcard(require("./pbkdf2"));
|
|
12
25
|
var random = _interopRequireWildcard(require("./random"));
|
|
13
26
|
var utils = _interopRequireWildcard(require("./utils"));
|
|
@@ -43,20 +56,17 @@ const QuickCrypto = {
|
|
|
43
56
|
// createCipheriv,
|
|
44
57
|
// createDecipher,
|
|
45
58
|
// createDecipheriv,
|
|
46
|
-
// createPublicKey,
|
|
47
|
-
// createPrivateKey,
|
|
48
|
-
// createSecretKey,
|
|
49
59
|
// publicEncrypt,
|
|
50
60
|
// publicDecrypt,
|
|
51
61
|
// privateDecrypt,
|
|
52
62
|
// generateKey,
|
|
53
|
-
// generateKeyPair,
|
|
54
|
-
// generateKeyPairSync,
|
|
55
63
|
// generateKeySync,
|
|
56
64
|
// createSign,
|
|
57
65
|
// createVerify,
|
|
58
66
|
// subtle,
|
|
59
67
|
// constants,
|
|
68
|
+
...keys,
|
|
69
|
+
...ed,
|
|
60
70
|
...pbkdf2,
|
|
61
71
|
...random,
|
|
62
72
|
// getCiphers,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_reactNativeBuffer","require","
|
|
1
|
+
{"version":3,"names":["_reactNativeBuffer","require","keys","_interopRequireWildcard","ed","Object","forEach","key","prototype","hasOwnProperty","call","_exportNames","exports","defineProperty","enumerable","get","pbkdf2","random","utils","_getRequireWildcardCache","e","WeakMap","r","t","__esModule","default","has","n","__proto__","a","getOwnPropertyDescriptor","u","i","set","QuickCrypto","install","global","Buffer","crypto","process","nextTick","setImmediate","_default","module"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":"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","ignoreList":[]}
|