react-native-quick-crypto 1.0.0-beta.1 → 1.0.0-beta.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 ADDED
@@ -0,0 +1,170 @@
1
+ <a href="https://margelo.io">
2
+ <img src="./docs/img/banner.svg" width="100%" />
3
+ </a>
4
+
5
+ # ⚡️ react-native-quick-crypto
6
+
7
+ A fast implementation of Node's `crypto` module.
8
+
9
+ > Note: This version `1.x` is undergoing a major refactor, porting to New Architecture, Bridgeless, and [`Nitro Modules`](https://github.com/mrousavy/react-native-nitro) and is incomplete compared to the `0.x` version. Status, as always, will be represented in [implementation-coverage.md](../blob/main/docs/implementation-coverage.md).
10
+
11
+ ## Features
12
+
13
+ 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.
14
+ QuickCrypto can be used as a drop-in replacement for your Web3/Crypto apps to speed up common cryptography functions.
15
+
16
+ - 🏎️ Up to 58x faster than all other solutions
17
+ - ⚡️ Lightning fast implementation with pure C++ and JSI, instead of JS
18
+ - 🧪 Well tested in JS and C++ (OpenSSL)
19
+ - 💰 Made for crypto apps and Wallets
20
+ - 🔢 Secure native compiled cryptography
21
+ - 🔁 Easy drop-in replacement for [crypto-browserify](https://github.com/browserify/crypto-browserify) or [react-native-crypto](https://github.com/tradle/react-native-crypto)
22
+
23
+ ## Versions
24
+
25
+ | Version | RN Architecture | Modules |
26
+ | ------- | ------ | ------- |
27
+ | `1.x` | new [->](https://github.com/reactwg/react-native-new-architecture/blob/main/docs/enable-apps.md) | Nitro Modules [->](https://github.com/margelo/react-native-nitro) |
28
+ | `0.x` | old | Bridge & JSI |
29
+
30
+ ## Benchmarks
31
+
32
+ For example, creating a Wallet using ethers.js uses complex algorithms to generate a private-key/mnemonic-phrase pair:
33
+
34
+ ```ts
35
+ const start = performance.now();
36
+ const wallet = ethers.Wallet.createRandom();
37
+ const end = performance.now();
38
+ console.log(`Creating a Wallet took ${end - start} ms.`);
39
+ ```
40
+
41
+ **Without** react-native-quick-crypto 🐢:
42
+
43
+ ```
44
+ Creating a Wallet took 16862 ms
45
+ ```
46
+
47
+ **With** react-native-quick-crypto ⚡️:
48
+
49
+ ```
50
+ Creating a Wallet took 289 ms
51
+ ```
52
+
53
+ ---
54
+
55
+ ## Installation
56
+
57
+ <h3>
58
+ React Native  <a href="#"><img src="./docs/img/react-native.png" height="15" /></a>
59
+ </h3>
60
+
61
+ ```sh
62
+ yarn add react-native-quick-crypto
63
+ cd ios && pod install
64
+ ```
65
+
66
+ <h3>
67
+ Expo  <a href="#"><img src="./docs/img/expo.png" height="12" /></a>
68
+ </h3>
69
+
70
+ ```sh
71
+ expo install react-native-quick-crypto
72
+ expo prebuild
73
+ ```
74
+
75
+ Optional: override `global.Buffer` and `global.crypto` in your application as early as possible for example in index.js.
76
+
77
+ ```ts
78
+ import { install } from 'react-native-quick-crypto';
79
+
80
+ install();
81
+ ```
82
+
83
+ ## Replace `crypto-browserify`
84
+
85
+ If you are using a library that depends on `crypto`, instead of polyfilling it with `crypto-browserify` (or `react-native-crypto`) you can use `react-native-quick-crypto` for a fully native implementation. This way you can get much faster crypto operations with just a single-line change!
86
+
87
+ ### Using metro config
88
+
89
+ Use the [`resolveRequest`](https://facebook.github.io/metro/docs/resolution#resolverequest-customresolver) configuration option in your `metro.config.js`
90
+
91
+ ```js
92
+ config.resolver.resolveRequest = (context, moduleName, platform) => {
93
+ if (moduleName === 'crypto') {
94
+ // when importing crypto, resolve to react-native-quick-crypto
95
+ return context.resolveRequest(
96
+ context,
97
+ 'react-native-quick-crypto',
98
+ platform,
99
+ )
100
+ }
101
+ // otherwise chain to the standard Metro resolver.
102
+ return context.resolveRequest(context, moduleName, platform)
103
+ }
104
+ ```
105
+
106
+ ### Using babel-plugin-module-resolver
107
+
108
+ You need to install `babel-plugin-module-resolver`, it's a babel plugin that will alias any imports in the code with the values you pass to it. It tricks any module that will try to import certain dependencies with the native versions we require for React Native.
109
+
110
+ ```sh
111
+ yarn add --dev babel-plugin-module-resolver
112
+ ```
113
+
114
+ Then, in your `babel.config.js`, add the plugin to swap the `crypto`, `stream` and `buffer` dependencies:
115
+
116
+ ```diff
117
+ module.exports = {
118
+ presets: ['module:metro-react-native-babel-preset'],
119
+ plugins: [
120
+ + [
121
+ + 'module-resolver',
122
+ + {
123
+ + alias: {
124
+ + 'crypto': 'react-native-quick-crypto',
125
+ + 'stream': 'readable-stream',
126
+ + 'buffer': '@craftzdog/react-native-buffer',
127
+ + },
128
+ + },
129
+ + ],
130
+ ...
131
+ ],
132
+ };
133
+ ```
134
+
135
+ Then restart your bundler using `yarn start --reset-cache`.
136
+
137
+ ## Usage
138
+
139
+ For example, to hash a string with SHA256 you can do the following:
140
+
141
+ ```ts
142
+ import QuickCrypto from 'react-native-quick-crypto';
143
+
144
+ const hashed = QuickCrypto.createHash('sha256')
145
+ .update('Damn, Margelo writes hella good software!')
146
+ .digest('hex');
147
+ ```
148
+
149
+ ## Limitations
150
+
151
+ As the library uses JSI for synchronous native methods access, remote debugging (e.g. with Chrome) is no longer possible. Instead, you should use [Flipper](https://fbflipper.com).
152
+
153
+ Not all cryptographic algorithms are supported yet. See the [implementation coverage](./docs/implementation-coverage.md) document for more details. If you need a specific algorithm, please open a `feature request` issue and we'll see what we can do.
154
+
155
+ ## Community Discord
156
+
157
+ [Join the Margelo Community Discord](https://discord.gg/6CSHz2qAvA) to chat about react-native-quick-crypto or other Margelo libraries.
158
+
159
+ ## Adopting at scale
160
+
161
+ react-native-quick-crypto was built at Margelo, an elite app development agency. For enterprise support or other business inquiries, contact us at <a href="mailto:hello@margelo.io?subject=Adopting react-native-quick-crypto at scale">hello@margelo.io</a>!
162
+
163
+ ## Contributing
164
+
165
+ See the [contributing guide](CONTRIBUTING.md) to learn how to contribute to the repository and the development workflow.
166
+
167
+ ## License
168
+
169
+ - react-native-quick-crypto is licensed under MIT.
170
+ - react-native-quick-crypto is heavily inspired by NodeJS Crypto, which is licensed under [nodejs/LICENSE](https://github.com/nodejs/node/blob/main/LICENSE).
@@ -0,0 +1,34 @@
1
+ #include "HybridRandom.hpp"
2
+
3
+ #include <openssl/err.h>
4
+ #include <openssl/rand.h>
5
+
6
+ namespace margelo::crypto {
7
+
8
+ using namespace margelo::nitro;
9
+ using namespace margelo::nitro::crypto;
10
+
11
+ std::future<std::shared_ptr<ArrayBuffer>> HybridRandom::randomFill(const std::shared_ptr<ArrayBuffer>& buffer, double dOffset,
12
+ double dSize) {
13
+ size_t size = checkSize(dSize);
14
+ // copy the JSArrayBuffer that we do not own into a NativeArrayBuffer that we do own, before passing to sync function
15
+ uint8_t* data = new uint8_t[size];
16
+ memcpy(data, buffer.get()->data(), size);
17
+ std::shared_ptr<ArrayBuffer> nativeBuffer = std::make_shared<NativeArrayBuffer>(data, size, false);
18
+
19
+ return std::async(std::launch::async,
20
+ [this, nativeBuffer, dOffset, dSize]() { return this->randomFillSync(nativeBuffer, dOffset, dSize); });
21
+ };
22
+
23
+ std::shared_ptr<ArrayBuffer> HybridRandom::randomFillSync(const std::shared_ptr<ArrayBuffer>& buffer, double dOffset, double dSize) {
24
+ size_t size = checkSize(dSize);
25
+ size_t offset = checkOffset(dSize, dOffset);
26
+ uint8_t* data = buffer.get()->data();
27
+
28
+ if (RAND_bytes(data + offset, (int)size) != 1) {
29
+ throw std::runtime_error("error calling RAND_bytes" + std::to_string(ERR_get_error()));
30
+ }
31
+ return std::make_shared<NativeArrayBuffer>(data, size, false);
32
+ };
33
+
34
+ } // namespace margelo::crypto
@@ -0,0 +1,44 @@
1
+ #include <NitroModules/ArrayBuffer.hpp>
2
+ #include <cmath>
3
+ #include <future>
4
+
5
+ #include "HybridRandomSpec.hpp"
6
+
7
+ #ifdef ANDROID
8
+ #include "utils/Utils.hpp"
9
+ #else
10
+ #include "Utils.hpp"
11
+ #endif
12
+
13
+ namespace margelo::crypto {
14
+
15
+ using namespace margelo::nitro;
16
+ using namespace margelo::nitro::crypto;
17
+
18
+ class HybridRandom : public HybridRandomSpec {
19
+ public:
20
+ std::future<std::shared_ptr<ArrayBuffer>> randomFill(const std::shared_ptr<ArrayBuffer>& buffer, double dOffset, double dSize) override;
21
+ std::shared_ptr<ArrayBuffer> randomFillSync(const std::shared_ptr<ArrayBuffer>& buffer, double dOffset, double dSize) override;
22
+ };
23
+
24
+ inline size_t checkSize(double size) {
25
+ if (!CheckIsUint32(size)) {
26
+ throw std::runtime_error("size must be uint32");
27
+ }
28
+ if (static_cast<uint32_t>(size) > pow(2, 31) - 1) {
29
+ throw std::runtime_error("size must be less than 2^31 - 1");
30
+ }
31
+ return static_cast<size_t>(size);
32
+ }
33
+
34
+ inline size_t checkOffset(double size, double offset) {
35
+ if (!CheckIsUint32(offset)) {
36
+ throw std::runtime_error("offset must be uint32");
37
+ }
38
+ if (offset > size) {
39
+ throw std::runtime_error("offset must be less than size");
40
+ }
41
+ return static_cast<size_t>(offset);
42
+ }
43
+
44
+ } // namespace margelo::crypto
@@ -0,0 +1,9 @@
1
+ #include <limits>
2
+
3
+ inline bool CheckIsUint32(double value) {
4
+ return (value >= std::numeric_limits<uint32_t>::lowest() && value <= std::numeric_limits<uint32_t>::max());
5
+ }
6
+
7
+ inline bool CheckIsInt32(double value) {
8
+ return (value >= std::numeric_limits<int32_t>::lowest() && value <= std::numeric_limits<int32_t>::max());
9
+ }
@@ -0,0 +1,45 @@
1
+ #
2
+ # QuickCrypto+autolinking.cmake
3
+ # Tue Aug 13 2024
4
+ # This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
5
+ # https://github.com/mrousavy/react-native-nitro
6
+ # Copyright © 2024 Marc Rousavy @ Margelo
7
+ #
8
+
9
+ # This is a CMake file that adds all files generated by Nitrogen
10
+ # to the current CMake project.
11
+ #
12
+ # To use it, add this to your CMakeLists.txt:
13
+ # ```cmake
14
+ # include(${CMAKE_SOURCE_DIR}/../nitrogen/generated/android/QuickCrypto+autolinking.cmake)
15
+ # ```
16
+
17
+ # Add all headers that were generated by Nitrogen
18
+ include_directories(
19
+ "../nitrogen/generated/shared/c++"
20
+ "../nitrogen/generated/android/c++"
21
+ )
22
+
23
+ # Add all .cpp sources that were generated by Nitrogen
24
+ target_sources(
25
+ # CMake project name (Android C++ library name)
26
+ QuickCrypto PRIVATE
27
+ # Shared Nitrogen C++ sources
28
+ ../nitrogen/generated/shared/c++/HybridRandomSpec.cpp
29
+ # Android-specific Nitrogen C++ sources
30
+
31
+ )
32
+
33
+ # Add all libraries required by the generated specs
34
+ find_package(fbjni REQUIRED) # <-- Used for communication between Java <-> C++
35
+ find_package(ReactAndroid REQUIRED) # <-- Used to set up React Native bindings (e.g. CallInvoker/TurboModule)
36
+ find_package(react-native-nitro-modules REQUIRED) # <-- Used to create all HybridObjects and use the Nitro core library
37
+
38
+ # Link all libraries together
39
+ target_link_libraries(
40
+ QuickCrypto
41
+ fbjni::fbjni # <-- Facebook C++ JNI helpers
42
+ ReactAndroid::jsi # <-- RN: JSI
43
+ ReactAndroid::react_nativemodule_core # <-- RN: TurboModules Core
44
+ react-native-nitro-modules::NitroModules # <-- NitroModules Core :)
45
+ )
@@ -0,0 +1,26 @@
1
+ ///
2
+ /// QuickCrypto+autolinking.gradle
3
+ /// Tue Aug 13 2024
4
+ /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
5
+ /// https://github.com/mrousavy/react-native-nitro
6
+ /// Copyright © 2024 Marc Rousavy @ Margelo
7
+ ///
8
+
9
+ /// This is a Gradle file that adds all files generated by Nitrogen
10
+ /// to the current Gradle project.
11
+ ///
12
+ /// To use it, add this to your build.gradle:
13
+ /// ```gradle
14
+ /// apply from: '../nitrogen/generated/android/QuickCrypto+autolinking.gradle'
15
+ /// ```
16
+
17
+ android {
18
+ sourceSets {
19
+ main {
20
+ java.srcDirs += [
21
+ // Nitrogen files
22
+ "${project.projectDir}/../nitrogen/generated/android/kotlin"
23
+ ]
24
+ }
25
+ }
26
+ }
@@ -0,0 +1,57 @@
1
+ #
2
+ # QuickCrypto+autolinking.rb
3
+ # Tue Aug 13 2024
4
+ # This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
5
+ # https://github.com/mrousavy/react-native-nitro
6
+ # Copyright © 2024 Marc Rousavy @ Margelo
7
+ #
8
+
9
+ # This is a Ruby script that adds all files generated by Nitrogen
10
+ # to the given podspec.
11
+ #
12
+ # To use it, add this to your .podspec:
13
+ # ```ruby
14
+ # Pod::Spec.new do |spec|
15
+ # # ...
16
+ #
17
+ # # Add all files generated by Nitrogen
18
+ # load 'nitrogen/generated/ios/QuickCrypto+autolinking.rb'
19
+ # add_nitrogen_files(spec)
20
+ # end
21
+ # ```
22
+
23
+ def add_nitrogen_files(spec)
24
+ Pod::UI.puts "[NitroModules] Adding QuickCrypto specs..."
25
+
26
+ spec.dependency "NitroModules"
27
+
28
+ current_source_files = spec.attributes_hash['source_files'] || []
29
+ spec.source_files = current_source_files + [
30
+ # Generated cross-platform specs
31
+ "nitrogen/generated/shared/**/*.{h,hpp,c,cpp,swift}",
32
+ # Generated bridges for the cross-platform specs
33
+ "nitrogen/generated/ios/**/*.{h,hpp,c,cpp,swift}",
34
+ ]
35
+
36
+ current_public_header_files = spec.attributes_hash['public_header_files'] || []
37
+ spec.public_header_files = current_public_header_files + [
38
+ # Generated specs
39
+ "nitrogen/generated/shared/**/*.{h,hpp}",
40
+ # Swift to C++ bridging helpers
41
+ "nitrogen/generated/ios/QuickCrypto-Swift-Cxx-Bridge.hpp"
42
+ ]
43
+
44
+ current_private_header_files = spec.attributes_hash['private_header_files'] || []
45
+ spec.private_header_files = current_private_header_files + [
46
+ # iOS specific specs
47
+ "nitrogen/generated/ios/c++/**/*.{h,hpp}",
48
+ ]
49
+
50
+ current_pod_target_xcconfig = spec.attributes_hash['pod_target_xcconfig'] || {}
51
+ spec.pod_target_xcconfig = current_pod_target_xcconfig.merge({
52
+ # Use C++ 20
53
+ "CLANG_CXX_LANGUAGE_STANDARD" => "c++20",
54
+ # Enables C++ <-> Swift interop (by default it's only C)
55
+ "SWIFT_OBJC_INTEROP_MODE" => "objcxx",
56
+ })
57
+ end
@@ -0,0 +1,9 @@
1
+ ///
2
+ /// QuickCrypto-Swift-Cxx-Bridge.cpp
3
+ /// Tue Aug 13 2024
4
+ /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
5
+ /// https://github.com/mrousavy/react-native-nitro
6
+ /// Copyright © 2024 Marc Rousavy @ Margelo
7
+ ///
8
+
9
+ #include "QuickCrypto-Swift-Cxx-Bridge.hpp"
@@ -0,0 +1,25 @@
1
+ ///
2
+ /// QuickCrypto-Swift-Cxx-Bridge.hpp
3
+ /// Tue Aug 13 2024
4
+ /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
5
+ /// https://github.com/mrousavy/react-native-nitro
6
+ /// Copyright © 2024 Marc Rousavy @ Margelo
7
+ ///
8
+
9
+ #pragma once
10
+
11
+ // Forward declarations of C++ defined types
12
+
13
+
14
+ // Include C++ defined types
15
+
16
+
17
+ /**
18
+ * Contains specialized versions of C++ templated types so they can be accessed from Swift,
19
+ * as well as helper functions to interact with those C++ types from Swift.
20
+ */
21
+ namespace margelo::nitro::crypto::bridge::swift {
22
+
23
+
24
+
25
+ } // namespace margelo::nitro::crypto::bridge::swift
@@ -0,0 +1,29 @@
1
+ ///
2
+ /// QuickCrypto-Swift-Cxx-Umbrella.hpp
3
+ /// Tue Aug 13 2024
4
+ /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
5
+ /// https://github.com/mrousavy/react-native-nitro
6
+ /// Copyright © 2024 Marc Rousavy @ Margelo
7
+ ///
8
+
9
+ #pragma once
10
+
11
+ // Forward declarations of C++ defined types
12
+ // Forward declaration of `ArrayBuffer` to properly resolve imports.
13
+ namespace NitroModules { class ArrayBuffer; }
14
+
15
+ // Include C++ defined types
16
+ #include <NitroModules/ArrayBuffer.hpp>
17
+
18
+ // C++ helpers for Swift
19
+ #include "QuickCrypto-Swift-Cxx-Bridge.hpp"
20
+
21
+ // Forward declarations of Swift defined types
22
+
23
+
24
+ // Include Swift defined types
25
+ #if __has_include("QuickCrypto-Swift.h")
26
+ #include "QuickCrypto-Swift.h"
27
+ #else
28
+ #error QuickCrypto's autogenerated Swift header cannot be found! Make sure the Swift module's name is actually "QuickCrypto", and try building the app first.
29
+ #endif
@@ -0,0 +1,23 @@
1
+ ///
2
+ /// HybridRandomSpec.cpp
3
+ /// Tue Aug 13 2024
4
+ /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
5
+ /// https://github.com/mrousavy/react-native-nitro
6
+ /// Copyright © 2024 Marc Rousavy @ Margelo
7
+ ///
8
+
9
+ #include "HybridRandomSpec.hpp"
10
+
11
+ namespace margelo::nitro::crypto {
12
+
13
+ void HybridRandomSpec::loadHybridMethods() {
14
+ // load base methods/properties
15
+ HybridObject::loadHybridMethods();
16
+ // load custom methods/properties
17
+ registerHybrids(this, [](Prototype& prototype) {
18
+ prototype.registerHybridMethod("randomFill", &HybridRandomSpec::randomFill);
19
+ prototype.registerHybridMethod("randomFillSync", &HybridRandomSpec::randomFillSync);
20
+ });
21
+ }
22
+
23
+ } // namespace margelo::nitro::crypto
@@ -0,0 +1,62 @@
1
+ ///
2
+ /// HybridRandomSpec.hpp
3
+ /// Tue Aug 13 2024
4
+ /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
5
+ /// https://github.com/mrousavy/react-native-nitro
6
+ /// Copyright © 2024 Marc Rousavy @ Margelo
7
+ ///
8
+
9
+ #pragma once
10
+
11
+ #if __has_include(<NitroModules/HybridObject.hpp>)
12
+ #include <NitroModules/HybridObject.hpp>
13
+ #else
14
+ #error NitroModules cannot be found! Are you sure you installed NitroModules properly?
15
+ #endif
16
+
17
+ // Forward declaration of `ArrayBuffer` to properly resolve imports.
18
+ namespace NitroModules { class ArrayBuffer; }
19
+
20
+ #include <NitroModules/ArrayBuffer.hpp>
21
+
22
+ namespace margelo::nitro::crypto {
23
+
24
+ using namespace margelo::nitro;
25
+
26
+ /**
27
+ * An abstract base class for `Random`
28
+ * Inherit this class to create instances of `HybridRandomSpec` in C++.
29
+ * @example
30
+ * ```cpp
31
+ * class HybridRandom: public HybridRandomSpec {
32
+ * // ...
33
+ * };
34
+ * ```
35
+ */
36
+ class HybridRandomSpec: public HybridObject {
37
+ public:
38
+ // Constructor
39
+ explicit HybridRandomSpec(): HybridObject(TAG) { }
40
+
41
+ // Destructor
42
+ ~HybridRandomSpec() { }
43
+
44
+ public:
45
+ // Properties
46
+
47
+
48
+ public:
49
+ // Methods
50
+ virtual std::future<std::shared_ptr<ArrayBuffer>> randomFill(const std::shared_ptr<ArrayBuffer>& buffer, double offset, double size) = 0;
51
+ virtual std::shared_ptr<ArrayBuffer> randomFillSync(const std::shared_ptr<ArrayBuffer>& buffer, double offset, double size) = 0;
52
+
53
+ protected:
54
+ // Hybrid Setup
55
+ void loadHybridMethods() override;
56
+
57
+ protected:
58
+ // Tag for logging
59
+ static constexpr auto TAG = "Random";
60
+ };
61
+
62
+ } // namespace margelo::nitro::crypto
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-quick-crypto",
3
- "version": "1.0.0-beta.1",
3
+ "version": "1.0.0-beta.2",
4
4
  "description": "A fast implementation of Node's `crypto` module written in C/C++ JSI",
5
5
  "type": "module",
6
6
  "main": "lib/commonjs/index",
@@ -10,17 +10,15 @@
10
10
  "source": "src/index",
11
11
  "files": [
12
12
  "src",
13
- "react-native.config.js",
14
13
  "lib",
15
14
  "android/build.gradle",
16
15
  "android/gradle.properties",
17
16
  "android/CMakeLists.txt",
18
17
  "android/src",
19
- "ios/**/*.h",
20
- "ios/**/*.m",
21
- "ios/**/*.mm",
22
- "ios/**/*.cpp",
23
- "ios/**/*.swift",
18
+ "ios",
19
+ "cpp",
20
+ "nitrogen",
21
+ "react-native.config.js",
24
22
  "app.plugin.js",
25
23
  "*.podspec",
26
24
  "README.md",