react-native-quick-crypto 0.2.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 (143) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +84 -0
  3. package/android/.DS_Store +0 -0
  4. package/android/CMakeLists.txt +117 -0
  5. package/android/build.gradle +367 -0
  6. package/android/gradle/.DS_Store +0 -0
  7. package/android/gradle/wrapper/gradle-wrapper.jar +0 -0
  8. package/android/gradle/wrapper/gradle-wrapper.properties +5 -0
  9. package/android/gradle.properties +6 -0
  10. package/android/gradlew +183 -0
  11. package/android/gradlew.bat +100 -0
  12. package/android/src/.DS_Store +0 -0
  13. package/android/src/main/.DS_Store +0 -0
  14. package/android/src/main/AndroidManifest.xml +4 -0
  15. package/android/src/main/cpp/cpp-adapter.cpp +60 -0
  16. package/android/src/main/java/.DS_Store +0 -0
  17. package/android/src/main/java/com/.DS_Store +0 -0
  18. package/android/src/main/java/com/reactnativequickcrypto/QuickCryptoModule.java +70 -0
  19. package/android/src/main/java/com/reactnativequickcrypto/QuickCryptoPackage.java +26 -0
  20. package/cpp/.DS_Store +0 -0
  21. package/cpp/Cipher/MGLCipherHostObject.cpp +632 -0
  22. package/cpp/Cipher/MGLCipherHostObject.h +90 -0
  23. package/cpp/Cipher/MGLCreateCipherInstaller.cpp +74 -0
  24. package/cpp/Cipher/MGLCreateCipherInstaller.h +17 -0
  25. package/cpp/Cipher/MGLCreateDecipherInstaller.cpp +74 -0
  26. package/cpp/Cipher/MGLCreateDecipherInstaller.h +17 -0
  27. package/cpp/HMAC/MGLHmacHostObject.cpp +95 -0
  28. package/cpp/HMAC/MGLHmacHostObject.h +39 -0
  29. package/cpp/HMAC/MGLHmacInstaller.cpp +43 -0
  30. package/cpp/HMAC/MGLHmacInstaller.h +20 -0
  31. package/cpp/Hash/MGLHashHostObject.cpp +147 -0
  32. package/cpp/Hash/MGLHashHostObject.h +53 -0
  33. package/cpp/Hash/MGLHashInstaller.cpp +46 -0
  34. package/cpp/Hash/MGLHashInstaller.h +20 -0
  35. package/cpp/JSIUtils/MGLJSIMacros.h +37 -0
  36. package/cpp/JSIUtils/MGLSmartHostObject.cpp +43 -0
  37. package/cpp/JSIUtils/MGLSmartHostObject.h +46 -0
  38. package/cpp/JSIUtils/MGLThreadAwareHostObject.cpp +24 -0
  39. package/cpp/JSIUtils/MGLThreadAwareHostObject.h +43 -0
  40. package/cpp/JSIUtils/MGLTypedArray.cpp +325 -0
  41. package/cpp/JSIUtils/MGLTypedArray.h +160 -0
  42. package/cpp/MGLQuickCryptoHostObject.cpp +64 -0
  43. package/cpp/MGLQuickCryptoHostObject.h +30 -0
  44. package/cpp/Random/MGLRandomHostObject.cpp +89 -0
  45. package/cpp/Random/MGLRandomHostObject.h +27 -0
  46. package/cpp/Utils/MGLDispatchQueue.cpp +75 -0
  47. package/cpp/Utils/MGLDispatchQueue.h +55 -0
  48. package/cpp/Utils/logs.h +38 -0
  49. package/cpp/fastpbkdf2/MGLPbkdf2HostObject.cpp +164 -0
  50. package/cpp/fastpbkdf2/MGLPbkdf2HostObject.h +29 -0
  51. package/cpp/fastpbkdf2/fastpbkdf2.c +352 -0
  52. package/cpp/fastpbkdf2/fastpbkdf2.h +68 -0
  53. package/ios/.DS_Store +0 -0
  54. package/ios/QuickCrypto.xcodeproj/project.pbxproj +274 -0
  55. package/ios/QuickCryptoModule.h +5 -0
  56. package/ios/QuickCryptoModule.mm +42 -0
  57. package/lib/.DS_Store +0 -0
  58. package/lib/commonjs/Cipher.js +293 -0
  59. package/lib/commonjs/Cipher.js.map +1 -0
  60. package/lib/commonjs/Hash.js +102 -0
  61. package/lib/commonjs/Hash.js.map +1 -0
  62. package/lib/commonjs/Hmac.js +104 -0
  63. package/lib/commonjs/Hmac.js.map +1 -0
  64. package/lib/commonjs/NativeQuickCrypto/Cipher.js +6 -0
  65. package/lib/commonjs/NativeQuickCrypto/Cipher.js.map +1 -0
  66. package/lib/commonjs/NativeQuickCrypto/NativeQuickCrypto.js +61 -0
  67. package/lib/commonjs/NativeQuickCrypto/NativeQuickCrypto.js.map +1 -0
  68. package/lib/commonjs/NativeQuickCrypto/hash.js +2 -0
  69. package/lib/commonjs/NativeQuickCrypto/hash.js.map +1 -0
  70. package/lib/commonjs/NativeQuickCrypto/hmac.js +2 -0
  71. package/lib/commonjs/NativeQuickCrypto/hmac.js.map +1 -0
  72. package/lib/commonjs/NativeQuickCrypto/pbkdf2.js +2 -0
  73. package/lib/commonjs/NativeQuickCrypto/pbkdf2.js.map +1 -0
  74. package/lib/commonjs/NativeQuickCrypto/random.js +2 -0
  75. package/lib/commonjs/NativeQuickCrypto/random.js.map +1 -0
  76. package/lib/commonjs/QuickCrypto.js +35 -0
  77. package/lib/commonjs/QuickCrypto.js.map +1 -0
  78. package/lib/commonjs/Utils.js +152 -0
  79. package/lib/commonjs/Utils.js.map +1 -0
  80. package/lib/commonjs/index.js +19 -0
  81. package/lib/commonjs/index.js.map +1 -0
  82. package/lib/commonjs/pbkdf2.js +64 -0
  83. package/lib/commonjs/pbkdf2.js.map +1 -0
  84. package/lib/commonjs/random.js +213 -0
  85. package/lib/commonjs/random.js.map +1 -0
  86. package/lib/module/Cipher.js +287 -0
  87. package/lib/module/Cipher.js.map +1 -0
  88. package/lib/module/Hash.js +87 -0
  89. package/lib/module/Hash.js.map +1 -0
  90. package/lib/module/Hmac.js +90 -0
  91. package/lib/module/Hmac.js.map +1 -0
  92. package/lib/module/NativeQuickCrypto/Cipher.js +2 -0
  93. package/lib/module/NativeQuickCrypto/Cipher.js.map +1 -0
  94. package/lib/module/NativeQuickCrypto/NativeQuickCrypto.js +53 -0
  95. package/lib/module/NativeQuickCrypto/NativeQuickCrypto.js.map +1 -0
  96. package/lib/module/NativeQuickCrypto/hash.js +2 -0
  97. package/lib/module/NativeQuickCrypto/hash.js.map +1 -0
  98. package/lib/module/NativeQuickCrypto/hmac.js +2 -0
  99. package/lib/module/NativeQuickCrypto/hmac.js.map +1 -0
  100. package/lib/module/NativeQuickCrypto/pbkdf2.js +2 -0
  101. package/lib/module/NativeQuickCrypto/pbkdf2.js.map +1 -0
  102. package/lib/module/NativeQuickCrypto/random.js +2 -0
  103. package/lib/module/NativeQuickCrypto/random.js.map +1 -0
  104. package/lib/module/QuickCrypto.js +18 -0
  105. package/lib/module/QuickCrypto.js.map +1 -0
  106. package/lib/module/Utils.js +131 -0
  107. package/lib/module/Utils.js.map +1 -0
  108. package/lib/module/index.js +2 -0
  109. package/lib/module/index.js.map +1 -0
  110. package/lib/module/pbkdf2.js +51 -0
  111. package/lib/module/pbkdf2.js.map +1 -0
  112. package/lib/module/random.js +190 -0
  113. package/lib/module/random.js.map +1 -0
  114. package/lib/typescript/Cipher.d.ts +30 -0
  115. package/lib/typescript/Hash.d.ts +44 -0
  116. package/lib/typescript/Hmac.d.ts +37 -0
  117. package/lib/typescript/NativeQuickCrypto/Cipher.d.ts +22 -0
  118. package/lib/typescript/NativeQuickCrypto/NativeQuickCrypto.d.ts +19 -0
  119. package/lib/typescript/NativeQuickCrypto/hash.d.ts +6 -0
  120. package/lib/typescript/NativeQuickCrypto/hmac.d.ts +5 -0
  121. package/lib/typescript/NativeQuickCrypto/pbkdf2.d.ts +4 -0
  122. package/lib/typescript/NativeQuickCrypto/random.d.ts +4 -0
  123. package/lib/typescript/QuickCrypto.d.ts +31 -0
  124. package/lib/typescript/Utils.d.ts +13 -0
  125. package/lib/typescript/index.d.ts +1 -0
  126. package/lib/typescript/pbkdf2.d.ts +9 -0
  127. package/lib/typescript/random.d.ts +20 -0
  128. package/package.json +168 -0
  129. package/react-native-quick-crypto.podspec +44 -0
  130. package/src/Cipher.ts +322 -0
  131. package/src/Hash.ts +98 -0
  132. package/src/Hmac.ts +107 -0
  133. package/src/NativeQuickCrypto/Cipher.ts +25 -0
  134. package/src/NativeQuickCrypto/NativeQuickCrypto.ts +79 -0
  135. package/src/NativeQuickCrypto/hash.ts +10 -0
  136. package/src/NativeQuickCrypto/hmac.ts +9 -0
  137. package/src/NativeQuickCrypto/pbkdf2.ts +16 -0
  138. package/src/NativeQuickCrypto/random.ts +12 -0
  139. package/src/QuickCrypto.ts +23 -0
  140. package/src/Utils.ts +151 -0
  141. package/src/index.ts +1 -0
  142. package/src/pbkdf2.ts +96 -0
  143. package/src/random.ts +277 -0
@@ -0,0 +1,90 @@
1
+ //
2
+ // Created by Oscar on 07.06.22.
3
+ //
4
+
5
+ #ifndef MGLCipherHostObject_h
6
+ #define MGLCipherHostObject_h
7
+
8
+ #include <jsi/jsi.h>
9
+ #include <openssl/evp.h>
10
+
11
+ #include <memory>
12
+ #include <string>
13
+
14
+ #ifdef ANDROID
15
+ #include "JSIUtils/MGLSmartHostObject.h"
16
+ #else
17
+ #include "MGLSmartHostObject.h"
18
+ #endif
19
+
20
+ namespace margelo {
21
+
22
+ namespace jsi = facebook::jsi;
23
+
24
+ class MGLCipherHostObject : public MGLSmartHostObject {
25
+ protected:
26
+ enum CipherKind { kCipher, kDecipher };
27
+ enum UpdateResult { kSuccess, kErrorMessageSize, kErrorState };
28
+ enum AuthTagState { kAuthTagUnknown, kAuthTagKnown, kAuthTagPassedToOpenSSL };
29
+
30
+ public:
31
+ // TODO(osp) Why does an empty constructor need to be here and not on
32
+ // HashHostObject?
33
+ explicit MGLCipherHostObject(
34
+ std::shared_ptr<react::CallInvoker> jsCallInvoker,
35
+ std::shared_ptr<DispatchQueue::dispatch_queue> workerQueue);
36
+
37
+ explicit MGLCipherHostObject(
38
+ MGLCipherHostObject *other,
39
+ std::shared_ptr<react::CallInvoker> jsCallInvoker,
40
+ std::shared_ptr<DispatchQueue::dispatch_queue> workerQueue);
41
+
42
+ // Without iv
43
+ explicit MGLCipherHostObject(
44
+ const std::string &cipher_type, jsi::ArrayBuffer *cipher_key,
45
+ bool isCipher, unsigned int auth_tag_len, jsi::Runtime &runtime,
46
+ std::shared_ptr<react::CallInvoker> jsCallInvoker,
47
+ std::shared_ptr<DispatchQueue::dispatch_queue> workerQueue);
48
+
49
+ // With iv
50
+ explicit MGLCipherHostObject(
51
+ const std::string &cipher_type, jsi::ArrayBuffer *cipher_key,
52
+ bool isCipher, unsigned int auth_tag_len, jsi::ArrayBuffer *iv,
53
+ jsi::Runtime &runtime, std::shared_ptr<react::CallInvoker> jsCallInvoker,
54
+ std::shared_ptr<DispatchQueue::dispatch_queue> workerQueue);
55
+
56
+ void commonInit(jsi::Runtime &runtime, const char *cipher_type,
57
+ const EVP_CIPHER *cipher, const unsigned char *key,
58
+ int key_len, const unsigned char *iv, int iv_len,
59
+ unsigned int auth_tag_len);
60
+
61
+ void installMethods();
62
+
63
+ bool InitAuthenticated(const char *cipher_type, int iv_len,
64
+ unsigned int auth_tag_len);
65
+
66
+ bool CheckCCMMessageLength(int message_len);
67
+
68
+ bool IsAuthenticatedMode() const;
69
+
70
+ bool MaybePassAuthTagToOpenSSL();
71
+
72
+ virtual ~MGLCipherHostObject();
73
+
74
+ private:
75
+ // TODO(osp) this is the node version, DeleteFnPtr seems to be some custom
76
+ // wrapper, I guess useful for memory deallocation
77
+ // DeleteFnPtr<EVP_CIPHER_CTX, EVP_CIPHER_CTX_free> ctx_;
78
+ // For now I'm manually calling EVP_CIPHER_CTX_free in the implementation
79
+ EVP_CIPHER_CTX *ctx_ = nullptr;
80
+ bool isCipher_;
81
+ bool pending_auth_failed_;
82
+ char auth_tag_[EVP_GCM_TLS_TAG_LEN];
83
+ AuthTagState auth_tag_state_;
84
+ unsigned int auth_tag_len_;
85
+ int max_message_size_;
86
+ };
87
+
88
+ } // namespace margelo
89
+
90
+ #endif // MGLCipherHostObject_h
@@ -0,0 +1,74 @@
1
+
2
+ #include "MGLCreateCipherInstaller.h"
3
+
4
+ #include <memory>
5
+
6
+ #ifdef ANDROID
7
+ #include "JSIUtils/MGLJSIMacros.h"
8
+ #else
9
+ #include "MGLJSIMacros.h"
10
+ #endif
11
+ #include "MGLCipherHostObject.h"
12
+
13
+ using namespace facebook;
14
+
15
+ namespace margelo {
16
+
17
+ FieldDefinition getCreateCipherFieldDefinition(
18
+ std::shared_ptr<react::CallInvoker> jsCallInvoker,
19
+ std::shared_ptr<DispatchQueue::dispatch_queue> workerQueue) {
20
+ return HOST_LAMBDA("createCipher", {
21
+ if (count < 1) {
22
+ throw jsi::JSError(runtime, "Params object is required");
23
+ }
24
+
25
+ if (!arguments[0].isObject()) {
26
+ throw jsi::JSError(runtime, "createCipher: Params needs to be an object");
27
+ }
28
+
29
+ auto params = arguments[0].getObject(runtime);
30
+
31
+ if (!params.hasProperty(runtime, "cipher_type")) {
32
+ throw jsi::JSError(runtime, "createCipher: cipher_type is required");
33
+ }
34
+
35
+ auto cipher_type = params.getProperty(runtime, "cipher_type")
36
+ .asString(runtime)
37
+ .utf8(runtime);
38
+
39
+ if (!params.hasProperty(runtime, "cipher_key")) {
40
+ throw jsi::JSError(runtime, "createCipher: cipher_key is required");
41
+ }
42
+
43
+ auto cipher_key = params.getProperty(runtime, "cipher_key")
44
+ .getObject(runtime)
45
+ .getArrayBuffer(runtime);
46
+
47
+ if (!params.hasProperty(runtime, "auth_tag_len")) {
48
+ throw jsi::JSError(runtime, "createCipher: auth_tag_len is required");
49
+ }
50
+
51
+ unsigned auto int auth_tag_len =
52
+ (int)params.getProperty(runtime, "auth_tag_len").getNumber();
53
+
54
+ if (params.hasProperty(runtime, "iv") &&
55
+ !params.getProperty(runtime, "iv").isNull() &&
56
+ !params.getProperty(runtime, "iv").isUndefined()) { // createCipheriv
57
+ auto iv = params.getProperty(runtime, "iv")
58
+ .getObject(runtime)
59
+ .getArrayBuffer(runtime);
60
+ auto hostObject = std::make_shared<MGLCipherHostObject>(
61
+ cipher_type, &cipher_key, true, auth_tag_len, &iv, runtime,
62
+ jsCallInvoker, workerQueue);
63
+
64
+ return jsi::Object::createFromHostObject(runtime, hostObject);
65
+ } else {
66
+ auto hostObject = std::make_shared<MGLCipherHostObject>(
67
+ cipher_type, &cipher_key, true, auth_tag_len, runtime, jsCallInvoker,
68
+ workerQueue);
69
+
70
+ return jsi::Object::createFromHostObject(runtime, hostObject);
71
+ }
72
+ });
73
+ }
74
+ } // namespace margelo
@@ -0,0 +1,17 @@
1
+ #include <jsi/jsi.h>
2
+
3
+ #include <memory>
4
+
5
+ #ifdef ANDROID
6
+ #include "JSIUtils/MGLSmartHostObject.h"
7
+ #else
8
+ #include "MGLSmartHostObject.h"
9
+ #endif
10
+
11
+ namespace margelo {
12
+ namespace jsi = facebook::jsi;
13
+
14
+ FieldDefinition getCreateCipherFieldDefinition(
15
+ std::shared_ptr<react::CallInvoker> jsCallInvoker,
16
+ std::shared_ptr<DispatchQueue::dispatch_queue> workerQueue);
17
+ } // namespace margelo
@@ -0,0 +1,74 @@
1
+ #include "MGLCreateDecipherInstaller.h"
2
+
3
+ #include <memory>
4
+
5
+ #include "MGLCipherHostObject.h"
6
+
7
+ #ifdef ANDROID
8
+ #include "JSIUtils/MGLJSIMacros.h"
9
+ #else
10
+ #include "MGLJSIMacros.h"
11
+ #endif
12
+
13
+ using namespace facebook;
14
+
15
+ namespace margelo {
16
+
17
+ FieldDefinition getCreateDecipherFieldDefinition(
18
+ std::shared_ptr<react::CallInvoker> jsCallInvoker,
19
+ std::shared_ptr<DispatchQueue::dispatch_queue> workerQueue) {
20
+ return HOST_LAMBDA("createDecipher", {
21
+ if (count < 1) {
22
+ throw jsi::JSError(runtime, "Params object is required");
23
+ }
24
+
25
+ if (!arguments[0].isObject()) {
26
+ throw jsi::JSError(runtime, "createCipher: Params needs to be an object");
27
+ }
28
+
29
+ auto params = arguments[0].getObject(runtime);
30
+
31
+ if (!params.hasProperty(runtime, "cipher_type")) {
32
+ throw jsi::JSError(runtime, "createCipher: cipher_type is required");
33
+ }
34
+
35
+ auto cipher_type = params.getProperty(runtime, "cipher_type")
36
+ .asString(runtime)
37
+ .utf8(runtime);
38
+
39
+ if (!params.hasProperty(runtime, "cipher_key")) {
40
+ throw jsi::JSError(runtime, "createCipher: cipher_key is required");
41
+ }
42
+
43
+ auto cipher_key = params.getProperty(runtime, "cipher_key")
44
+ .getObject(runtime)
45
+ .getArrayBuffer(runtime);
46
+
47
+ if (!params.hasProperty(runtime, "auth_tag_len")) {
48
+ throw jsi::JSError(runtime, "createCipher: auth_tag_len is required");
49
+ }
50
+
51
+ unsigned auto int auth_tag_len =
52
+ (int)params.getProperty(runtime, "auth_tag_len").getNumber();
53
+
54
+ if (params.hasProperty(runtime, "iv") &&
55
+ !params.getProperty(runtime, "iv").isNull() &&
56
+ !params.getProperty(runtime, "iv").isUndefined()) { // createDecipheriv
57
+ auto iv = params.getProperty(runtime, "iv")
58
+ .getObject(runtime)
59
+ .getArrayBuffer(runtime);
60
+ auto hostObject = std::make_shared<MGLCipherHostObject>(
61
+ cipher_type, &cipher_key, false, auth_tag_len, &iv, runtime,
62
+ jsCallInvoker, workerQueue);
63
+
64
+ return jsi::Object::createFromHostObject(runtime, hostObject);
65
+ } else {
66
+ auto hostObject = std::make_shared<MGLCipherHostObject>(
67
+ cipher_type, &cipher_key, false, auth_tag_len, runtime, jsCallInvoker,
68
+ workerQueue);
69
+
70
+ return jsi::Object::createFromHostObject(runtime, hostObject);
71
+ }
72
+ });
73
+ }
74
+ } // namespace margelo
@@ -0,0 +1,17 @@
1
+ #include <jsi/jsi.h>
2
+
3
+ #include <memory>
4
+
5
+ #ifdef ANDROID
6
+ #include "JSIUtils/MGLSmartHostObject.h"
7
+ #else
8
+ #include "MGLSmartHostObject.h"
9
+ #endif
10
+
11
+ namespace margelo {
12
+ namespace jsi = facebook::jsi;
13
+
14
+ FieldDefinition getCreateDecipherFieldDefinition(
15
+ std::shared_ptr<react::CallInvoker> jsCallInvoker,
16
+ std::shared_ptr<DispatchQueue::dispatch_queue> workerQueue);
17
+ } // namespace margelo
@@ -0,0 +1,95 @@
1
+ // Copyright 2022 Margelo
2
+
3
+ #ifdef ANDROID
4
+ #include "MGLHmacHostObject.h"
5
+
6
+ #include "JSIUtils/MGLTypedArray.h"
7
+ #else
8
+ #include "MGLHmacHostObject.h"
9
+ #include "MGLTypedArray.h"
10
+ #endif
11
+
12
+ #include <jsi/jsi.h>
13
+ #include <openssl/hmac.h>
14
+
15
+ #include <memory>
16
+ #include <string>
17
+ #include <vector>
18
+
19
+ #define OUT
20
+
21
+ namespace margelo {
22
+
23
+ using namespace facebook;
24
+
25
+ const EVP_MD *parseHashAlgorithm(const std::string &hashAlgorithm) {
26
+ if (hashAlgorithm == "sha1") {
27
+ return EVP_sha1();
28
+ }
29
+ if (hashAlgorithm == "sha256") {
30
+ return EVP_sha256();
31
+ }
32
+ if (hashAlgorithm == "sha512") {
33
+ return EVP_sha512();
34
+ }
35
+ const EVP_MD *res = EVP_get_digestbyname(hashAlgorithm.c_str());
36
+ if (res != nullptr) {
37
+ return res;
38
+ }
39
+ throw std::runtime_error("Invalid Hash Algorithm!");
40
+ }
41
+
42
+ MGLHmacHostObject::MGLHmacHostObject(
43
+ const std::string &hashAlgorithm, jsi::Runtime &runtime,
44
+ jsi::ArrayBuffer &key, std::shared_ptr<react::CallInvoker> jsCallInvoker,
45
+ std::shared_ptr<DispatchQueue::dispatch_queue> workerQueue)
46
+ : MGLSmartHostObject(jsCallInvoker, workerQueue) {
47
+ this->context = HMAC_CTX_new();
48
+ if (key.size(runtime) == 0) {
49
+ HMAC_Init_ex(this->context, "", 0, parseHashAlgorithm(hashAlgorithm),
50
+ nullptr);
51
+ } else {
52
+ HMAC_Init_ex(this->context, key.data(runtime),
53
+ static_cast<int>(key.size(runtime)),
54
+ parseHashAlgorithm(hashAlgorithm), nullptr);
55
+ }
56
+
57
+ this->fields.push_back(HOST_LAMBDA("update", {
58
+ if (!arguments[0].isObject() ||
59
+ !arguments[0].getObject(runtime).isArrayBuffer(runtime)) {
60
+ throw jsi::JSError(
61
+ runtime,
62
+ "MGLHmacHostObject::update: First argument ('message') "
63
+ "has to be of type ArrayBuffer!");
64
+ }
65
+
66
+ auto message = arguments[0].getObject(runtime).getArrayBuffer(runtime);
67
+
68
+ HMAC_Update(this->context, message.data(runtime), message.size(runtime));
69
+
70
+ return jsi::Value::undefined();
71
+ }));
72
+
73
+ this->fields.push_back(HOST_LAMBDA("digest", {
74
+ auto size = HMAC_size(this->context);
75
+
76
+ unsigned char *OUT md = new unsigned char[size];
77
+ unsigned int OUT length;
78
+
79
+ HMAC_Final(this->context, md, &length);
80
+
81
+ MGLTypedArray<MGLTypedArrayKind::Uint8Array> MGLtypedArray(runtime, length);
82
+ std::vector<unsigned char> vec(md, md + length);
83
+ MGLtypedArray.update(runtime, vec);
84
+
85
+ return MGLtypedArray;
86
+ }));
87
+ }
88
+
89
+ MGLHmacHostObject::~MGLHmacHostObject() {
90
+ if (this->context != nullptr) {
91
+ HMAC_CTX_free(this->context);
92
+ }
93
+ }
94
+
95
+ } // namespace margelo
@@ -0,0 +1,39 @@
1
+ //
2
+ // HmacHostObject.h
3
+ //
4
+ // Created by Marc Rousavy on 22.02.22.
5
+ //
6
+
7
+ #ifndef MGLHmacHostObject_h
8
+ #define MGLHmacHostObject_h
9
+
10
+ #include <jsi/jsi.h>
11
+ #include <openssl/hmac.h>
12
+
13
+ #include <memory>
14
+ #include <string>
15
+
16
+ #ifdef ANDROID
17
+ #include "JSIUtils/MGLSmartHostObject.h"
18
+ #else
19
+ #include "MGLSmartHostObject.h"
20
+ #endif
21
+
22
+ namespace margelo {
23
+
24
+ using namespace facebook;
25
+
26
+ class MGLHmacHostObject : public MGLSmartHostObject {
27
+ public:
28
+ explicit MGLHmacHostObject(
29
+ const std::string &hashAlgorithm, jsi::Runtime &runtime,
30
+ jsi::ArrayBuffer &key, std::shared_ptr<react::CallInvoker> jsCallInvoker,
31
+ std::shared_ptr<DispatchQueue::dispatch_queue> workerQueue);
32
+ virtual ~MGLHmacHostObject();
33
+
34
+ private:
35
+ HMAC_CTX *context;
36
+ };
37
+ } // namespace margelo
38
+
39
+ #endif /* MGLHmacHostObject_h */
@@ -0,0 +1,43 @@
1
+ //
2
+ // HMAC-JSI-Installer.m
3
+ // PinkPanda
4
+ //
5
+ // Created by Marc Rousavy on 31.10.21.
6
+ //
7
+
8
+ #include "MGLHmacInstaller.h"
9
+
10
+ #include <openssl/hmac.h>
11
+
12
+ #ifdef ANDROID
13
+ #include "JSIUtils/MGLJSIMacros.h"
14
+ #include "MGLHmacHostObject.h"
15
+ #else
16
+ #include "MGLHmacHostObject.h"
17
+ #include "MGLJSIMacros.h"
18
+ #endif
19
+
20
+ using namespace facebook;
21
+
22
+ namespace margelo {
23
+
24
+ FieldDefinition getHmacFieldDefinition(
25
+ std::shared_ptr<react::CallInvoker> jsCallInvoker,
26
+ std::shared_ptr<DispatchQueue::dispatch_queue> workerQueue) {
27
+ // createHmac(hashAlgorithm: 'sha1' | 'sha256' | 'sha512',
28
+ // key: string)
29
+ return HOST_LAMBDA("createHmac", {
30
+ if (count != 2) {
31
+ throw jsi::JSError(runtime,
32
+ "createHmac(..) expects exactly 2 arguments!");
33
+ }
34
+
35
+ auto hashAlgorithm = arguments[0].asString(runtime).utf8(runtime);
36
+ auto key = arguments[1].getObject(runtime).getArrayBuffer(runtime);
37
+
38
+ auto hostObject = std::make_shared<MGLHmacHostObject>(
39
+ hashAlgorithm, runtime, key, jsCallInvoker, workerQueue);
40
+ return jsi::Object::createFromHostObject(runtime, hostObject);
41
+ });
42
+ }
43
+ } // namespace margelo
@@ -0,0 +1,20 @@
1
+ #include <jsi/jsi.h>
2
+
3
+ #include <memory>
4
+
5
+ #ifdef ANDROID
6
+ #include "JSIUtils/MGLSmartHostObject.h"
7
+ #else
8
+ #include "MGLSmartHostObject.h"
9
+ #endif
10
+
11
+ namespace margelo {
12
+ namespace jsi = facebook::jsi;
13
+
14
+ /// It's signature is:
15
+ /// createHmac(hashAlgorithm: 'sha1' | 'sha256' | 'sha512',
16
+ /// key: string): HMAC
17
+ FieldDefinition getHmacFieldDefinition(
18
+ std::shared_ptr<react::CallInvoker> jsCallInvoker,
19
+ std::shared_ptr<DispatchQueue::dispatch_queue> workerQueue);
20
+ } // namespace margelo
@@ -0,0 +1,147 @@
1
+ // Copyright 2022 Margelo
2
+
3
+ #include "MGLHashHostObject.h"
4
+
5
+ #ifdef ANDROID
6
+ #include "JSIUtils/MGLTypedArray.h"
7
+ #else
8
+ #include "MGLTypedArray.h"
9
+ #endif
10
+
11
+ #include <jsi/jsi.h>
12
+ #include <openssl/err.h>
13
+
14
+ #include <memory>
15
+ #include <string>
16
+ #include <vector>
17
+
18
+ #define OUT
19
+
20
+ namespace margelo {
21
+
22
+ using namespace facebook;
23
+ namespace jsi = facebook::jsi;
24
+
25
+ const EVP_MD *parseHashAlgorithmForHashObject(
26
+ const std::string &hashAlgorithm) {
27
+ const EVP_MD *res = EVP_get_digestbyname(hashAlgorithm.c_str());
28
+ if (res != nullptr) {
29
+ return res;
30
+ }
31
+ throw std::runtime_error("Invalid Hash Algorithm!");
32
+ }
33
+
34
+ MGLHashHostObject::MGLHashHostObject(
35
+ MGLHashHostObject *other, std::shared_ptr<react::CallInvoker> jsCallInvoker,
36
+ std::shared_ptr<DispatchQueue::dispatch_queue> workerQueue)
37
+ : MGLSmartHostObject(jsCallInvoker, workerQueue) {
38
+ const EVP_MD *md = EVP_MD_CTX_md(other->mdctx_);
39
+ this->mdctx_ = EVP_MD_CTX_new();
40
+ EVP_MD_CTX_copy(this->mdctx_, other->mdctx_);
41
+ md_len_ = EVP_MD_size(md);
42
+
43
+ installMethods();
44
+ }
45
+
46
+ MGLHashHostObject::MGLHashHostObject(
47
+ const std::string hashAlgorithm, unsigned int md_len,
48
+ std::shared_ptr<react::CallInvoker> jsCallInvoker,
49
+ std::shared_ptr<DispatchQueue::dispatch_queue> workerQueue)
50
+ : MGLSmartHostObject(jsCallInvoker, workerQueue) {
51
+ const EVP_MD *md = parseHashAlgorithmForHashObject(hashAlgorithm);
52
+ mdctx_ = EVP_MD_CTX_new();
53
+ if (!mdctx_ || EVP_DigestInit_ex(mdctx_, md, nullptr) <= 0) {
54
+ EVP_MD_CTX_reset(mdctx_);
55
+ return;
56
+ }
57
+ md_len_ = EVP_MD_size(md);
58
+ if (md_len != -1) {
59
+ md_len_ = md_len;
60
+ }
61
+
62
+ installMethods();
63
+ }
64
+
65
+ void MGLHashHostObject::installMethods() {
66
+ this->fields.push_back(HOST_LAMBDA("update", {
67
+ if (!arguments[0].isObject() ||
68
+ !arguments[0].getObject(runtime).isArrayBuffer(runtime)) {
69
+ throw jsi::JSError(runtime,
70
+ "HmacHostObject::update: First argument ('message') "
71
+ "has to be of type ArrayBuffer!");
72
+ }
73
+ auto messageBuffer =
74
+ arguments[0].getObject(runtime).getArrayBuffer(runtime);
75
+
76
+ const unsigned char *data =
77
+ reinterpret_cast<const unsigned char *>(messageBuffer.data(runtime));
78
+ int size = messageBuffer.size(runtime);
79
+
80
+ EVP_DigestUpdate(mdctx_, data, size);
81
+
82
+ return jsi::Value::undefined();
83
+ }));
84
+
85
+ this->fields.push_back(buildPair(
86
+ "copy", JSIF([this]) {
87
+ int md_len = -1;
88
+ if (!arguments[0].isUndefined()) {
89
+ md_len = static_cast<int>(arguments[0].asNumber());
90
+ }
91
+ std::shared_ptr<MGLHashHostObject> copy =
92
+ std::make_shared<MGLHashHostObject>(
93
+ this, this->weakJsCallInvoker.lock(), this->dispatchQueue);
94
+ if (md_len != -1) {
95
+ copy->md_len_ = md_len;
96
+ }
97
+ return jsi::Object::createFromHostObject(runtime, copy);
98
+ }));
99
+
100
+ this->fields.push_back(buildPair(
101
+ "digest", JSIF([this]) {
102
+ unsigned int len = md_len_;
103
+
104
+ if (digest_ == nullptr && len > 0) {
105
+ // Some hash algorithms such as SHA3 do not support calling
106
+ // EVP_DigestFinal_ex more than once, however, Hash._flush
107
+ // and Hash.digest can both be used to retrieve the digest,
108
+ // so we need to cache it.
109
+ // See https://github.com/nodejs/node/issues/28245.
110
+
111
+ char *md_value = new char[len];
112
+
113
+ size_t default_len = EVP_MD_CTX_size(mdctx_);
114
+ int ret;
115
+ if (len == default_len) {
116
+ ret = EVP_DigestFinal_ex(
117
+ mdctx_, reinterpret_cast<unsigned char *>(md_value), &len);
118
+ } else {
119
+ ret = EVP_DigestFinalXOF(
120
+ mdctx_, reinterpret_cast<unsigned char *>(md_value), len);
121
+ }
122
+
123
+ if (ret != 1) {
124
+ throw jsi::JSError(
125
+ runtime, "openSSL error:" + std::to_string(ERR_get_error()));
126
+ }
127
+
128
+ digest_ = md_value;
129
+ }
130
+
131
+ MGLTypedArray<MGLTypedArrayKind::Uint8Array> typedArray(runtime, len);
132
+ std::vector<unsigned char> vec(digest_, digest_ + len);
133
+ typedArray.update(runtime, vec);
134
+ return typedArray;
135
+ }));
136
+ }
137
+
138
+ MGLHashHostObject::~MGLHashHostObject() {
139
+ if (this->mdctx_ != nullptr) {
140
+ EVP_MD_CTX_free(this->mdctx_);
141
+ }
142
+ if (digest_ != nullptr) {
143
+ delete[] digest_;
144
+ }
145
+ }
146
+
147
+ } // namespace margelo
@@ -0,0 +1,53 @@
1
+ // Copyright 2022 Margelo
2
+ // HashHostObject.h
3
+ //
4
+ //
5
+
6
+ #ifndef HashHostObject_h
7
+ #define HashHostObject_h
8
+
9
+ #include <jsi/jsi.h>
10
+ #include <openssl/dsa.h>
11
+ #include <openssl/ec.h>
12
+ #include <openssl/err.h>
13
+ #include <openssl/evp.h>
14
+ #include <openssl/kdf.h>
15
+ #include <openssl/rsa.h>
16
+ #include <openssl/ssl.h>
17
+
18
+ #include <memory>
19
+ #include <string>
20
+
21
+ #ifdef ANDROID
22
+ #include "JSIUtils/MGLSmartHostObject.h"
23
+ #else
24
+ #include "MGLSmartHostObject.h"
25
+ #endif
26
+
27
+ namespace margelo {
28
+
29
+ using namespace facebook;
30
+
31
+ class MGLHashHostObject : public MGLSmartHostObject {
32
+ public:
33
+ explicit MGLHashHostObject(
34
+ std::string hashAlgorithm, unsigned int md_len,
35
+ std::shared_ptr<react::CallInvoker> jsCallInvoker,
36
+ std::shared_ptr<DispatchQueue::dispatch_queue> workerQueue);
37
+
38
+ explicit MGLHashHostObject(
39
+ MGLHashHostObject *other,
40
+ std::shared_ptr<react::CallInvoker> jsCallInvoker,
41
+ std::shared_ptr<DispatchQueue::dispatch_queue> workerQueue);
42
+ void installMethods();
43
+
44
+ virtual ~MGLHashHostObject();
45
+
46
+ private:
47
+ EVP_MD_CTX *mdctx_ = nullptr;
48
+ unsigned int md_len_ = 0;
49
+ char *digest_ = nullptr;
50
+ };
51
+ } // namespace margelo
52
+
53
+ #endif /* MGLHashHostObject_h */