react-native-quick-crypto 0.2.0 → 0.3.2

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 (95) hide show
  1. package/README.md +38 -14
  2. package/android/src/main/AndroidManifest.xml +1 -1
  3. package/android/src/main/java/com/margelo/quickcrypto/QuickCryptoModule.java +70 -0
  4. package/android/src/main/java/com/{reactnativequickcrypto → margelo/quickcrypto}/QuickCryptoPackage.java +11 -12
  5. package/cpp/Cipher/MGLCipherHostObject.cpp +64 -48
  6. package/cpp/Cipher/MGLCipherKeys.cpp +1469 -0
  7. package/cpp/Cipher/MGLCipherKeys.h +124 -0
  8. package/cpp/Cipher/MGLCreateCipherInstaller.cpp +56 -53
  9. package/cpp/Cipher/MGLCreateCipherInstaller.h +5 -0
  10. package/cpp/Cipher/MGLCreateDecipherInstaller.cpp +56 -53
  11. package/cpp/Cipher/MGLGenerateKeyPairInstaller.cpp +107 -0
  12. package/cpp/Cipher/MGLGenerateKeyPairInstaller.h +32 -0
  13. package/cpp/Cipher/MGLGenerateKeyPairSyncInstaller.cpp +60 -0
  14. package/cpp/Cipher/MGLGenerateKeyPairSyncInstaller.h +35 -0
  15. package/cpp/Cipher/MGLPublicCipher.h +120 -0
  16. package/cpp/Cipher/MGLPublicCipherInstaller.h +113 -0
  17. package/cpp/Cipher/MGLRsa.cpp +188 -0
  18. package/cpp/Cipher/MGLRsa.h +61 -0
  19. package/cpp/JSIUtils/MGLJSIUtils.h +24 -0
  20. package/cpp/JSIUtils/MGLThreadAwareHostObject.h +1 -1
  21. package/cpp/MGLQuickCryptoHostObject.cpp +42 -3
  22. package/cpp/Utils/MGLUtils.cpp +156 -0
  23. package/cpp/Utils/MGLUtils.h +254 -0
  24. package/lib/commonjs/@types/crypto-browserify.d.js +2 -0
  25. package/lib/commonjs/@types/crypto-browserify.d.js.map +1 -0
  26. package/lib/commonjs/@types/stream-browserify.d.js +2 -0
  27. package/lib/commonjs/@types/stream-browserify.d.js.map +1 -0
  28. package/lib/commonjs/Cipher.js +310 -2
  29. package/lib/commonjs/Cipher.js.map +1 -1
  30. package/lib/commonjs/Hash.js +2 -2
  31. package/lib/commonjs/Hash.js.map +1 -1
  32. package/lib/commonjs/Hmac.js +2 -2
  33. package/lib/commonjs/Hmac.js.map +1 -1
  34. package/lib/commonjs/NativeQuickCrypto/Cipher.js +11 -0
  35. package/lib/commonjs/NativeQuickCrypto/Cipher.js.map +1 -1
  36. package/lib/commonjs/NativeQuickCrypto/NativeQuickCrypto.js.map +1 -1
  37. package/lib/commonjs/QuickCrypto.js +8 -0
  38. package/lib/commonjs/QuickCrypto.js.map +1 -1
  39. package/lib/commonjs/Utils.js +82 -1
  40. package/lib/commonjs/Utils.js.map +1 -1
  41. package/lib/commonjs/constants.js +86 -0
  42. package/lib/commonjs/constants.js.map +1 -0
  43. package/lib/commonjs/index.js +18 -10
  44. package/lib/commonjs/index.js.map +1 -1
  45. package/lib/commonjs/keys.js +207 -0
  46. package/lib/commonjs/keys.js.map +1 -0
  47. package/lib/module/@types/crypto-browserify.d.js +2 -0
  48. package/lib/module/@types/crypto-browserify.d.js.map +1 -0
  49. package/lib/module/@types/stream-browserify.d.js +2 -0
  50. package/lib/module/@types/stream-browserify.d.js.map +1 -0
  51. package/lib/module/Cipher.js +298 -4
  52. package/lib/module/Cipher.js.map +1 -1
  53. package/lib/module/Hash.js +1 -1
  54. package/lib/module/Hash.js.map +1 -1
  55. package/lib/module/Hmac.js +1 -1
  56. package/lib/module/Hmac.js.map +1 -1
  57. package/lib/module/NativeQuickCrypto/Cipher.js +9 -1
  58. package/lib/module/NativeQuickCrypto/Cipher.js.map +1 -1
  59. package/lib/module/NativeQuickCrypto/NativeQuickCrypto.js.map +1 -1
  60. package/lib/module/QuickCrypto.js +8 -1
  61. package/lib/module/QuickCrypto.js.map +1 -1
  62. package/lib/module/Utils.js +67 -1
  63. package/lib/module/Utils.js.map +1 -1
  64. package/lib/module/constants.js +79 -0
  65. package/lib/module/constants.js.map +1 -0
  66. package/lib/module/index.js +13 -1
  67. package/lib/module/index.js.map +1 -1
  68. package/lib/module/keys.js +193 -0
  69. package/lib/module/keys.js.map +1 -0
  70. package/lib/typescript/Cipher.d.ts +59 -2
  71. package/lib/typescript/Hash.d.ts +1 -1
  72. package/lib/typescript/Hmac.d.ts +1 -1
  73. package/lib/typescript/NativeQuickCrypto/Cipher.d.ts +10 -0
  74. package/lib/typescript/NativeQuickCrypto/NativeQuickCrypto.d.ts +6 -1
  75. package/lib/typescript/QuickCrypto.d.ts +105 -1
  76. package/lib/typescript/Utils.d.ts +11 -0
  77. package/lib/typescript/constants.d.ts +75 -0
  78. package/lib/typescript/index.d.ts +208 -1
  79. package/lib/typescript/keys.d.ts +60 -0
  80. package/package.json +7 -6
  81. package/react-native-quick-crypto.podspec +1 -1
  82. package/src/.DS_Store +0 -0
  83. package/src/@types/crypto-browserify.d.ts +4 -0
  84. package/src/@types/stream-browserify.d.ts +4 -0
  85. package/src/Cipher.ts +446 -4
  86. package/src/Hash.ts +1 -1
  87. package/src/Hmac.ts +1 -1
  88. package/src/NativeQuickCrypto/Cipher.ts +44 -0
  89. package/src/NativeQuickCrypto/NativeQuickCrypto.ts +13 -1
  90. package/src/QuickCrypto.ts +12 -0
  91. package/src/Utils.ts +91 -0
  92. package/src/constants.ts +79 -0
  93. package/src/index.ts +15 -1
  94. package/src/keys.ts +297 -0
  95. package/android/src/main/java/com/reactnativequickcrypto/QuickCryptoModule.java +0 -70
package/README.md CHANGED
@@ -1,8 +1,21 @@
1
+ <a href="https://margelo.io">
2
+ <img src="./img/banner.svg" width="100%" />
3
+ </a>
4
+
1
5
  # ⚡️ react-native-quick-crypto
2
6
 
3
- A fast implementation of Node's `crypto` module written in C/C++ JSI.
7
+ A fast implementation of Node's `crypto` module.
8
+
9
+ Unlike any other current JS-based polyfills, react-native-quick-crypto is written in C/C++ JSI and provides much greater performance - especially on mobile devices.
10
+ QuickCrypto can be used as a drop-in replacement for your Web3/Crypto apps to speed up common cryptography functions.
4
11
 
5
- QuickCrypto can be used as a drop-in replacement for your Web3/Crypto apps to speed up all cryptography functions.
12
+ * 🏎️ Up to 300x faster than all other solutions
13
+ * ⚡️ Lightning fast implementation with pure C++ and JSI, instead of JS
14
+ * 🧪 Well tested in JS and C++ (OpenSSL)
15
+ * 💰 Made for crypto apps and Wallets
16
+ * 🤌 Up to 5x smaller in JS-bundle size
17
+ * 🔢 Secure native compiled cryptography
18
+ * 🔁 Easy drop-in replacement for [crypto-browserify](https://github.com/crypto-browserify/crypto-browserify) or [react-native-crypto](https://github.com/tradle/react-native-crypto)
6
19
 
7
20
  For example, creating a Wallet using ethers.js uses complex algorithms to generate a private-key/mnemonic-phrase pair:
8
21
 
@@ -16,27 +29,31 @@ console.log(`Creating a Wallet took ${end - start}ms.`)
16
29
  **Without** react-native-crypto 🐢:
17
30
 
18
31
  ```
19
- Creating a Wallet took 31.3582738422ms
32
+ Creating a Wallet took xxxms
20
33
  ```
21
34
 
22
35
  **With** react-native-crypto ⚡️:
23
36
 
24
37
  ```
25
- Creating a Wallet took 2.47425001859ms
38
+ Creating a Wallet took yyyms
26
39
  ```
27
40
 
28
41
  ---
29
42
 
30
43
  ## Installation
31
44
 
32
- ### React Native
45
+ <h3>
46
+ React Native  <a href="#"><img src="./img/react-native.png" height="15" /></a>
47
+ </h3>
33
48
 
34
49
  ```sh
35
50
  yarn add react-native-quick-crypto
36
51
  cd ios && pod install
37
52
  ```
38
53
 
39
- ### Expo
54
+ <h3>
55
+ Expo  <a href="#"><img src="./img/expo.png" height="12" /></a>
56
+ </h3>
40
57
 
41
58
  ```sh
42
59
  expo install react-native-quick-crypto
@@ -45,18 +62,25 @@ expo prebuild
45
62
 
46
63
  ## Usage
47
64
 
48
- In your `metro.config.js`, add a module resolver to replace `crypto` with `react-native-quick-crypto`:
65
+ In your `babel.config.js`, add a module resolver to replace `crypto` with `react-native-quick-crypto`:
49
66
 
50
67
  ```diff
51
68
  +const path = require('path');
52
69
 
53
- module.exports = {
54
- + resolver: {
55
- + extraNodeModules: {
56
- + crypto: path.resolve(__dirname, './node_modules/react-native-quick-crypto'),
57
- + },
58
- + },
59
- ...
70
+ module.exports = {
71
+ presets: ['module:metro-react-native-babel-preset'],
72
+ plugins: [
73
+ + [
74
+ + 'module-resolver',
75
+ + {
76
+ + alias: {
77
+ + 'crypto': 'react-native-quick-crypto',
78
+ + },
79
+ + },
80
+ + ],
81
+ ...
82
+ ],
83
+ };
60
84
  ```
61
85
 
62
86
  Now, all imports for `crypto` will be resolved as `react-native-quick-crypto` instead.
@@ -1,4 +1,4 @@
1
1
  <manifest xmlns:android="http://schemas.android.com/apk/res/android"
2
- package="com.reactnativebignumber">
2
+ package="com.margelo.quickcrypto">
3
3
 
4
4
  </manifest>
@@ -0,0 +1,70 @@
1
+ package com.margelo.quickcrypto;
2
+
3
+ import android.util.Log;
4
+
5
+ import androidx.annotation.NonNull;
6
+
7
+ import com.facebook.jni.HybridData;
8
+ import com.facebook.proguard.annotations.DoNotStrip;
9
+ import com.facebook.react.bridge.JavaScriptContextHolder;
10
+ import com.facebook.react.bridge.ReactContextBaseJavaModule;
11
+ import com.facebook.react.bridge.ReactApplicationContext;
12
+ import com.facebook.react.bridge.ReactMethod;
13
+ import com.facebook.react.module.annotations.ReactModule;
14
+ import com.facebook.react.turbomodule.core.CallInvokerHolderImpl;
15
+
16
+ @ReactModule(name = QuickCryptoModule.NAME)
17
+ public class QuickCryptoModule extends ReactContextBaseJavaModule {
18
+ public static final String NAME = "QuickCrypto";
19
+
20
+ @DoNotStrip
21
+ private HybridData mHybridData;
22
+
23
+ private native HybridData initHybrid();
24
+
25
+ public QuickCryptoModule(ReactApplicationContext reactContext) {
26
+ super(reactContext);
27
+ }
28
+
29
+ @NonNull
30
+ @Override
31
+ public String getName() {
32
+ return NAME;
33
+ }
34
+
35
+ @ReactMethod(isBlockingSynchronousMethod = true)
36
+ public boolean install() {
37
+ try {
38
+ if (mHybridData != null) {
39
+ return false;
40
+ }
41
+ Log.i(NAME, "Loading C++ library...");
42
+ System.loadLibrary("reactnativequickcrypto");
43
+
44
+ JavaScriptContextHolder jsContext = getReactApplicationContext().getJavaScriptContextHolder();
45
+ CallInvokerHolderImpl jsCallInvokerHolder = (CallInvokerHolderImpl) getReactApplicationContext()
46
+ .getCatalystInstance()
47
+ .getJSCallInvokerHolder();
48
+
49
+
50
+ Log.i(NAME, "Installing JSI Bindings for react-native-quick-crypto...");
51
+ mHybridData = initHybrid();
52
+ nativeInstall(jsContext.get(), jsCallInvokerHolder);
53
+ Log.i(NAME, "Successfully installed JSI Bindings for react-native-quick-crypto!");
54
+
55
+ return true;
56
+ } catch (Exception exception) {
57
+ Log.e(NAME, "Failed to install JSI Bindings for react-native-quick-crypto!", exception);
58
+ return false;
59
+ }
60
+ }
61
+
62
+ public void destroy() {
63
+ if (mHybridData == null) {
64
+ return;
65
+ }
66
+ mHybridData.resetNative();
67
+ }
68
+
69
+ private native void nativeInstall(long jsiPtr, CallInvokerHolderImpl jsCallInvokerHolder);
70
+ }
@@ -1,4 +1,4 @@
1
- package com.reactnativequickcrypto;
1
+ package com.margelo.quickcrypto;
2
2
 
3
3
  import androidx.annotation.NonNull;
4
4
 
@@ -10,17 +10,16 @@ import com.facebook.react.uimanager.ViewManager;
10
10
  import java.util.Collections;
11
11
  import java.util.List;
12
12
 
13
-
14
13
  public class QuickCryptoPackage implements ReactPackage {
15
- @NonNull
16
- @Override
17
- public List<NativeModule> createNativeModules(@NonNull ReactApplicationContext reactContext) {
18
- return Collections.singletonList(new QuickCryptoModule(reactContext));
19
- }
14
+ @NonNull
15
+ @Override
16
+ public List<NativeModule> createNativeModules(@NonNull ReactApplicationContext reactContext) {
17
+ return Collections.singletonList(new QuickCryptoModule(reactContext));
18
+ }
20
19
 
21
- @NonNull
22
- @Override
23
- public List<ViewManager> createViewManagers(@NonNull ReactApplicationContext reactContext) {
24
- return Collections.emptyList();
25
- }
20
+ @NonNull
21
+ @Override
22
+ public List<ViewManager> createViewManagers(@NonNull ReactApplicationContext reactContext) {
23
+ return Collections.emptyList();
24
+ }
26
25
  }
@@ -4,8 +4,10 @@
4
4
  #include "MGLCipherHostObject.h"
5
5
 
6
6
  #ifdef ANDROID
7
+ #include "JSIUtils/MGLJSIUtils.h"
7
8
  #include "JSIUtils/MGLTypedArray.h"
8
9
  #else
10
+ #include "MGLJSIUtils.h"
9
11
  #include "MGLTypedArray.h"
10
12
  #endif
11
13
 
@@ -106,7 +108,7 @@ MGLCipherHostObject::MGLCipherHostObject(
106
108
 
107
109
  int key_len =
108
110
  EVP_BytesToKey(cipher, EVP_md5(), nullptr, cipher_key->data(runtime),
109
- cipher_key->size(runtime), 1, key, iv);
111
+ static_cast<int>(cipher_key->size(runtime)), 1, key, iv);
110
112
 
111
113
  // TODO(osp) this looks like a macro, check if necessary
112
114
  // CHECK_NE(key_len, 0);
@@ -445,62 +447,76 @@ void MGLCipherHostObject::installMethods() {
445
447
  }));
446
448
 
447
449
  // setAuthTag
448
- this->fields.push_back(HOST_LAMBDA("setAuthTag", {
449
- if (count != 1 || !arguments[0].isObject() ||
450
- !arguments[0].asObject(runtime).isArrayBuffer(runtime)) {
451
- throw jsi::JSError(
452
- runtime, "cipher.setAuthTag requires an ArrayBuffer tag argument");
453
- }
450
+ this->fields.push_back(buildPair(
451
+ "setAuthTag", JSIF([=]) {
452
+ if (count != 1 || !arguments[0].isObject() ||
453
+ !arguments[0].asObject(runtime).isArrayBuffer(runtime)) {
454
+ jsi::detail::throwJSError(
455
+ runtime,
456
+ "cipher.setAuthTag requires an ArrayBuffer tag argument");
457
+ throw jsi::JSError(
458
+ runtime,
459
+ "cipher.setAuthTag requires an ArrayBuffer tag argument");
460
+ }
454
461
 
455
- if (!ctx_ || !IsAuthenticatedMode() || isCipher_ ||
456
- auth_tag_state_ != kAuthTagUnknown) {
457
- return false;
458
- }
462
+ if (!ctx_ || !IsAuthenticatedMode() || isCipher_ ||
463
+ auth_tag_state_ != kAuthTagUnknown) {
464
+ return false;
465
+ }
459
466
 
460
- auto authTagArrayBuffer =
461
- arguments[0].asObject(runtime).getArrayBuffer(runtime);
462
- const unsigned char *data = authTagArrayBuffer.data(runtime);
463
- auto tag_len = authTagArrayBuffer.length(runtime);
467
+ auto authTagArrayBuffer =
468
+ arguments[0].asObject(runtime).getArrayBuffer(runtime);
469
+ if (!CheckSizeInt32(runtime, authTagArrayBuffer)) {
470
+ jsi::detail::throwJSError(
471
+ runtime,
472
+ "cipher.setAuthTag requires an ArrayBuffer tag argument");
473
+ throw jsi::JSError(
474
+ runtime,
475
+ "cipher.setAuthTag requires an ArrayBuffer tag argument");
476
+ }
477
+ // const unsigned char *data = authTagArrayBuffer.data(runtime);
478
+ unsigned int tag_len =
479
+ static_cast<unsigned int>(authTagArrayBuffer.length(runtime));
464
480
 
465
- // ArrayBufferOrViewContents<char> auth_tag(args[0]);
466
- // TODO(osp) implement this check
467
- // if (UNLIKELY(!auth_tag.CheckSizeInt32()))
468
- // return THROW_ERR_OUT_OF_RANGE(env, "buffer is too big");
481
+ // ArrayBufferOrViewContents<char> auth_tag(args[0]);
482
+ // TODO(osp) implement this check
483
+ // if (UNLIKELY(!auth_tag.CheckSizeInt32()))
484
+ // return THROW_ERR_OUT_OF_RANGE(env, "buffer is too big");
469
485
 
470
- // unsigned int tag_len = auth_tag.size();
486
+ // unsigned int tag_len = auth_tag.size();
471
487
 
472
- const int mode = EVP_CIPHER_CTX_mode(ctx_);
473
- bool is_valid;
474
- if (mode == EVP_CIPH_GCM_MODE) {
475
- // Restrict GCM tag lengths according to NIST 800-38d, page 9.
476
- is_valid =
477
- (auth_tag_len_ == kNoAuthTagLength || auth_tag_len_ == tag_len) &&
478
- IsValidGCMTagLength(tag_len);
479
- } else {
480
- // At this point, the tag length is already known and must match the
481
- // length of the given authentication tag.
482
- // TODO(osp) add CHECK here
483
- IsSupportedAuthenticatedMode(ctx_);
484
- // CHECK_NE(cipher->auth_tag_len_, kNoAuthTagLength);
485
- is_valid = auth_tag_len_ == tag_len;
486
- }
488
+ const int mode = EVP_CIPHER_CTX_mode(ctx_);
489
+ bool is_valid;
490
+ if (mode == EVP_CIPH_GCM_MODE) {
491
+ // Restrict GCM tag lengths according to NIST 800-38d, page 9.
492
+ is_valid =
493
+ (auth_tag_len_ == kNoAuthTagLength || auth_tag_len_ == tag_len) &&
494
+ IsValidGCMTagLength(tag_len);
495
+ } else {
496
+ // At this point, the tag length is already known and must match the
497
+ // length of the given authentication tag.
498
+ // TODO(osp) add CHECK here
499
+ IsSupportedAuthenticatedMode(ctx_);
500
+ // CHECK_NE(cipher->auth_tag_len_, kNoAuthTagLength);
501
+ is_valid = auth_tag_len_ == tag_len;
502
+ }
487
503
 
488
- if (!is_valid) {
489
- throw jsi::JSError(runtime,
490
- "Invalid authentication tag length: " + tag_len);
491
- // return THROW_ERR_CRYPTO_INVALID_AUTH_TAG(
492
- // env, "Invalid authentication tag length: %u", tag_len);
493
- }
504
+ if (!is_valid) {
505
+ jsi::detail::throwJSError(
506
+ runtime, "Invalid authentication tag length" + tag_len);
507
+ throw jsi::JSError(runtime,
508
+ "Invalid authentication tag length: " + tag_len);
509
+ }
494
510
 
495
- auth_tag_len_ = tag_len;
496
- auth_tag_state_ = kAuthTagKnown;
497
- // CHECK_LE(cipher->auth_tag_len_, sizeof(cipher->auth_tag_));
511
+ auth_tag_len_ = tag_len;
512
+ auth_tag_state_ = kAuthTagKnown;
513
+ // CHECK_LE(cipher->auth_tag_len_, sizeof(cipher->auth_tag_));
498
514
 
499
- memset(auth_tag_, 0, sizeof(auth_tag_));
500
- CopyTo(runtime, &authTagArrayBuffer, auth_tag_, auth_tag_len_);
515
+ memset(auth_tag_, 0, sizeof(auth_tag_));
516
+ CopyTo(runtime, &authTagArrayBuffer, auth_tag_, auth_tag_len_);
501
517
 
502
- return true;
503
- }));
518
+ return true;
519
+ }));
504
520
  }
505
521
 
506
522
  bool MGLCipherHostObject::MaybePassAuthTagToOpenSSL() {