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.
- package/README.md +38 -14
- package/android/src/main/AndroidManifest.xml +1 -1
- package/android/src/main/java/com/margelo/quickcrypto/QuickCryptoModule.java +70 -0
- package/android/src/main/java/com/{reactnativequickcrypto → margelo/quickcrypto}/QuickCryptoPackage.java +11 -12
- package/cpp/Cipher/MGLCipherHostObject.cpp +64 -48
- package/cpp/Cipher/MGLCipherKeys.cpp +1469 -0
- package/cpp/Cipher/MGLCipherKeys.h +124 -0
- package/cpp/Cipher/MGLCreateCipherInstaller.cpp +56 -53
- package/cpp/Cipher/MGLCreateCipherInstaller.h +5 -0
- package/cpp/Cipher/MGLCreateDecipherInstaller.cpp +56 -53
- package/cpp/Cipher/MGLGenerateKeyPairInstaller.cpp +107 -0
- package/cpp/Cipher/MGLGenerateKeyPairInstaller.h +32 -0
- package/cpp/Cipher/MGLGenerateKeyPairSyncInstaller.cpp +60 -0
- package/cpp/Cipher/MGLGenerateKeyPairSyncInstaller.h +35 -0
- package/cpp/Cipher/MGLPublicCipher.h +120 -0
- package/cpp/Cipher/MGLPublicCipherInstaller.h +113 -0
- package/cpp/Cipher/MGLRsa.cpp +188 -0
- package/cpp/Cipher/MGLRsa.h +61 -0
- package/cpp/JSIUtils/MGLJSIUtils.h +24 -0
- package/cpp/JSIUtils/MGLThreadAwareHostObject.h +1 -1
- package/cpp/MGLQuickCryptoHostObject.cpp +42 -3
- package/cpp/Utils/MGLUtils.cpp +156 -0
- package/cpp/Utils/MGLUtils.h +254 -0
- package/lib/commonjs/@types/crypto-browserify.d.js +2 -0
- package/lib/commonjs/@types/crypto-browserify.d.js.map +1 -0
- package/lib/commonjs/@types/stream-browserify.d.js +2 -0
- package/lib/commonjs/@types/stream-browserify.d.js.map +1 -0
- package/lib/commonjs/Cipher.js +310 -2
- package/lib/commonjs/Cipher.js.map +1 -1
- package/lib/commonjs/Hash.js +2 -2
- package/lib/commonjs/Hash.js.map +1 -1
- package/lib/commonjs/Hmac.js +2 -2
- package/lib/commonjs/Hmac.js.map +1 -1
- package/lib/commonjs/NativeQuickCrypto/Cipher.js +11 -0
- package/lib/commonjs/NativeQuickCrypto/Cipher.js.map +1 -1
- package/lib/commonjs/NativeQuickCrypto/NativeQuickCrypto.js.map +1 -1
- package/lib/commonjs/QuickCrypto.js +8 -0
- package/lib/commonjs/QuickCrypto.js.map +1 -1
- package/lib/commonjs/Utils.js +82 -1
- package/lib/commonjs/Utils.js.map +1 -1
- package/lib/commonjs/constants.js +86 -0
- package/lib/commonjs/constants.js.map +1 -0
- package/lib/commonjs/index.js +18 -10
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/keys.js +207 -0
- package/lib/commonjs/keys.js.map +1 -0
- package/lib/module/@types/crypto-browserify.d.js +2 -0
- package/lib/module/@types/crypto-browserify.d.js.map +1 -0
- package/lib/module/@types/stream-browserify.d.js +2 -0
- package/lib/module/@types/stream-browserify.d.js.map +1 -0
- package/lib/module/Cipher.js +298 -4
- package/lib/module/Cipher.js.map +1 -1
- package/lib/module/Hash.js +1 -1
- package/lib/module/Hash.js.map +1 -1
- package/lib/module/Hmac.js +1 -1
- package/lib/module/Hmac.js.map +1 -1
- package/lib/module/NativeQuickCrypto/Cipher.js +9 -1
- package/lib/module/NativeQuickCrypto/Cipher.js.map +1 -1
- package/lib/module/NativeQuickCrypto/NativeQuickCrypto.js.map +1 -1
- package/lib/module/QuickCrypto.js +8 -1
- package/lib/module/QuickCrypto.js.map +1 -1
- package/lib/module/Utils.js +67 -1
- package/lib/module/Utils.js.map +1 -1
- package/lib/module/constants.js +79 -0
- package/lib/module/constants.js.map +1 -0
- package/lib/module/index.js +13 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/keys.js +193 -0
- package/lib/module/keys.js.map +1 -0
- package/lib/typescript/Cipher.d.ts +59 -2
- package/lib/typescript/Hash.d.ts +1 -1
- package/lib/typescript/Hmac.d.ts +1 -1
- package/lib/typescript/NativeQuickCrypto/Cipher.d.ts +10 -0
- package/lib/typescript/NativeQuickCrypto/NativeQuickCrypto.d.ts +6 -1
- package/lib/typescript/QuickCrypto.d.ts +105 -1
- package/lib/typescript/Utils.d.ts +11 -0
- package/lib/typescript/constants.d.ts +75 -0
- package/lib/typescript/index.d.ts +208 -1
- package/lib/typescript/keys.d.ts +60 -0
- package/package.json +7 -6
- package/react-native-quick-crypto.podspec +1 -1
- package/src/.DS_Store +0 -0
- package/src/@types/crypto-browserify.d.ts +4 -0
- package/src/@types/stream-browserify.d.ts +4 -0
- package/src/Cipher.ts +446 -4
- package/src/Hash.ts +1 -1
- package/src/Hmac.ts +1 -1
- package/src/NativeQuickCrypto/Cipher.ts +44 -0
- package/src/NativeQuickCrypto/NativeQuickCrypto.ts +13 -1
- package/src/QuickCrypto.ts +12 -0
- package/src/Utils.ts +91 -0
- package/src/constants.ts +79 -0
- package/src/index.ts +15 -1
- package/src/keys.ts +297 -0
- 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
|
|
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
|
-
|
|
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
|
|
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
|
|
38
|
+
Creating a Wallet took yyyms
|
|
26
39
|
```
|
|
27
40
|
|
|
28
41
|
---
|
|
29
42
|
|
|
30
43
|
## Installation
|
|
31
44
|
|
|
32
|
-
|
|
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
|
-
|
|
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 `
|
|
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
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
+
|
|
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.
|
|
@@ -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.
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
449
|
-
|
|
450
|
-
!arguments[0].
|
|
451
|
-
|
|
452
|
-
|
|
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
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
462
|
+
if (!ctx_ || !IsAuthenticatedMode() || isCipher_ ||
|
|
463
|
+
auth_tag_state_ != kAuthTagUnknown) {
|
|
464
|
+
return false;
|
|
465
|
+
}
|
|
459
466
|
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
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
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
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
|
-
|
|
486
|
+
// unsigned int tag_len = auth_tag.size();
|
|
471
487
|
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
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
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
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
|
-
|
|
496
|
-
|
|
497
|
-
|
|
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
|
-
|
|
500
|
-
|
|
515
|
+
memset(auth_tag_, 0, sizeof(auth_tag_));
|
|
516
|
+
CopyTo(runtime, &authTagArrayBuffer, auth_tag_, auth_tag_len_);
|
|
501
517
|
|
|
502
|
-
|
|
503
|
-
|
|
518
|
+
return true;
|
|
519
|
+
}));
|
|
504
520
|
}
|
|
505
521
|
|
|
506
522
|
bool MGLCipherHostObject::MaybePassAuthTagToOpenSSL() {
|