Library / SDK
margelo/react-native-quick-crypto avatar
margelo/react-native-quick-crypto

react-native-quick-crypto puts OpenSSL behind a Node compatible API in your app

⚡️ A fast implementation of Node's `crypto` module written in C/C++ JSI

1,072 stars119 forksTypeScriptNOASSERTION

At a glance

What is it?
react-native-quick-crypto is a C and C++ implementation of Node's crypto module compiled into a React Native app through JSI and, on the 1.x line, Nitro Modules. The point is to swap the crypto import in an existing wallet or web3 app without rewriting the code, and the cost is a native build, a platform matrix and an algorithm coverage list you have to read.
Who is it for?
Adopt react-native-quick-crypto when you have a React Native app that already uses Node's crypto API and the JavaScript polyfill is the bottleneck, particularly a wallet or a web3 app where signing and hashing happen on the critical path. Do not adopt it for an app that needs an algorithm the implementation does not cover, because the library is explicit that not all cryptographic algorithms are supported yet.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 15 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A drop-in for the crypto import, not a new API

react-native-quick-crypto is a fast implementation of Node's crypto module, and the reason it exists is stated in the features list. Unlike any other current JS based polyfills, it is written in C and C++ JSI and provides much greater performance, especially on mobile devices.

The claim about speed is aggressive. The feature list says hundreds of times faster than all JS based solutions, and the Benchmarks section then explains the context, which is the honest framing to read.

There is a benchmark suite in the Example app in this repository that has benchmarks of algorithms against their pure JS counterparts. The README is careful about the purpose, saying it is not meant to disparage the other libraries, and that on the contrary they perform amazingly well when used in a server side Node environment. This library exists because React Native does not have that environment nor the Node Crypto API implementation at hand, so the benchmark suite is there to show the speedup against the alternative of using a pure JS library on React Native.

That is a fair framing, and it also tells you the use case. QuickCrypto can be used as a drop-in replacement for your web3 and crypto apps, or for CRDT based local first databases, to speed up common cryptography functions.

The API compatibility is the point, and it is why the library is worth the native build cost. You change how the crypto import resolves, and the rest of the code, which was written against the Node API, keeps working.

Two architecture lines, and the 1.x rewrite

The Versions table is short and it is the first thing to read, because the right line for you depends on your React Native version.

The 1.x line requires the new React Native architecture and uses Nitro Modules, which the table links to the Nitro repository. The 0.x line works on the old architecture, and the table marks the new one with a crossed fingers emoji and a hopeful word.

There is a note under the table. The minimum supported version of React Native is 0.75, and if you need to use earlier versions you should use the 0.x versions of this library.

So the decision is a fork in the road. An app on React Native 0.75 or newer with the new architecture enabled can use the current line, which is the one with the performance work in it. An app on an older React Native, or one that has not migrated to the new architecture, is on 0.x with the Bridge and JSI, which is the older and slower arrangement.

The Migration section then sets the expectation for the 1.0 refactor, which was the move to Nitro Modules. The goal in refactoring to v1.0 was to maintain API compatibility, and if you are upgrading to v1.0 from 0.x and find any discrepancies you are asked to open an issue.

That is the honest framing of a native module rewrite. The API is meant to be the same, and the places where it is not are exactly the places where you will find out at runtime rather than at compile time, since a native binding fails differently from a JavaScript import.

Installing it, and overriding the globals

The installation for a React Native project is two commands.

sh
bun add react-native-quick-crypto react-native-nitro-modules react-native-quick-base64
cd ios && pod install

Note that the nitro modules package and the quick base64 package are installed alongside, because the 1.x line depends on them.

For Expo the flow is shorter.

sh
expo install react-native-quick-crypto
expo prebuild

The prebuild step is there because a native module needs a development build, not the Expo Go client, and prebuild generates the native projects from the config.

There is also an optional step that is worth understanding rather than skipping. You can override global.Buffer and global.crypto in your application as early as possible, for example in index.js, by calling the install function.

ts
import { install } from 'react-native-quick-crypto';

install();

The reason it says as early as possible is that these globals are captured at import time by whatever runs first. If a library reads global.crypto during its own module initialisation, the override has to have happened before that library is imported, and in JavaScript module evaluation order is not something you control from the outside. So the call goes at the top of the entry point, before the other imports are evaluated in practice, and the wording in the README is the acknowledgement of that fragility.

Redirecting the crypto import in Metro or in Babel

This is the part that makes the library a drop-in, and there are two ways to do it.

The first is the Metro resolver, using the resolveRequest configuration option in your metro.config.js.

js
config.resolver.resolveRequest = (context, moduleName, platform) => {
  if (moduleName === 'crypto') {
    // when importing crypto, resolve to react-native-quick-crypto
    return context.resolveRequest(
      context,
      'react-native-quick-crypto',
      platform,
    )
  }
  // otherwise chain to the standard Metro resolver.
  return context.resolveRequest(context, moduleName, platform)
}

The second is babel-plugin-module-resolver, which you install as a dev dependency, and which aliases the imports in your code with the values you pass to it. It tricks any module that will try to import certain dependencies with the native versions required for React Native.

sh
yarn add --dev babel-plugin-module-resolver

The plugin then goes into your babel.config.js with an alias block, and the three dependencies it swaps are crypto, stream and buffer.

The note about Buffer is the detail that saves an afternoon. react-native-quick-crypto re-exports Buffer from @craftzdog/react-native-buffer, so you can use either as the buffer alias, and using react-native-quick-crypto ensures a single Buffer instance across your app.

Two Buffer instances in one app is the classic source of a subclassing bug that only appears on one platform, so the guidance to alias buffer to the quick crypto package rather than to the buffer package is about identity, not about speed.

After changing the bundler configuration you restart it with yarn start --reset-cache, because a resolver change is not picked up by a warm cache.

The algorithm coverage is the real limitation

The Limitations section is one paragraph and it is the most important one in the readme.

Not all cryptographic algorithms are supported yet, and the implementation coverage document has more details. If you need a specific algorithm, you are asked to open a feature request issue.

This is the shape of every native crypto module, and it is the reason the coverage document exists. A JavaScript polyfill covers the algorithms that JavaScript can express, which is most of the common ones, because the polyfill is the reference implementation ported. A native module is a binding to a library, here OpenSSL underneath, and it exposes what has been bound so far. The result is that the API surface looks like Node's and the coverage does not.

So the check before you adopt is concrete. Read the coverage document, find the algorithms your application actually calls, and look for the ones it uses in a signing or key derivation path. A missing algorithm in a wallet is a production incident, not a build error, because the failure happens at runtime on a device.

The feature request route is the stated remedy, and the fact that the library is used by wallets and web3 apps is why the coverage question is asked in such a prominent place rather than buried.

The monorepo, the toolchain and who pays for it

The top level listing describes a mature monorepo rather than a single package.

There is a packages/ directory holding the workspace packages, an example/ directory with a full application including an android/ and ios/ project, a.maestro/ directory for end to end tests, and a Gemfile and Gemfile.lock in the example, which is the Ruby toolchain used by the iOS side. There are docs/ and.docs/ directories, a config/ directory, scripts/ for the release and formatting scripts, and an example/ folder with its own metro, babel, jest and eslint configuration. A plans/ directory and an.agents/ directory sit alongside AGENTS.md and CLAUDE.md, and the.rules file is another convention file.

The package manifest shows the tooling in use. The workspace is driven by bun, with the scripts filtered through bun --filter across the packages, and the native code generator is nitrogen at 0.33.2, which is the tool that turns the Nitrogen specifications into the C++ bindings. Release automation uses release-it with the conventional changelog plugin, linting is eslint with the react-native plugin, and formatting is prettier with a separate.prettierrc.json and prettier.config.js. The C++ side is checked by a.clang-format file and CPPLINT.cfg, husky handles the git hooks and lint-staged runs the checks on the staged files. The postinstall script runs git submodule update --init --recursive, which tells you the OpenSSL sources are vendored as submodules.

The releases show the two version lines in the repository. v1.1.8 came on 2026-10-08 and v1.1.7 on 2026-08-15, and there is a third tag that is not a library release at all, openssl-apple-3.6.2 for static OpenSSL on Apple platforms, dated 2026-08-13.

Finally, the funding model is explicit. The library was built at Margelo, an app development agency, and there is an enterprise support contact address for organisations adopting it at scale.

Editorial conclusion

Adopt react-native-quick-crypto when you have a React Native app that already uses Node's crypto API and the JavaScript polyfill is the bottleneck, particularly a wallet or a web3 app where signing and hashing happen on the critical path. Do not adopt it for an app that needs an algorithm the implementation does not cover, because the library is explicit that not all cryptographic algorithms are supported yet. Verify first that your React Native version is 0.75 or newer, that the algorithms your code calls are in the implementation coverage document, and that your bundler resolves the crypto, stream and buffer imports, since a single unaliased import leaves you on the slow path.

Frequently asked questions

What is react-native-quick-crypto?

It is a fast implementation of Node's crypto module, written in C and C++ JSI and compiled into a React Native app. It is intended as a drop-in replacement for crypto-browserify or react-native-crypto, for web3 and crypto apps and for CRDT based local first databases.

Which React Native versions are supported?

The minimum supported version of React Native is 0.75. The 1.x line requires the new React Native architecture and uses Nitro Modules, while the 0.x line works on the old architecture with the Bridge and JSI, and is the one to use on earlier React Native versions.

How do I install it in a React Native app?

Run bun add react-native-quick-crypto react-native-nitro-modules react-native-quick-base64 and then cd ios && pod install. For Expo, run expo install react-native-quick-crypto followed by expo prebuild, since a native module needs a development build.

How do I make existing code use the native module?

Redirect the import. You can add a resolveRequest handler in metro.config.js that resolves crypto to react-native-quick-crypto, or use babel-plugin-module-resolver with an alias block swapping crypto, stream and buffer in your babel.config.js, then restart the bundler with yarn start --reset-cache.

Does it support every cryptographic algorithm?

No. The README states that not all cryptographic algorithms are supported yet and points to an implementation coverage document for the details, and asks for a feature request issue if you need a specific one.

What licence is react-native-quick-crypto under?

MIT for the library itself, and the README notes that it is heavily inspired by NodeJS Crypto, which is licensed under the Node.js licence.

Official sources

  1. Issues
  2. margelo/react-native-quick-crypto on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/margelo-react-native-quick-crypto.svg)](https://hysenlabs.com/projects/margelo-react-native-quick-crypto)

Was this useful?