Increase Speed and Security With Native Crypto Libraries

In short

The article highlights the challenge of using crypto libraries in React Native due to the lack of built-in implementations, leading to security risks and performance issues. The common practice of polyfilling from browser or Node.js APIs can result in non-standardization and potential vulnerabilities. The recommended solution is to use modern native implementations like react-native-get-random-values for specific crypto functions, ensuring better security, performance, and a smaller bundle size in web3 apps.

Issue

Crypto libraries polyfilled from the browser or Node.js APIs open the door to security issues and are not performant

Web3 apps share similarities with the apps we've been accustomed to over the last decade. They also use native features like the Camera and Geolocation, and often also require a centralized server, besides interacting with the blockchain. The key distinction lies in occasional cryptographic requirements, such as hashing values, message signing with a private key, or generating secure random numbers cryptographically.

The web3 space as a whole is still new but can be considered mature on the web. There are plenty of web apps running stable for years and a good set of libraries and abstractions that allow a productive workflow. Therefore, it's only natural that when porting these applications to the React Native environment, developers will try going through the already known path, looking to use the same APIs.

The problem is that crypto utilities and functions are not provided by the JavaScript spec, but by the environment itself i.e. the browser, Node.js, Deno, Bun, etc., and the React Native environment lacks a native implementation.

There’s a GitHub discussion on adding a global crypto implementation to the React Native core (and even Hermes, the JavaScript engine created for React Native). However, following the React Native Lean Core efforts, the current understanding is that it's best to keep it as external packages by contributors committed to auditing and maintaining such critical packages.

Attempts were made to solve the issue

Over the past few years, several packages emerged to address this challenge by polyfilling the global <rte-code>crypto<rte-code> API with either the browser or Node.js implementation. However, this approach often comes with drawbacks, including an increased bundle size, non-standardization (as the browser crypto spec differs slightly from the Node.js spec), incomplete implementation for specific functions, and a potential security vulnerability.

Probably the most famous package, <rte-code>react-native-crypto<rte-code> (now deprecated) was a clone of <rte-code>crypto-browserify<rte-code> (a port of the Node.js implementation to the browser) and relied on traversing the <rte-code>node_modules<rte-code> directory and manually applying patches to the files inside. While this works, it opens the door to many security issues and is hard to maintain.

Solution

Use modern native implementations

Often, even web3 apps will only need a very specific subset of the available crypto functions. More specifically, most will need only <rte-code>getRandomValues()<rte-code>, a Cryptographically secure pseudorandom number generator (CSPRNG).

This is a function that can't be implemented relying on JavaScript's <rte-code>Math.random()<rte-code> because it can't guarantee that the result will contain enough entropy to be considered secure.

And that's where the native implementations come in. react-native-get-random-values by Linus Unnebäck is a native implementation of <rte-code>getRandomValues()<rte-code> committed to doing just that, and doing it well. It is battle-tested with more than 890.000 downloads weekly and uses <rte-code>SecureRandom<rte-code> on Android, and <rte-code>SecRandomCopyBytes<rte-code> on iOS, both APIs that are present and well-tested in the operating systems for many years.

The implementation is minimal and allows for easier auditing against security issues, within a very focused package.

This is the whole iOS implementation in Objective-C:

And the Android implementation in Java:

If you are using Expo, then you should consider the recently-revamped Expo Crypto, that contains a very similar implementation for <rte-code>getRandomValues<rte-code> in addition to other utilities like string digests and UUID generation. It will plug perfectly into your Expo app, and you can expect the same refined API and attention to detail as with all other Expo modules.

Finally, if you need a more complete crypto package, you should go for Margelo’s react-native-quick-crypto. It aims to be a drop-in replacement for the old <rte-code>react-native-crypto<rte-code> with a bigger set of crypto functions and provides great performance by taking advantage of directly invoking methods through C/C++ JSI.

Benefits

Less security attack vectors, faster performance, and a smaller bundle size

Security should always be a top priority, and even more when talking about web3 apps, which usually deal with financial and/or other unrecoverable assets from your users.

By using the options suggested above, you take another step towards a more secure and performant app, with an overall smaller bundle size without relying on clunky polyfills. It's a win-win situation, both for DX as well as UX.

Latest update:
March 6, 2024

FAQ

No items found.
React Galaxy City
Get our newsletter

By subscribing to the newsletter, you give us consent to use your email address to deliver curated content. We will process your email address until you unsubscribe or otherwise object to the processing of your personal data for marketing purposes. You can unsubscribe or exercise other privacy rights at any time. For details, visit our Privacy Policy.

Callstack astronaut
Download our ebook

I agree to receive electronic communications By checking any of the boxes, you give us consent to use your email address for our direct marketing purposes, including the latest tech & biz updates. We will process your email address and names (if you have entered them into the above form) until you withdraw your consent to the processing of your names, or unsubscribe, or otherwise object to the processing of your personal data for marketing purposes. You can unsubscribe or exercise other privacy rights at any time. For details, visit our Privacy Policy.

By pressing the “Download” button, you give us consent to use your email address to send you a copy of the Ultimate Guide to React Native Optimization.