react-native-quick-crypto 0.7.0-rc.9 → 0.7.1
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/Cipher/MGLGenerateKeyPairInstaller.cpp +51 -14
- package/cpp/Cipher/MGLGenerateKeyPairSyncInstaller.cpp +25 -9
- package/cpp/Cipher/MGLRsa.cpp +192 -15
- package/cpp/Cipher/MGLRsa.h +36 -2
- package/cpp/JSIUtils/MGLJSIUtils.h +17 -0
- package/cpp/MGLKeys.cpp +210 -187
- package/cpp/MGLKeys.h +25 -13
- package/cpp/MGLQuickCryptoHostObject.cpp +6 -6
- package/cpp/Sig/MGLSignHostObjects.cpp +284 -421
- package/cpp/Sig/MGLSignHostObjects.h +40 -0
- package/cpp/Utils/MGLUtils.cpp +71 -42
- package/cpp/Utils/MGLUtils.h +81 -6
- package/cpp/webcrypto/MGLWebCrypto.cpp +97 -35
- package/cpp/webcrypto/MGLWebCrypto.h +5 -7
- package/cpp/webcrypto/crypto_aes.cpp +516 -0
- package/cpp/webcrypto/crypto_aes.h +79 -0
- package/cpp/webcrypto/crypto_ec.cpp +110 -20
- package/cpp/webcrypto/crypto_ec.h +18 -5
- package/cpp/webcrypto/crypto_keygen.cpp +86 -0
- package/cpp/webcrypto/crypto_keygen.h +38 -0
- package/lib/commonjs/Cipher.js +140 -95
- package/lib/commonjs/Cipher.js.map +1 -1
- package/lib/commonjs/Hashnames.js +20 -8
- package/lib/commonjs/Hashnames.js.map +1 -1
- package/lib/commonjs/NativeQuickCrypto/Cipher.js +23 -8
- package/lib/commonjs/NativeQuickCrypto/Cipher.js.map +1 -1
- package/lib/commonjs/NativeQuickCrypto/NativeQuickCrypto.js.map +1 -1
- package/lib/commonjs/NativeQuickCrypto/aes.js +6 -0
- package/lib/commonjs/NativeQuickCrypto/aes.js.map +1 -0
- package/lib/commonjs/NativeQuickCrypto/keygen.js +6 -0
- package/lib/commonjs/NativeQuickCrypto/keygen.js.map +1 -0
- package/lib/commonjs/NativeQuickCrypto/rsa.js +6 -0
- package/lib/commonjs/NativeQuickCrypto/rsa.js.map +1 -0
- package/lib/commonjs/NativeQuickCrypto/sig.js +17 -0
- package/lib/commonjs/NativeQuickCrypto/sig.js.map +1 -1
- package/lib/commonjs/Utils.js +45 -7
- package/lib/commonjs/Utils.js.map +1 -1
- package/lib/commonjs/aes.js +184 -227
- package/lib/commonjs/aes.js.map +1 -1
- package/lib/commonjs/ec.js +79 -91
- package/lib/commonjs/ec.js.map +1 -1
- package/lib/commonjs/index.js +12 -2
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/keygen.js +56 -0
- package/lib/commonjs/keygen.js.map +1 -0
- package/lib/commonjs/keys.js +84 -29
- package/lib/commonjs/keys.js.map +1 -1
- package/lib/commonjs/random.js +6 -0
- package/lib/commonjs/random.js.map +1 -1
- package/lib/commonjs/rsa.js +115 -196
- package/lib/commonjs/rsa.js.map +1 -1
- package/lib/commonjs/sig.js.map +1 -1
- package/lib/commonjs/subtle.js +205 -29
- package/lib/commonjs/subtle.js.map +1 -1
- package/lib/commonjs/webcrypto.js +14 -0
- package/lib/commonjs/webcrypto.js.map +1 -0
- package/lib/module/Cipher.js +138 -93
- package/lib/module/Cipher.js.map +1 -1
- package/lib/module/Hashnames.js +20 -8
- package/lib/module/Hashnames.js.map +1 -1
- package/lib/module/NativeQuickCrypto/Cipher.js +22 -7
- package/lib/module/NativeQuickCrypto/Cipher.js.map +1 -1
- package/lib/module/NativeQuickCrypto/NativeQuickCrypto.js.map +1 -1
- package/lib/module/NativeQuickCrypto/aes.js +2 -0
- package/lib/module/NativeQuickCrypto/aes.js.map +1 -0
- package/lib/module/NativeQuickCrypto/keygen.js +2 -0
- package/lib/module/NativeQuickCrypto/keygen.js.map +1 -0
- package/lib/module/NativeQuickCrypto/rsa.js +2 -0
- package/lib/module/NativeQuickCrypto/rsa.js.map +1 -0
- package/lib/module/NativeQuickCrypto/sig.js +13 -0
- package/lib/module/NativeQuickCrypto/sig.js.map +1 -1
- package/lib/module/Utils.js +38 -5
- package/lib/module/Utils.js.map +1 -1
- package/lib/module/aes.js +183 -228
- package/lib/module/aes.js.map +1 -1
- package/lib/module/ec.js +76 -93
- package/lib/module/ec.js.map +1 -1
- package/lib/module/index.js +11 -2
- package/lib/module/index.js.map +1 -1
- package/lib/module/keygen.js +47 -0
- package/lib/module/keygen.js.map +1 -0
- package/lib/module/keys.js +76 -28
- package/lib/module/keys.js.map +1 -1
- package/lib/module/random.js +6 -0
- package/lib/module/random.js.map +1 -1
- package/lib/module/rsa.js +115 -198
- package/lib/module/rsa.js.map +1 -1
- package/lib/module/sig.js.map +1 -1
- package/lib/module/subtle.js +209 -34
- package/lib/module/subtle.js.map +1 -1
- package/lib/module/webcrypto.js +8 -0
- package/lib/module/webcrypto.js.map +1 -0
- package/lib/typescript/Cipher.d.ts +23 -14
- package/lib/typescript/Cipher.d.ts.map +1 -1
- package/lib/typescript/Hash.d.ts.map +1 -1
- package/lib/typescript/Hashnames.d.ts +2 -2
- package/lib/typescript/Hashnames.d.ts.map +1 -1
- package/lib/typescript/NativeQuickCrypto/Cipher.d.ts +16 -6
- package/lib/typescript/NativeQuickCrypto/Cipher.d.ts.map +1 -1
- package/lib/typescript/NativeQuickCrypto/NativeQuickCrypto.d.ts +4 -1
- package/lib/typescript/NativeQuickCrypto/NativeQuickCrypto.d.ts.map +1 -1
- package/lib/typescript/NativeQuickCrypto/aes.d.ts +5 -0
- package/lib/typescript/NativeQuickCrypto/aes.d.ts.map +1 -0
- package/lib/typescript/NativeQuickCrypto/keygen.d.ts +4 -0
- package/lib/typescript/NativeQuickCrypto/keygen.d.ts.map +1 -0
- package/lib/typescript/NativeQuickCrypto/rsa.d.ts +5 -0
- package/lib/typescript/NativeQuickCrypto/rsa.d.ts.map +1 -0
- package/lib/typescript/NativeQuickCrypto/sig.d.ts +10 -0
- package/lib/typescript/NativeQuickCrypto/sig.d.ts.map +1 -1
- package/lib/typescript/NativeQuickCrypto/webcrypto.d.ts +14 -2
- package/lib/typescript/NativeQuickCrypto/webcrypto.d.ts.map +1 -1
- package/lib/typescript/Utils.d.ts +5 -4
- package/lib/typescript/Utils.d.ts.map +1 -1
- package/lib/typescript/aes.d.ts +18 -1
- package/lib/typescript/aes.d.ts.map +1 -1
- package/lib/typescript/ec.d.ts +3 -1
- package/lib/typescript/ec.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +30 -24
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/keygen.d.ts +6 -0
- package/lib/typescript/keygen.d.ts.map +1 -0
- package/lib/typescript/keys.d.ts +67 -18
- package/lib/typescript/keys.d.ts.map +1 -1
- package/lib/typescript/random.d.ts +2 -1
- package/lib/typescript/random.d.ts.map +1 -1
- package/lib/typescript/rsa.d.ts +9 -1
- package/lib/typescript/rsa.d.ts.map +1 -1
- package/lib/typescript/sig.d.ts +3 -17
- package/lib/typescript/sig.d.ts.map +1 -1
- package/lib/typescript/subtle.d.ts +8 -4
- package/lib/typescript/subtle.d.ts.map +1 -1
- package/lib/typescript/webcrypto.d.ts +9 -0
- package/lib/typescript/webcrypto.d.ts.map +1 -0
- package/package.json +2 -2
- package/src/Cipher.ts +139 -75
- package/src/Hashnames.ts +23 -21
- package/src/NativeQuickCrypto/Cipher.ts +46 -14
- package/src/NativeQuickCrypto/NativeQuickCrypto.ts +6 -0
- package/src/NativeQuickCrypto/aes.ts +14 -0
- package/src/NativeQuickCrypto/keygen.ts +7 -0
- package/src/NativeQuickCrypto/rsa.ts +12 -0
- package/src/NativeQuickCrypto/sig.ts +27 -0
- package/src/NativeQuickCrypto/webcrypto.ts +28 -2
- package/src/Utils.ts +49 -8
- package/src/aes.ts +259 -222
- package/src/ec.ts +114 -90
- package/src/index.ts +10 -1
- package/src/keygen.ts +80 -0
- package/src/keys.ts +165 -61
- package/src/random.ts +12 -1
- package/src/rsa.ts +161 -187
- package/src/sig.ts +7 -23
- package/src/subtle.ts +309 -35
- package/src/webcrypto.ts +8 -0
package/android/CMakeLists.txt
CHANGED
|
@@ -43,7 +43,9 @@ add_library(
|
|
|
43
43
|
"../cpp/Sig/MGLVerifyInstaller.cpp"
|
|
44
44
|
"../cpp/Sig/MGLSignHostObjects.cpp"
|
|
45
45
|
"../cpp/webcrypto/MGLWebCrypto.cpp"
|
|
46
|
+
"../cpp/webcrypto/crypto_aes.cpp"
|
|
46
47
|
"../cpp/webcrypto/crypto_ec.cpp"
|
|
48
|
+
"../cpp/webcrypto/crypto_keygen.cpp"
|
|
47
49
|
)
|
|
48
50
|
|
|
49
51
|
target_include_directories(
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
#include <iostream>
|
|
11
11
|
#include <memory>
|
|
12
12
|
#include <mutex>
|
|
13
|
+
#include <string>
|
|
13
14
|
#include <thread>
|
|
14
15
|
#include <utility>
|
|
15
16
|
|
|
@@ -18,9 +19,11 @@
|
|
|
18
19
|
#ifdef ANDROID
|
|
19
20
|
#include "JSIUtils/MGLJSIMacros.h"
|
|
20
21
|
#include "JSIUtils/MGLTypedArray.h"
|
|
22
|
+
#include "webcrypto/crypto_ec.h"
|
|
21
23
|
#else
|
|
22
24
|
#include "MGLJSIMacros.h"
|
|
23
25
|
#include "MGLTypedArray.h"
|
|
26
|
+
#include "crypto_ec.h"
|
|
24
27
|
#endif
|
|
25
28
|
|
|
26
29
|
using namespace facebook;
|
|
@@ -29,24 +32,44 @@ namespace margelo {
|
|
|
29
32
|
|
|
30
33
|
std::mutex m;
|
|
31
34
|
|
|
32
|
-
// Current implementation only supports RSA schemes (check line config.variant =
|
|
33
|
-
// ) As more encryption schemes are added this will require an abstraction that
|
|
34
|
-
// supports more schemes
|
|
35
35
|
FieldDefinition getGenerateKeyPairFieldDefinition(
|
|
36
36
|
std::shared_ptr<react::CallInvoker> jsCallInvoker,
|
|
37
37
|
std::shared_ptr<DispatchQueue::dispatch_queue> workerQueue) {
|
|
38
38
|
return buildPair(
|
|
39
39
|
"generateKeyPair", JSIF([=]) {
|
|
40
|
-
|
|
40
|
+
|
|
41
|
+
KeyVariant variant =
|
|
42
|
+
static_cast<KeyVariant>((int)arguments[0].asNumber());
|
|
43
|
+
std::shared_ptr<RsaKeyPairGenConfig> rsaConfig;
|
|
44
|
+
std::shared_ptr<EcKeyPairGenConfig> ecConfig;
|
|
45
|
+
|
|
46
|
+
// switch on variant to get proper config from arguments
|
|
47
|
+
// outside of lambda 🤮
|
|
48
|
+
if (variant == kvRSA_SSA_PKCS1_v1_5 ||
|
|
49
|
+
variant == kvRSA_PSS ||
|
|
50
|
+
variant == kvRSA_OAEP
|
|
51
|
+
) {
|
|
52
|
+
rsaConfig = std::make_shared<RsaKeyPairGenConfig>(
|
|
41
53
|
prepareRsaKeyGenConfig(runtime, arguments));
|
|
54
|
+
} else
|
|
55
|
+
if (variant == kvEC) {
|
|
56
|
+
ecConfig = std::make_shared<EcKeyPairGenConfig>(
|
|
57
|
+
prepareEcKeyGenConfig(runtime, arguments));
|
|
58
|
+
} else {
|
|
59
|
+
throw std::runtime_error("KeyVariant not implemented"
|
|
60
|
+
+ std::to_string((int)variant));
|
|
61
|
+
}
|
|
62
|
+
|
|
42
63
|
auto promiseConstructor =
|
|
43
64
|
runtime.global().getPropertyAsFunction(runtime, "Promise");
|
|
44
65
|
|
|
45
66
|
auto promise = promiseConstructor.callAsConstructor(
|
|
46
67
|
runtime,
|
|
47
68
|
jsi::Function::createFromHostFunction(
|
|
48
|
-
runtime,
|
|
49
|
-
|
|
69
|
+
runtime,
|
|
70
|
+
jsi::PropNameID::forAscii(runtime, "executor"),
|
|
71
|
+
4,
|
|
72
|
+
[&jsCallInvoker, variant, rsaConfig, ecConfig](
|
|
50
73
|
jsi::Runtime &runtime, const jsi::Value &,
|
|
51
74
|
const jsi::Value *promiseArgs, size_t) -> jsi::Value {
|
|
52
75
|
auto resolve =
|
|
@@ -54,19 +77,33 @@ FieldDefinition getGenerateKeyPairFieldDefinition(
|
|
|
54
77
|
auto reject =
|
|
55
78
|
std::make_shared<jsi::Value>(runtime, promiseArgs[1]);
|
|
56
79
|
|
|
57
|
-
std::thread t([&runtime, resolve, reject,
|
|
58
|
-
|
|
80
|
+
std::thread t([&runtime, resolve, reject, jsCallInvoker,
|
|
81
|
+
variant, rsaConfig, ecConfig]() {
|
|
59
82
|
m.lock();
|
|
60
83
|
try {
|
|
61
|
-
jsCallInvoker->invokeAsync([&runtime,
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
84
|
+
jsCallInvoker->invokeAsync([&runtime, resolve,
|
|
85
|
+
variant, rsaConfig, ecConfig]() {
|
|
86
|
+
std::pair<jsi::Value, jsi::Value> keys;
|
|
87
|
+
|
|
88
|
+
// switch on variant to get proper generateKeyPair
|
|
89
|
+
if (variant == kvRSA_SSA_PKCS1_v1_5 ||
|
|
90
|
+
variant == kvRSA_PSS ||
|
|
91
|
+
variant == kvRSA_OAEP
|
|
92
|
+
) {
|
|
93
|
+
keys = generateRsaKeyPair(runtime, rsaConfig);
|
|
94
|
+
} else
|
|
95
|
+
if (variant == kvEC) {
|
|
96
|
+
keys = generateEcKeyPair(runtime, ecConfig);
|
|
97
|
+
} else {
|
|
98
|
+
throw std::runtime_error("KeyVariant not implemented"
|
|
99
|
+
+ std::to_string((int)variant));
|
|
100
|
+
}
|
|
101
|
+
|
|
65
102
|
auto res = jsi::Array::createWithElements(
|
|
66
103
|
runtime,
|
|
67
104
|
jsi::Value::undefined(),
|
|
68
|
-
|
|
69
|
-
|
|
105
|
+
keys.first,
|
|
106
|
+
keys.second);
|
|
70
107
|
resolve->asObject(runtime).asFunction(runtime).call(
|
|
71
108
|
runtime, std::move(res));
|
|
72
109
|
});
|
|
@@ -17,31 +17,47 @@
|
|
|
17
17
|
#include "JSIUtils/MGLJSIMacros.h"
|
|
18
18
|
#include "JSIUtils/MGLJSIUtils.h"
|
|
19
19
|
#include "JSIUtils/MGLTypedArray.h"
|
|
20
|
+
#include "webcrypto/crypto_ec.h"
|
|
20
21
|
#else
|
|
21
22
|
#include "MGLJSIMacros.h"
|
|
22
23
|
#include "MGLJSIUtils.h"
|
|
23
24
|
#include "MGLTypedArray.h"
|
|
25
|
+
#include "crypto_ec.h"
|
|
24
26
|
#endif
|
|
25
27
|
|
|
26
28
|
using namespace facebook;
|
|
27
29
|
|
|
28
30
|
namespace margelo {
|
|
29
31
|
|
|
30
|
-
// Current implementation only supports RSA schemes (check line config.variant =
|
|
31
|
-
// ) As more encryption schemes are added this will require an abstraction that
|
|
32
|
-
// supports more schemes
|
|
33
32
|
FieldDefinition getGenerateKeyPairSyncFieldDefinition(
|
|
34
33
|
std::shared_ptr<react::CallInvoker> jsCallInvoker,
|
|
35
34
|
std::shared_ptr<DispatchQueue::dispatch_queue> workerQueue) {
|
|
36
35
|
return buildPair(
|
|
37
36
|
"generateKeyPairSync", JSIF([=]) {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
37
|
+
std::pair<jsi::Value, jsi::Value> keys;
|
|
38
|
+
KeyVariant variant =
|
|
39
|
+
static_cast<KeyVariant>((int)arguments[0].asNumber());
|
|
40
|
+
|
|
41
|
+
// switch on variant to get proper config/genKeyPair
|
|
42
|
+
if (variant == kvRSA_SSA_PKCS1_v1_5 ||
|
|
43
|
+
variant == kvRSA_PSS ||
|
|
44
|
+
variant == kvRSA_OAEP
|
|
45
|
+
) {
|
|
46
|
+
auto config = std::make_shared<RsaKeyPairGenConfig>(
|
|
47
|
+
prepareRsaKeyGenConfig(runtime, arguments));
|
|
48
|
+
keys = generateRsaKeyPair(runtime, config);
|
|
49
|
+
} else
|
|
50
|
+
if (variant == kvEC) {
|
|
51
|
+
auto config = std::make_shared<EcKeyPairGenConfig>(
|
|
52
|
+
prepareEcKeyGenConfig(runtime, arguments));
|
|
53
|
+
keys = generateEcKeyPair(runtime, config);
|
|
54
|
+
} else {
|
|
55
|
+
throw std::runtime_error("KeyVariant not implemented: " +
|
|
56
|
+
std::to_string((int)variant));
|
|
57
|
+
}
|
|
58
|
+
// keys.first = publicKey keys.second = privateKey
|
|
43
59
|
return jsi::Array::createWithElements(
|
|
44
|
-
runtime, jsi::Value::undefined(),
|
|
60
|
+
runtime, jsi::Value::undefined(), keys.first, keys.second);
|
|
45
61
|
});
|
|
46
62
|
}
|
|
47
63
|
} // namespace margelo
|
package/cpp/Cipher/MGLRsa.cpp
CHANGED
|
@@ -7,9 +7,15 @@
|
|
|
7
7
|
|
|
8
8
|
#include "MGLRsa.h"
|
|
9
9
|
#ifdef ANDROID
|
|
10
|
+
#include "Cipher/MGLPublicCipher.h"
|
|
10
11
|
#include "JSIUtils/MGLJSIMacros.h"
|
|
12
|
+
#include "JSIUtils/MGLJSIUtils.h"
|
|
13
|
+
#include "Utils/MGLUtils.h"
|
|
11
14
|
#else
|
|
15
|
+
#include "MGLPublicCipher.h"
|
|
12
16
|
#include "MGLJSIMacros.h"
|
|
17
|
+
#include "MGLJSIUtils.h"
|
|
18
|
+
#include "MGLUtils.h"
|
|
13
19
|
#endif
|
|
14
20
|
|
|
15
21
|
#include <string>
|
|
@@ -21,7 +27,7 @@ namespace jsi = facebook::jsi;
|
|
|
21
27
|
|
|
22
28
|
EVPKeyCtxPointer setup(std::shared_ptr<RsaKeyPairGenConfig> config) {
|
|
23
29
|
EVPKeyCtxPointer ctx(EVP_PKEY_CTX_new_id(
|
|
24
|
-
config->variant ==
|
|
30
|
+
config->variant == kvRSA_PSS ? EVP_PKEY_RSA_PSS : EVP_PKEY_RSA,
|
|
25
31
|
nullptr));
|
|
26
32
|
|
|
27
33
|
if (EVP_PKEY_keygen_init(ctx.get()) <= 0) return EVPKeyCtxPointer();
|
|
@@ -43,7 +49,7 @@ EVPKeyCtxPointer setup(std::shared_ptr<RsaKeyPairGenConfig> config) {
|
|
|
43
49
|
bn.release();
|
|
44
50
|
}
|
|
45
51
|
|
|
46
|
-
if (config->variant ==
|
|
52
|
+
if (config->variant == kvRSA_PSS) {
|
|
47
53
|
if (config->md != nullptr &&
|
|
48
54
|
EVP_PKEY_CTX_set_rsa_pss_keygen_md(ctx.get(), config->md) <= 0) {
|
|
49
55
|
return EVPKeyCtxPointer();
|
|
@@ -94,12 +100,12 @@ RsaKeyPairGenConfig prepareRsaKeyGenConfig(jsi::Runtime& runtime,
|
|
|
94
100
|
// CHECK(args[*offset + 1]->IsUint32()); // Modulus bits
|
|
95
101
|
// CHECK(args[*offset + 2]->IsUint32()); // Exponent
|
|
96
102
|
config.variant =
|
|
97
|
-
static_cast<
|
|
103
|
+
static_cast<KeyVariant>((int)arguments[offset].asNumber());
|
|
98
104
|
|
|
99
105
|
// TODO(osp)
|
|
100
|
-
// CHECK_IMPLIES(params->params.variant !=
|
|
106
|
+
// CHECK_IMPLIES(params->params.variant != kvRSA_PSS,
|
|
101
107
|
// args.Length() == 10);
|
|
102
|
-
// CHECK_IMPLIES(params->params.variant ==
|
|
108
|
+
// CHECK_IMPLIES(params->params.variant == kvRSA_PSS,
|
|
103
109
|
// args.Length() == 13);
|
|
104
110
|
config.modulus_bits =
|
|
105
111
|
static_cast<unsigned int>(arguments[offset + 1].asNumber());
|
|
@@ -107,7 +113,7 @@ RsaKeyPairGenConfig prepareRsaKeyGenConfig(jsi::Runtime& runtime,
|
|
|
107
113
|
|
|
108
114
|
offset += 3;
|
|
109
115
|
|
|
110
|
-
if (config.variant ==
|
|
116
|
+
if (config.variant == kvRSA_PSS) {
|
|
111
117
|
if (!arguments[offset].isUndefined()) {
|
|
112
118
|
// TODO(osp) CHECK(string)
|
|
113
119
|
config.md = EVP_get_digestbyname(
|
|
@@ -153,8 +159,9 @@ RsaKeyPairGenConfig prepareRsaKeyGenConfig(jsi::Runtime& runtime,
|
|
|
153
159
|
return config;
|
|
154
160
|
}
|
|
155
161
|
|
|
156
|
-
std::pair<
|
|
162
|
+
std::pair<jsi::Value, jsi::Value> generateRsaKeyPair(
|
|
157
163
|
jsi::Runtime& runtime, std::shared_ptr<RsaKeyPairGenConfig> config) {
|
|
164
|
+
// TODO: this is all copied into crypto_ec.cpp - template it up like Node?
|
|
158
165
|
CheckEntropy();
|
|
159
166
|
|
|
160
167
|
EVPKeyCtxPointer ctx = setup(config);
|
|
@@ -171,18 +178,137 @@ std::pair<JSVariant, JSVariant> generateRSAKeyPair(
|
|
|
171
178
|
|
|
172
179
|
config->key = ManagedEVPPKey(EVPKeyPointer(pkey));
|
|
173
180
|
|
|
174
|
-
|
|
181
|
+
jsi::Value publicBuffer =
|
|
175
182
|
ManagedEVPPKey::ToEncodedPublicKey(runtime, std::move(config->key),
|
|
176
183
|
config->public_key_encoding);
|
|
177
|
-
|
|
184
|
+
jsi::Value privateBuffer =
|
|
178
185
|
ManagedEVPPKey::ToEncodedPrivateKey(runtime, std::move(config->key),
|
|
179
186
|
config->private_key_encoding);
|
|
180
187
|
|
|
181
|
-
if (
|
|
182
|
-
throw jsi::JSError(runtime, "Failed to encode public and/or private key");
|
|
188
|
+
if (publicBuffer.isUndefined() || privateBuffer.isUndefined()) {
|
|
189
|
+
throw jsi::JSError(runtime, "Failed to encode public and/or private key (RSA)");
|
|
183
190
|
}
|
|
184
191
|
|
|
185
|
-
return {std::move(publicBuffer
|
|
192
|
+
return {std::move(publicBuffer), std::move(privateBuffer)};
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
template <MGLPublicCipher::EVP_PKEY_cipher_init_t init,
|
|
196
|
+
MGLPublicCipher::EVP_PKEY_cipher_t cipher>
|
|
197
|
+
WebCryptoCipherStatus RSA_Cipher(const RSACipherConfig& params, ByteSource* out) {
|
|
198
|
+
CHECK_NE(params.key->GetKeyType(), kKeyTypeSecret);
|
|
199
|
+
ManagedEVPPKey m_pkey = params.key->GetAsymmetricKey();
|
|
200
|
+
// Mutex::ScopedLock lock(*m_pkey.mutex());
|
|
201
|
+
|
|
202
|
+
EVPKeyCtxPointer ctx(EVP_PKEY_CTX_new(m_pkey.get(), nullptr));
|
|
203
|
+
|
|
204
|
+
if (!ctx || init(ctx.get()) <= 0)
|
|
205
|
+
return WebCryptoCipherStatus::FAILED;
|
|
206
|
+
|
|
207
|
+
if (EVP_PKEY_CTX_set_rsa_padding(ctx.get(), params.padding) <= 0) {
|
|
208
|
+
return WebCryptoCipherStatus::FAILED;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
if (params.digest != nullptr &&
|
|
212
|
+
(EVP_PKEY_CTX_set_rsa_oaep_md(ctx.get(), params.digest) <= 0 ||
|
|
213
|
+
EVP_PKEY_CTX_set_rsa_mgf1_md(ctx.get(), params.digest) <= 0)) {
|
|
214
|
+
return WebCryptoCipherStatus::FAILED;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
if (!SetRsaOaepLabel(ctx, params.label)) return WebCryptoCipherStatus::FAILED;
|
|
218
|
+
|
|
219
|
+
size_t out_len = 0;
|
|
220
|
+
if (cipher(
|
|
221
|
+
ctx.get(),
|
|
222
|
+
nullptr,
|
|
223
|
+
&out_len,
|
|
224
|
+
params.data.data<unsigned char>(),
|
|
225
|
+
params.data.size()) <= 0) {
|
|
226
|
+
return WebCryptoCipherStatus::FAILED;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
ByteSource::Builder buf(out_len);
|
|
230
|
+
|
|
231
|
+
if (cipher(ctx.get(),
|
|
232
|
+
buf.data<unsigned char>(),
|
|
233
|
+
&out_len,
|
|
234
|
+
params.data.data<unsigned char>(),
|
|
235
|
+
params.data.size()) <= 0) {
|
|
236
|
+
return WebCryptoCipherStatus::FAILED;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
*out = std::move(buf).release(out_len);
|
|
240
|
+
return WebCryptoCipherStatus::OK;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
RSACipherConfig RSACipher::GetParamsFromJS(jsi::Runtime &rt,
|
|
244
|
+
const jsi::Value *args) {
|
|
245
|
+
RSACipherConfig params;
|
|
246
|
+
unsigned int offset = 0;
|
|
247
|
+
|
|
248
|
+
// padding
|
|
249
|
+
params.padding = RSA_PKCS1_OAEP_PADDING;
|
|
250
|
+
|
|
251
|
+
// mode (encrypt/decrypt)
|
|
252
|
+
params.mode = static_cast<WebCryptoCipherMode>((int)args[offset].getNumber());
|
|
253
|
+
offset++;
|
|
254
|
+
|
|
255
|
+
// key (handle)
|
|
256
|
+
if (!args[offset].isObject()) {
|
|
257
|
+
throw std::runtime_error("arg is not a KeyObjectHandle: key");
|
|
258
|
+
}
|
|
259
|
+
std::shared_ptr<KeyObjectHandle> handle =
|
|
260
|
+
std::static_pointer_cast<KeyObjectHandle>(
|
|
261
|
+
args[offset].asObject(rt).getHostObject(rt));
|
|
262
|
+
params.key = handle->Data();
|
|
263
|
+
offset++;
|
|
264
|
+
|
|
265
|
+
// data
|
|
266
|
+
params.data = GetByteSourceFromJS(rt, args[offset], "data");
|
|
267
|
+
offset++;
|
|
268
|
+
|
|
269
|
+
// variant
|
|
270
|
+
if (CheckIsInt32(args[offset])) {
|
|
271
|
+
params.variant = static_cast<RSAKeyVariant>((int)args[offset].getNumber());
|
|
272
|
+
}
|
|
273
|
+
// offset++; // The below variant-dependent params advance offset themselves
|
|
274
|
+
|
|
275
|
+
std::string digest;
|
|
276
|
+
switch (params.variant) {
|
|
277
|
+
case kKeyVariantRSA_OAEP:
|
|
278
|
+
// hash (digest)
|
|
279
|
+
CHECK(args[offset + 1].isString());
|
|
280
|
+
digest = args[offset + 1].asString(rt).utf8(rt);
|
|
281
|
+
params.digest = EVP_get_digestbyname(digest.c_str());
|
|
282
|
+
if (params.digest == nullptr) {
|
|
283
|
+
throw jsi::JSError(rt, "invalid digest: " + digest);
|
|
284
|
+
return params;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// label
|
|
288
|
+
if (args[offset + 2].isUndefined()) {
|
|
289
|
+
params.label = ByteSource();
|
|
290
|
+
} else {
|
|
291
|
+
params.label = GetByteSourceFromJS(rt, args[offset + 2], "label");
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
break;
|
|
295
|
+
default:
|
|
296
|
+
throw jsi::JSError(rt, "Invalid RSA key variant");
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
return params;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
WebCryptoCipherStatus RSACipher::DoCipher(const RSACipherConfig ¶ms,
|
|
303
|
+
ByteSource *out) {
|
|
304
|
+
switch (params.mode) {
|
|
305
|
+
case kEncrypt:
|
|
306
|
+
CHECK_EQ(params.key->GetKeyType(), kKeyTypePublic);
|
|
307
|
+
return RSA_Cipher<EVP_PKEY_encrypt_init, EVP_PKEY_encrypt>(params, out);
|
|
308
|
+
case kDecrypt:
|
|
309
|
+
CHECK_EQ(params.key->GetKeyType(), kKeyTypePrivate);
|
|
310
|
+
return RSA_Cipher<EVP_PKEY_decrypt_init, EVP_PKEY_decrypt>(params, out);
|
|
311
|
+
}
|
|
186
312
|
}
|
|
187
313
|
|
|
188
314
|
jsi::Value ExportJWKRsaKey(jsi::Runtime &rt,
|
|
@@ -329,12 +455,11 @@ jsi::Value GetRsaKeyDetail(jsi::Runtime &rt,
|
|
|
329
455
|
RSA_get0_key(rsa, &n, &e, nullptr);
|
|
330
456
|
|
|
331
457
|
size_t modulus_length = BN_num_bits(n);
|
|
332
|
-
// TODO: should this be modulusLength or n?
|
|
333
458
|
target.setProperty(rt, "modulusLength", static_cast<double>(modulus_length));
|
|
334
459
|
|
|
335
460
|
size_t exp_size = BN_num_bytes(e);
|
|
336
|
-
|
|
337
|
-
target.setProperty(rt, "publicExponent",
|
|
461
|
+
ByteSource public_exponent = ByteSource::FromBN(e, exp_size);
|
|
462
|
+
target.setProperty(rt, "publicExponent", toJSI(rt, std::move(public_exponent)));
|
|
338
463
|
|
|
339
464
|
if (type == EVP_PKEY_RSA_PSS) {
|
|
340
465
|
// Due to the way ASN.1 encoding works, default values are omitted when
|
|
@@ -393,4 +518,56 @@ jsi::Value GetRsaKeyDetail(jsi::Runtime &rt,
|
|
|
393
518
|
return target;
|
|
394
519
|
}
|
|
395
520
|
|
|
521
|
+
bool RsaKeyExport::GetParamsFromJS(jsi::Runtime &rt, const jsi::Value *args) {
|
|
522
|
+
RsaKeyExportConfig params;
|
|
523
|
+
unsigned int offset = 0;
|
|
524
|
+
|
|
525
|
+
// format
|
|
526
|
+
params.format = static_cast<WebCryptoKeyFormat>((int)args[offset].getNumber());
|
|
527
|
+
offset++;
|
|
528
|
+
|
|
529
|
+
// key
|
|
530
|
+
std::shared_ptr<KeyObjectHandle> handle =
|
|
531
|
+
std::static_pointer_cast<KeyObjectHandle>(
|
|
532
|
+
args[1].asObject(rt).getHostObject(rt));
|
|
533
|
+
params.key_ = handle->Data();
|
|
534
|
+
offset++;
|
|
535
|
+
|
|
536
|
+
// variant
|
|
537
|
+
params.variant = static_cast<KeyVariant>((int)args[offset].getNumber());
|
|
538
|
+
offset++;
|
|
539
|
+
|
|
540
|
+
this->params_ = std::move(params);
|
|
541
|
+
return true;
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
WebCryptoKeyExportStatus RsaKeyExport::DoExport(ByteSource* out) {
|
|
545
|
+
auto key_data = this->params_.key_;
|
|
546
|
+
CHECK_NE(key_data->GetKeyType(), kKeyTypeSecret);
|
|
547
|
+
|
|
548
|
+
switch (this->params_.format) {
|
|
549
|
+
case kWebCryptoKeyFormatRaw:
|
|
550
|
+
throw std::runtime_error("Raw format not supported for RSA keys");
|
|
551
|
+
return WebCryptoKeyExportStatus::FAILED;
|
|
552
|
+
case kWebCryptoKeyFormatJWK:
|
|
553
|
+
throw std::runtime_error("JWK format not handled in C++ for RSA keys");
|
|
554
|
+
return WebCryptoKeyExportStatus::FAILED;
|
|
555
|
+
case kWebCryptoKeyFormatPKCS8:
|
|
556
|
+
if (key_data->GetKeyType() != kKeyTypePrivate) {
|
|
557
|
+
throw std::runtime_error("Invalid key type for PKCS8 export");
|
|
558
|
+
return WebCryptoKeyExportStatus::INVALID_KEY_TYPE;
|
|
559
|
+
}
|
|
560
|
+
return PKEY_PKCS8_Export(key_data.get(), out);
|
|
561
|
+
case kWebCryptoKeyFormatSPKI:
|
|
562
|
+
if (key_data->GetKeyType() != kKeyTypePublic) {
|
|
563
|
+
throw std::runtime_error("Invalid key type for SPKI export");
|
|
564
|
+
return WebCryptoKeyExportStatus::INVALID_KEY_TYPE;
|
|
565
|
+
}
|
|
566
|
+
return PKEY_SPKI_Export(key_data.get(), out);
|
|
567
|
+
default:
|
|
568
|
+
throw std::runtime_error("Unrecognized format for RSA key export");
|
|
569
|
+
return WebCryptoKeyExportStatus::FAILED;
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
|
|
396
573
|
} // namespace margelo
|
package/cpp/Cipher/MGLRsa.h
CHANGED
|
@@ -25,6 +25,7 @@ namespace margelo {
|
|
|
25
25
|
|
|
26
26
|
namespace jsi = facebook::jsi;
|
|
27
27
|
|
|
28
|
+
// TODO: keep in in sync with JS side (src/rsa.ts)
|
|
28
29
|
enum RSAKeyVariant {
|
|
29
30
|
kKeyVariantRSA_SSA_PKCS1_v1_5,
|
|
30
31
|
kKeyVariantRSA_PSS,
|
|
@@ -43,7 +44,7 @@ struct RsaKeyPairGenConfig {
|
|
|
43
44
|
PrivateKeyEncodingConfig private_key_encoding;
|
|
44
45
|
ManagedEVPPKey key;
|
|
45
46
|
|
|
46
|
-
|
|
47
|
+
KeyVariant variant;
|
|
47
48
|
unsigned int modulus_bits;
|
|
48
49
|
unsigned int exponent;
|
|
49
50
|
|
|
@@ -57,7 +58,7 @@ struct RsaKeyPairGenConfig {
|
|
|
57
58
|
RsaKeyPairGenConfig prepareRsaKeyGenConfig(jsi::Runtime& runtime,
|
|
58
59
|
const jsi::Value* arguments);
|
|
59
60
|
|
|
60
|
-
std::pair<
|
|
61
|
+
std::pair<jsi::Value, jsi::Value> generateRsaKeyPair(
|
|
61
62
|
jsi::Runtime& runtime, std::shared_ptr<RsaKeyPairGenConfig> config);
|
|
62
63
|
|
|
63
64
|
jsi::Value ExportJWKRsaKey(jsi::Runtime &rt,
|
|
@@ -70,6 +71,39 @@ std::shared_ptr<KeyObjectData> ImportJWKRsaKey(jsi::Runtime &rt,
|
|
|
70
71
|
jsi::Value GetRsaKeyDetail(jsi::Runtime &rt,
|
|
71
72
|
std::shared_ptr<KeyObjectData> key);
|
|
72
73
|
|
|
74
|
+
struct RsaKeyExportConfig final {
|
|
75
|
+
WebCryptoKeyFormat format;
|
|
76
|
+
std::shared_ptr<KeyObjectData> key_;
|
|
77
|
+
KeyVariant variant;
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
class RsaKeyExport {
|
|
81
|
+
public:
|
|
82
|
+
bool GetParamsFromJS(jsi::Runtime &rt, const jsi::Value *args);
|
|
83
|
+
WebCryptoKeyExportStatus DoExport(ByteSource* out);
|
|
84
|
+
private:
|
|
85
|
+
RsaKeyExportConfig params_;
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
struct RSACipherConfig final {
|
|
89
|
+
WebCryptoCipherMode mode;
|
|
90
|
+
std::shared_ptr<KeyObjectData> key;
|
|
91
|
+
ByteSource data;
|
|
92
|
+
RSAKeyVariant variant;
|
|
93
|
+
ByteSource label;
|
|
94
|
+
int padding = 0;
|
|
95
|
+
const EVP_MD* digest = nullptr;
|
|
96
|
+
|
|
97
|
+
RSACipherConfig() = default;
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
class RSACipher {
|
|
101
|
+
public:
|
|
102
|
+
RSACipher() {}
|
|
103
|
+
RSACipherConfig GetParamsFromJS(jsi::Runtime &rt, const jsi::Value *args);
|
|
104
|
+
WebCryptoCipherStatus DoCipher(const RSACipherConfig ¶ms, ByteSource *out);
|
|
105
|
+
};
|
|
106
|
+
|
|
73
107
|
} // namespace margelo
|
|
74
108
|
|
|
75
109
|
#endif /* MGLRsa_hpp */
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
#define MGLJSIUtils_h
|
|
10
10
|
|
|
11
11
|
#include <jsi/jsi.h>
|
|
12
|
+
#include <limits>
|
|
12
13
|
|
|
13
14
|
namespace jsi = facebook::jsi;
|
|
14
15
|
|
|
@@ -21,4 +22,20 @@ inline bool CheckSizeInt32(jsi::Runtime &runtime, jsi::ArrayBuffer &buffer) {
|
|
|
21
22
|
return buffer.size(runtime) <= INT_MAX;
|
|
22
23
|
}
|
|
23
24
|
|
|
25
|
+
inline bool CheckIsInt32(const jsi::Value &value) {
|
|
26
|
+
if (!value.isNumber()) {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
double d = value.asNumber();
|
|
30
|
+
return (d >= std::numeric_limits<int32_t>::lowest() && d <= std::numeric_limits<int32_t>::max());
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
inline bool CheckIsUint32(const jsi::Value &value) {
|
|
34
|
+
if (!value.isNumber()) {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
double d = value.asNumber();
|
|
38
|
+
return (d >= std::numeric_limits<uint32_t>::lowest() && d <= std::numeric_limits<uint32_t>::max());
|
|
39
|
+
}
|
|
40
|
+
|
|
24
41
|
#endif /* MGLJSIUtils_h */
|