react-native-quick-crypto 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/README.md +23 -6
  2. package/cpp/Cipher/MGLCipherHostObject.cpp +64 -48
  3. package/cpp/Cipher/MGLCipherKeys.cpp +1469 -0
  4. package/cpp/Cipher/MGLCipherKeys.h +124 -0
  5. package/cpp/Cipher/MGLCreateCipherInstaller.cpp +56 -53
  6. package/cpp/Cipher/MGLCreateCipherInstaller.h +5 -0
  7. package/cpp/Cipher/MGLCreateDecipherInstaller.cpp +56 -53
  8. package/cpp/Cipher/MGLGenerateKeyPairInstaller.cpp +107 -0
  9. package/cpp/Cipher/MGLGenerateKeyPairInstaller.h +32 -0
  10. package/cpp/Cipher/MGLGenerateKeyPairSyncInstaller.cpp +60 -0
  11. package/cpp/Cipher/MGLGenerateKeyPairSyncInstaller.h +35 -0
  12. package/cpp/Cipher/MGLPublicCipher.h +120 -0
  13. package/cpp/Cipher/MGLPublicCipherInstaller.h +113 -0
  14. package/cpp/Cipher/MGLRsa.cpp +188 -0
  15. package/cpp/Cipher/MGLRsa.h +61 -0
  16. package/cpp/JSIUtils/MGLJSIUtils.h +24 -0
  17. package/cpp/JSIUtils/MGLThreadAwareHostObject.h +1 -1
  18. package/cpp/MGLQuickCryptoHostObject.cpp +42 -3
  19. package/cpp/Utils/MGLUtils.cpp +156 -0
  20. package/cpp/Utils/MGLUtils.h +254 -0
  21. package/lib/commonjs/Cipher.js +307 -0
  22. package/lib/commonjs/Cipher.js.map +1 -1
  23. package/lib/commonjs/NativeQuickCrypto/Cipher.js +11 -0
  24. package/lib/commonjs/NativeQuickCrypto/Cipher.js.map +1 -1
  25. package/lib/commonjs/NativeQuickCrypto/NativeQuickCrypto.js.map +1 -1
  26. package/lib/commonjs/QuickCrypto.js +8 -0
  27. package/lib/commonjs/QuickCrypto.js.map +1 -1
  28. package/lib/commonjs/Utils.js +82 -1
  29. package/lib/commonjs/Utils.js.map +1 -1
  30. package/lib/commonjs/constants.js +86 -0
  31. package/lib/commonjs/constants.js.map +1 -0
  32. package/lib/commonjs/index.js +5 -0
  33. package/lib/commonjs/index.js.map +1 -1
  34. package/lib/commonjs/keys.js +207 -0
  35. package/lib/commonjs/keys.js.map +1 -0
  36. package/lib/module/Cipher.js +296 -3
  37. package/lib/module/Cipher.js.map +1 -1
  38. package/lib/module/NativeQuickCrypto/Cipher.js +9 -1
  39. package/lib/module/NativeQuickCrypto/Cipher.js.map +1 -1
  40. package/lib/module/NativeQuickCrypto/NativeQuickCrypto.js.map +1 -1
  41. package/lib/module/QuickCrypto.js +8 -1
  42. package/lib/module/QuickCrypto.js.map +1 -1
  43. package/lib/module/Utils.js +67 -1
  44. package/lib/module/Utils.js.map +1 -1
  45. package/lib/module/constants.js +79 -0
  46. package/lib/module/constants.js.map +1 -0
  47. package/lib/module/index.js +2 -0
  48. package/lib/module/index.js.map +1 -1
  49. package/lib/module/keys.js +193 -0
  50. package/lib/module/keys.js.map +1 -0
  51. package/lib/typescript/Cipher.d.ts +58 -1
  52. package/lib/typescript/NativeQuickCrypto/Cipher.d.ts +10 -0
  53. package/lib/typescript/NativeQuickCrypto/NativeQuickCrypto.d.ts +6 -1
  54. package/lib/typescript/QuickCrypto.d.ts +105 -1
  55. package/lib/typescript/Utils.d.ts +11 -0
  56. package/lib/typescript/constants.d.ts +75 -0
  57. package/lib/typescript/index.d.ts +2 -0
  58. package/lib/typescript/keys.d.ts +60 -0
  59. package/package.json +5 -5
  60. package/react-native-quick-crypto.podspec +1 -1
  61. package/src/.DS_Store +0 -0
  62. package/src/Cipher.ts +444 -3
  63. package/src/NativeQuickCrypto/Cipher.ts +44 -0
  64. package/src/NativeQuickCrypto/NativeQuickCrypto.ts +13 -1
  65. package/src/QuickCrypto.ts +12 -0
  66. package/src/Utils.ts +91 -0
  67. package/src/constants.ts +79 -0
  68. package/src/index.ts +4 -0
  69. package/src/keys.ts +297 -0
@@ -0,0 +1,120 @@
1
+ //
2
+ // MGLPublicCipher.h
3
+ // react-native-fast-crypto
4
+ //
5
+ // Created by Oscar on 17.06.22.
6
+ //
7
+
8
+ #ifndef MGLPublicCipher_h
9
+ #define MGLPublicCipher_h
10
+
11
+ #include <jsi/jsi.h>
12
+ #include <openssl/evp.h>
13
+
14
+ #include <optional>
15
+ #include <vector>
16
+
17
+ #include "MGLCipherKeys.h"
18
+ #ifdef ANDROID
19
+ #include "JSIUtils/MGLJSIUtils.h"
20
+ #include "JSIUtils/MGLTypedArray.h"
21
+ #else
22
+ #include "MGLJSIUtils.h"
23
+ #include "MGLTypedArray.h"
24
+ #include "logs.h"
25
+ #endif
26
+
27
+ namespace margelo {
28
+
29
+ namespace jsi = facebook::jsi;
30
+
31
+ class MGLPublicCipher {
32
+ public:
33
+ typedef int (*EVP_PKEY_cipher_init_t)(EVP_PKEY_CTX* ctx);
34
+ typedef int (*EVP_PKEY_cipher_t)(EVP_PKEY_CTX* ctx, unsigned char* out,
35
+ size_t* outlen, const unsigned char* in,
36
+ size_t inlen);
37
+
38
+ enum Operation { kPublic, kPrivate };
39
+
40
+ template <Operation operation, EVP_PKEY_cipher_init_t EVP_PKEY_cipher_init,
41
+ EVP_PKEY_cipher_t EVP_PKEY_cipher>
42
+ static std::optional<jsi::Value> Cipher(jsi::Runtime& runtime,
43
+ const ManagedEVPPKey& pkey,
44
+ int padding, const EVP_MD* digest,
45
+ const jsi::Value& oaep_label,
46
+ jsi::ArrayBuffer& data);
47
+ };
48
+
49
+ template <MGLPublicCipher::Operation operation,
50
+ MGLPublicCipher::EVP_PKEY_cipher_init_t EVP_PKEY_cipher_init,
51
+ MGLPublicCipher::EVP_PKEY_cipher_t EVP_PKEY_cipher>
52
+ std::optional<jsi::Value> MGLPublicCipher::Cipher(jsi::Runtime& runtime,
53
+ const ManagedEVPPKey& pkey,
54
+ int padding,
55
+ const EVP_MD* digest,
56
+ const jsi::Value& oaep_label,
57
+ jsi::ArrayBuffer& data) {
58
+ EVPKeyCtxPointer ctx(EVP_PKEY_CTX_new(pkey.get(), nullptr));
59
+
60
+ if (!ctx) {
61
+ return {};
62
+ }
63
+
64
+ if (EVP_PKEY_cipher_init(ctx.get()) <= 0) {
65
+ return {};
66
+ }
67
+
68
+ if (EVP_PKEY_CTX_set_rsa_padding(ctx.get(), padding) <= 0) {
69
+ return {};
70
+ }
71
+
72
+ if (digest != nullptr) {
73
+ if (EVP_PKEY_CTX_set_rsa_oaep_md(ctx.get(), digest) <= 0) {
74
+ return {};
75
+ }
76
+ }
77
+
78
+ if (!oaep_label.isUndefined()) {
79
+ auto oaep_label_buffer =
80
+ oaep_label.asObject(runtime).getArrayBuffer(runtime);
81
+ // OpenSSL takes ownership of the label, so we need to create a copy.
82
+ void* label = OPENSSL_memdup(oaep_label_buffer.data(runtime),
83
+ oaep_label_buffer.size(runtime));
84
+ if (label == nullptr) {
85
+ throw new jsi::JSError(runtime, "Error openSSL memdump oaep label");
86
+ }
87
+
88
+ if (0 >= EVP_PKEY_CTX_set0_rsa_oaep_label(
89
+ ctx.get(), static_cast<unsigned char*>(label),
90
+ static_cast<int>(oaep_label_buffer.size(runtime)))) {
91
+ OPENSSL_free(label);
92
+ return {};
93
+ }
94
+ }
95
+
96
+ // First pass without storing to get the out_len
97
+ size_t out_len = 0;
98
+ if (EVP_PKEY_cipher(ctx.get(), nullptr, &out_len, data.data(runtime),
99
+ data.size(runtime)) <= 0) {
100
+ return {};
101
+ }
102
+
103
+ std::vector<unsigned char> out_vec(out_len);
104
+
105
+ if (EVP_PKEY_cipher(ctx.get(), out_vec.data(), &out_len, data.data(runtime),
106
+ data.size(runtime)) <= 0) {
107
+ return {};
108
+ }
109
+
110
+ // trim unnecessary data
111
+ std::vector<unsigned char> helper_vec(out_vec.data(),
112
+ out_vec.data() + out_len);
113
+ MGLTypedArray<MGLTypedArrayKind::Uint8Array> outBuffer(runtime, out_len);
114
+ outBuffer.update(runtime, helper_vec);
115
+
116
+ return outBuffer;
117
+ }
118
+ } // namespace margelo
119
+
120
+ #endif /* MGLPublicCipher_h */
@@ -0,0 +1,113 @@
1
+ //
2
+ // MGLPrivateDecryptInstaller.h
3
+ // react-native-quick-crypto
4
+ //
5
+ // Created by Oscar on 28.06.22.
6
+ //
7
+
8
+ #ifndef MGLPublicCipherInstaller_h
9
+ #define MGLPublicCipherInstaller_h
10
+
11
+ #include <jsi/jsi.h>
12
+ #include <openssl/evp.h>
13
+
14
+ #include <iostream>
15
+ #include <memory>
16
+ #include <optional>
17
+ #include <string>
18
+ #include <utility>
19
+ #include <vector>
20
+
21
+ #include "MGLCipherKeys.h"
22
+ #include "MGLPublicCipher.h"
23
+
24
+ #ifdef ANDROID
25
+ #include "JSIUtils/MGLJSIUtils.h"
26
+ #include "JSIUtils/MGLSmartHostObject.h"
27
+ #include "JSIUtils/MGLTypedArray.h"
28
+ #else
29
+ #include "MGLJSIUtils.h"
30
+ #include "MGLSmartHostObject.h"
31
+ #include "MGLTypedArray.h"
32
+ #endif
33
+
34
+ namespace margelo {
35
+ namespace jsi = facebook::jsi;
36
+
37
+ // "publicEncrypt", "publicDecrypt", "privateEncrypt", "privateDecrypt" all use
38
+ // the same key extraction logic, only vary in the final openSSL call, so this
39
+ // is a template that accepts and incoming template function, think of it as a
40
+ // weird lambda before real lambdas Because this is a template, the
41
+ // implementation needs to be in this header to prevent linker failure
42
+ template <MGLPublicCipher::Operation operation,
43
+ MGLPublicCipher::EVP_PKEY_cipher_init_t EVP_PKEY_cipher_init,
44
+ MGLPublicCipher::EVP_PKEY_cipher_t EVP_PKEY_cipher>
45
+ FieldDefinition getPublicCipherFieldDefinition(
46
+ std::string name, std::shared_ptr<react::CallInvoker> jsCallInvoker,
47
+ std::shared_ptr<DispatchQueue::dispatch_queue> workerQueue) {
48
+ return buildPair(
49
+ name, JSIF([=]) {
50
+ // there is a variable amount of parameters passed depending on the
51
+ // scheme therefore making param validation on this level makes little
52
+ // sense everything should be done on JS, which makes this a bit unsafe
53
+ // but it's acceptable
54
+ unsigned int offset = 0;
55
+
56
+ ManagedEVPPKey pkey = ManagedEVPPKey::GetPublicOrPrivateKeyFromJs(
57
+ runtime, arguments, &offset);
58
+
59
+ if (!pkey) {
60
+ jsi::detail::throwJSError(runtime, "Could not generate key");
61
+ throw new jsi::JSError(runtime, "Could not generate key");
62
+ }
63
+
64
+ auto buf = arguments[offset].asObject(runtime).getArrayBuffer(runtime);
65
+ if (!CheckSizeInt32(runtime, buf)) {
66
+ jsi::detail::throwJSError(runtime, "Data buffer is too long");
67
+ throw new jsi::JSError(runtime, "Data buffer is too long");
68
+ }
69
+
70
+ uint32_t padding =
71
+ static_cast<uint32_t>(arguments[offset + 1].getNumber());
72
+ if (!padding) {
73
+ jsi::detail::throwJSError(runtime, "Invalid padding");
74
+ throw new jsi::JSError(runtime, "Invalid padding");
75
+ }
76
+
77
+ const EVP_MD* digest = nullptr;
78
+ if (arguments[offset + 2].isString()) {
79
+ auto oaep_str =
80
+ arguments[offset + 2].getString(runtime).utf8(runtime);
81
+
82
+ digest = EVP_get_digestbyname(oaep_str.c_str());
83
+ if (digest == nullptr) {
84
+ jsi::detail::throwJSError(runtime, "Invalid digest (oaep_str)");
85
+ throw new jsi::JSError(runtime, "Invalid digest (oaep_str)");
86
+ }
87
+ }
88
+
89
+ if (!arguments[offset + 3].isUndefined()) {
90
+ auto oaep_label_buffer =
91
+ arguments[offset + 3].getObject(runtime).getArrayBuffer(runtime);
92
+ if (!CheckSizeInt32(runtime, oaep_label_buffer)) {
93
+ jsi::detail::throwJSError(runtime, "oaep_label buffer is too long");
94
+ throw new jsi::JSError(runtime, "oaep_label buffer is too long");
95
+ }
96
+ }
97
+
98
+ std::optional<jsi::Value> out =
99
+ MGLPublicCipher::Cipher<operation, EVP_PKEY_cipher_init,
100
+ EVP_PKEY_cipher>(
101
+ runtime, pkey, padding, digest, arguments[offset + 3], buf);
102
+
103
+ if (!out.has_value()) {
104
+ jsi::detail::throwJSError(runtime, "Failed to decrypt");
105
+ throw new jsi::JSError(runtime, "Failed to decrypt");
106
+ }
107
+
108
+ return out.value().getObject(runtime);
109
+ });
110
+ }
111
+ } // namespace margelo
112
+
113
+ #endif /* MGLPublicCipherInstaller_h */
@@ -0,0 +1,188 @@
1
+ //
2
+ // MGLRsa.cpp
3
+ // react-native-quick-crypto
4
+ //
5
+ // Created by Oscar on 22.06.22.
6
+ //
7
+
8
+ #include "MGLRsa.h"
9
+
10
+ #include <utility>
11
+
12
+ namespace margelo {
13
+
14
+ namespace jsi = facebook::jsi;
15
+
16
+ EVPKeyCtxPointer setup(std::shared_ptr<RsaKeyPairGenConfig> config) {
17
+ EVPKeyCtxPointer ctx(EVP_PKEY_CTX_new_id(
18
+ config->variant == kKeyVariantRSA_PSS ? EVP_PKEY_RSA_PSS : EVP_PKEY_RSA,
19
+ nullptr));
20
+
21
+ if (EVP_PKEY_keygen_init(ctx.get()) <= 0) return EVPKeyCtxPointer();
22
+
23
+ if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx.get(), config->modulus_bits) <= 0) {
24
+ return EVPKeyCtxPointer();
25
+ }
26
+
27
+ // 0x10001 is the default RSA exponent.
28
+ if (config->exponent != 0x10001) {
29
+ BignumPointer bn(BN_new());
30
+ // CHECK_NOT_NULL(bn.get());
31
+ BN_set_word(bn.get(), config->exponent);
32
+ // EVP_CTX accepts ownership of bn on success.
33
+ if (EVP_PKEY_CTX_set_rsa_keygen_pubexp(ctx.get(), bn.get()) <= 0) {
34
+ return EVPKeyCtxPointer();
35
+ }
36
+
37
+ bn.release();
38
+ }
39
+
40
+ if (config->variant == kKeyVariantRSA_PSS) {
41
+ if (config->md != nullptr &&
42
+ EVP_PKEY_CTX_set_rsa_pss_keygen_md(ctx.get(), config->md) <= 0) {
43
+ return EVPKeyCtxPointer();
44
+ }
45
+
46
+ // TODO(tniessen): This appears to only be necessary in OpenSSL 3, while
47
+ // OpenSSL 1.1.1 behaves as recommended by RFC 8017 and defaults the MGF1
48
+ // hash algorithm to the RSA-PSS hashAlgorithm. Remove this code if the
49
+ // behavior of OpenSSL 3 changes.
50
+ const EVP_MD* mgf1_md = config->mgf1_md;
51
+ if (mgf1_md == nullptr && config->md != nullptr) {
52
+ mgf1_md = config->md;
53
+ }
54
+
55
+ if (mgf1_md != nullptr &&
56
+ EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md(ctx.get(), mgf1_md) <= 0) {
57
+ return EVPKeyCtxPointer();
58
+ }
59
+
60
+ int saltlen = config->saltlen;
61
+ if (saltlen < 0 && config->md != nullptr) {
62
+ saltlen = EVP_MD_size(config->md);
63
+ }
64
+
65
+ if (saltlen >= 0 &&
66
+ EVP_PKEY_CTX_set_rsa_pss_keygen_saltlen(ctx.get(), saltlen) <= 0) {
67
+ return EVPKeyCtxPointer();
68
+ }
69
+ }
70
+
71
+ return ctx;
72
+ }
73
+
74
+ RsaKeyPairGenConfig prepareRsaKeyGenConfig(jsi::Runtime& runtime,
75
+ const jsi::Value* arguments) {
76
+ RsaKeyPairGenConfig config = RsaKeyPairGenConfig();
77
+
78
+ // This is a funky one: depending on which encryption scheme you are
79
+ // using, there is a variable number of arguments that will need to be
80
+ // parsed, therefore this pointer will be used by the internal functions
81
+ // as they go reading the arguments based on the selected scheme. I
82
+ // tried to keep as close to the node implementation to make future
83
+ // debugging easier
84
+ unsigned int offset = 0;
85
+
86
+ // TODO(osp)
87
+ // CHECK(args[*offset]->IsUint32()); // Variant
88
+ // CHECK(args[*offset + 1]->IsUint32()); // Modulus bits
89
+ // CHECK(args[*offset + 2]->IsUint32()); // Exponent
90
+ config.variant =
91
+ static_cast<RSAKeyVariant>((int)arguments[offset].asNumber());
92
+
93
+ // TODO(osp)
94
+ // CHECK_IMPLIES(params->params.variant != kKeyVariantRSA_PSS,
95
+ // args.Length() == 10);
96
+ // CHECK_IMPLIES(params->params.variant == kKeyVariantRSA_PSS,
97
+ // args.Length() == 13);
98
+ config.modulus_bits =
99
+ static_cast<unsigned int>(arguments[offset + 1].asNumber());
100
+ config.exponent = static_cast<unsigned int>(arguments[offset + 2].asNumber());
101
+
102
+ offset += 3;
103
+
104
+ if (config.variant == kKeyVariantRSA_PSS) {
105
+ if (!arguments[offset].isUndefined()) {
106
+ // TODO(osp) CHECK(string)
107
+ config.md = EVP_get_digestbyname(
108
+ arguments[offset].asString(runtime).utf8(runtime).c_str());
109
+
110
+ if (config.md == nullptr) {
111
+ jsi::detail::throwJSError(runtime, "invalid digest");
112
+ throw new jsi::JSError(runtime, "invalid digest");
113
+ }
114
+ }
115
+
116
+ if (!arguments[offset + 1].isUndefined()) {
117
+ // TODO(osp) CHECK(string)
118
+ config.mgf1_md = EVP_get_digestbyname(
119
+ arguments[offset + 1].asString(runtime).utf8(runtime).c_str());
120
+
121
+ if (config.mgf1_md == nullptr) {
122
+ jsi::detail::throwJSError(runtime, "invalid digest");
123
+ throw new jsi::JSError(runtime, "invalid digest");
124
+ }
125
+ }
126
+
127
+ if (!arguments[offset + 2].isUndefined()) {
128
+ // CHECK(args[*offset + 2]->IsInt32());
129
+ config.saltlen = static_cast<int>(arguments[offset + 2].asNumber());
130
+
131
+ if (config.saltlen < 0) {
132
+ jsi::detail::throwJSError(runtime, "salt length is out of range");
133
+ throw new jsi::JSError(runtime, "salt length is out of range");
134
+ }
135
+ }
136
+
137
+ offset += 3;
138
+ }
139
+
140
+ config.public_key_encoding = ManagedEVPPKey::GetPublicKeyEncodingFromJs(
141
+ runtime, arguments, &offset, kKeyContextGenerate);
142
+
143
+ auto private_key_encoding = ManagedEVPPKey::GetPrivateKeyEncodingFromJs(
144
+ runtime, arguments, &offset, kKeyContextGenerate);
145
+
146
+ if (!private_key_encoding.IsEmpty()) {
147
+ config.private_key_encoding = private_key_encoding.Release();
148
+ }
149
+
150
+ return config;
151
+ }
152
+
153
+ std::pair<StringOrBuffer, StringOrBuffer> generateRSAKeyPair(
154
+ jsi::Runtime& runtime, std::shared_ptr<RsaKeyPairGenConfig> config) {
155
+ CheckEntropy();
156
+
157
+ EVPKeyCtxPointer ctx = setup(config);
158
+
159
+ if (!ctx) {
160
+ jsi::detail::throwJSError(runtime, "Error on key generation job");
161
+ throw new jsi::JSError(runtime, "Error on key generation job");
162
+ }
163
+
164
+ // Generate the key
165
+ EVP_PKEY* pkey = nullptr;
166
+ if (!EVP_PKEY_keygen(ctx.get(), &pkey)) {
167
+ jsi::detail::throwJSError(runtime, "Error generating key");
168
+ throw new jsi::JSError(runtime, "Error generating key");
169
+ }
170
+
171
+ config->key = ManagedEVPPKey(EVPKeyPointer(pkey));
172
+
173
+ std::optional<StringOrBuffer> publicBuffer =
174
+ ManagedEVPPKey::ToEncodedPublicKey(runtime, std::move(config->key),
175
+ config->public_key_encoding);
176
+ std::optional<StringOrBuffer> privateBuffer =
177
+ ManagedEVPPKey::ToEncodedPrivateKey(runtime, std::move(config->key),
178
+ config->private_key_encoding);
179
+
180
+ if (!publicBuffer.has_value() || !privateBuffer.has_value()) {
181
+ jsi::detail::throwJSError(runtime,
182
+ "Failed to encode public and/or private key");
183
+ }
184
+
185
+ return std::make_pair(publicBuffer.value(), privateBuffer.value());
186
+ }
187
+
188
+ } // namespace margelo
@@ -0,0 +1,61 @@
1
+ //
2
+ // MGLRsa.hpp
3
+ // react-native-quick-crypto
4
+ //
5
+ // Created by Oscar on 22.06.22.
6
+ //
7
+
8
+ #ifndef MGLRsa_hpp
9
+ #define MGLRsa_hpp
10
+
11
+ #include <jsi/jsi.h>
12
+
13
+ #include <memory>
14
+ #include <optional>
15
+ #include <utility>
16
+
17
+ #include "MGLCipherKeys.h"
18
+ #include "MGLUtils.h"
19
+
20
+ namespace margelo {
21
+
22
+ namespace jsi = facebook::jsi;
23
+
24
+ enum RSAKeyVariant {
25
+ kKeyVariantRSA_SSA_PKCS1_v1_5,
26
+ kKeyVariantRSA_PSS,
27
+ kKeyVariantRSA_OAEP
28
+ };
29
+
30
+ // On node there is a complete madness of structs/classes that encapsulate and
31
+ // initialize the data in a generic manner this is to be later be used to
32
+ // generate the keys in a thread-safe manner (I think) I'm however too dumb and
33
+ // after ~4hrs I have given up on trying to replicate/extract the important
34
+ // parts For now I'm storing a single config param, a generic abstractino is
35
+ // necessary for more schemes. this struct is just a very simplified version
36
+ // meant to carry information around
37
+ struct RsaKeyPairGenConfig {
38
+ PublicKeyEncodingConfig public_key_encoding;
39
+ PrivateKeyEncodingConfig private_key_encoding;
40
+ ManagedEVPPKey key;
41
+
42
+ RSAKeyVariant variant;
43
+ unsigned int modulus_bits;
44
+ unsigned int exponent;
45
+
46
+ // The following options are used for RSA-PSS. If any of them are set, a
47
+ // RSASSA-PSS-params sequence will be added to the key.
48
+ const EVP_MD* md = nullptr;
49
+ const EVP_MD* mgf1_md = nullptr;
50
+ int saltlen = -1;
51
+ };
52
+
53
+ RsaKeyPairGenConfig prepareRsaKeyGenConfig(jsi::Runtime& runtime,
54
+ const jsi::Value* arguments);
55
+
56
+ std::pair<StringOrBuffer, StringOrBuffer> generateRSAKeyPair(
57
+ jsi::Runtime& runtime, std::shared_ptr<RsaKeyPairGenConfig> config);
58
+
59
+ } // namespace margelo
60
+
61
+ #endif /* MGLRsa_hpp */
@@ -0,0 +1,24 @@
1
+ //
2
+ // MGLJSIUtils.h
3
+ // Pods
4
+ //
5
+ // Created by Oscar on 20.06.22.
6
+ //
7
+
8
+ #ifndef MGLJSIUtils_h
9
+ #define MGLJSIUtils_h
10
+
11
+ #include <jsi/jsi.h>
12
+
13
+ namespace jsi = facebook::jsi;
14
+
15
+ inline bool CheckIsArrayBuffer(jsi::Runtime &runtime, const jsi::Value &value) {
16
+ return !value.isNull() && !value.isUndefined() && value.isObject() &&
17
+ value.asObject(runtime).isArrayBuffer(runtime);
18
+ }
19
+
20
+ inline bool CheckSizeInt32(jsi::Runtime &runtime, jsi::ArrayBuffer &buffer) {
21
+ return buffer.size(runtime) <= INT_MAX;
22
+ }
23
+
24
+ #endif /* MGLJSIUtils_h */
@@ -13,7 +13,7 @@
13
13
  #ifdef ONANDROID
14
14
  #include "Utils/MGLDispatchQueue.h"
15
15
  #else
16
- #include "../Utils/MGLDispatchQueue.h"
16
+ #include "MGLDispatchQueue.h"
17
17
  #endif
18
18
 
19
19
  namespace margelo {
@@ -5,11 +5,14 @@
5
5
  #include <jsi/jsi.h>
6
6
 
7
7
  #include <memory>
8
+ #include <string>
8
9
  #include <vector>
9
10
 
10
11
  #ifdef ANDROID
11
12
  #include "Cipher/MGLCreateCipherInstaller.h"
12
13
  #include "Cipher/MGLCreateDecipherInstaller.h"
14
+ #include "Cipher/MGLPublicCipher.h"
15
+ #include "Cipher/MGLPublicCipherInstaller.h"
13
16
  #include "HMAC/MGLHmacInstaller.h"
14
17
  #include "Hash/MGLHashInstaller.h"
15
18
  #include "Random/MGLRandomHostObject.h"
@@ -17,11 +20,14 @@
17
20
  #else
18
21
  #include "MGLCreateCipherInstaller.h"
19
22
  #include "MGLCreateDecipherInstaller.h"
23
+ #include "MGLGenerateKeyPairInstaller.h"
24
+ #include "MGLGenerateKeyPairSyncInstaller.h"
20
25
  #include "MGLHashInstaller.h"
21
26
  #include "MGLHmacInstaller.h"
22
27
  #include "MGLPbkdf2HostObject.h"
28
+ #include "MGLPublicCipher.h"
29
+ #include "MGLPublicCipherInstaller.h"
23
30
  #include "MGLRandomHostObject.h"
24
-
25
31
  #endif
26
32
 
27
33
  namespace margelo {
@@ -38,14 +44,47 @@ MGLQuickCryptoHostObject::MGLQuickCryptoHostObject(
38
44
  // HashInstaller
39
45
  this->fields.push_back(getHashFieldDefinition(jsCallInvoker, workerQueue));
40
46
 
41
- // CreateCipherInstaller
47
+ // createCipher
42
48
  this->fields.push_back(
43
49
  getCreateCipherFieldDefinition(jsCallInvoker, workerQueue));
44
50
 
45
- // CreateDecipherInstaller
51
+ // createDecipher
46
52
  this->fields.push_back(
47
53
  getCreateDecipherFieldDefinition(jsCallInvoker, workerQueue));
48
54
 
55
+ // publicEncrypt
56
+ this->fields.push_back(
57
+ getPublicCipherFieldDefinition<MGLPublicCipher::kPublic,
58
+ EVP_PKEY_encrypt_init, EVP_PKEY_encrypt>(
59
+ "publicEncrypt", jsCallInvoker, workerQueue));
60
+
61
+ // privateDecrypt
62
+ this->fields.push_back(
63
+ getPublicCipherFieldDefinition<MGLPublicCipher::kPrivate,
64
+ EVP_PKEY_decrypt_init, EVP_PKEY_decrypt>(
65
+ "privateDecrypt", jsCallInvoker, workerQueue));
66
+
67
+ // privateEncrypt
68
+ this->fields.push_back(
69
+ getPublicCipherFieldDefinition<MGLPublicCipher::kPrivate,
70
+ EVP_PKEY_sign_init, EVP_PKEY_sign>(
71
+ "privateEncrypt", jsCallInvoker, workerQueue));
72
+
73
+ // publicDecrypt
74
+ this->fields.push_back(
75
+ getPublicCipherFieldDefinition<MGLPublicCipher::kPublic,
76
+ EVP_PKEY_verify_recover_init,
77
+ EVP_PKEY_verify_recover>(
78
+ "publicDecrypt", jsCallInvoker, workerQueue));
79
+
80
+ // generateKeyPair
81
+ this->fields.push_back(
82
+ getGenerateKeyPairFieldDefinition(jsCallInvoker, workerQueue));
83
+
84
+ // generateKeyPairSync
85
+ this->fields.push_back(
86
+ getGenerateKeyPairSyncFieldDefinition(jsCallInvoker, workerQueue));
87
+
49
88
  // Pbkdf2HostObject
50
89
  this->fields.push_back(JSI_VALUE("pbkdf2", {
51
90
  auto hostObject =