If you've ever tried to implement proper RSA-OAEP encryption in a React Native app, you know the pain. You open the Node.js crypto docs, write what looks like perfectly reasonable code — and then you hit the wall: React Native doesn't support Node.js core modules.

That frustration is exactly what led me to build @taronk/react-native-rsa-oaep.

The Problem

Modern security standards recommend RSA-OAEP (Optimal Asymmetric Encryption Padding) over older PKCS#1 v1.5 padding. OAEP is probabilistic, resistant to chosen-ciphertext attacks, and is what your backend (Node.js, Java, Python) almost certainly uses.

But when you search for RSA-OAEP in the React Native ecosystem, you quickly discover:

  • react-native-rsa-native uses PKCS#1 — which means cross-platform decryption breaks when your server uses OAEP
  • react-native-rsa is a JS-only port that hasn't been updated in years
  • node-forge can do it, but is a heavy dependency with a confusing API
  • Wrapping the Web Crypto API works on some platforms but not consistently across iOS and Android

Developers end up patching things together, hitting padding mismatch errors, and wondering why the server can't decrypt what the app encrypted.

The Approach

I wanted a package that:

  1. Uses RSA-OAEP specifically — not PKCS#1, not a generic RSA wrapper
  2. Interoperates with standard backends — Node.js, Java, Python, OpenSSL
  3. Works on both iOS and Android without native module linking complexity
  4. Has a dead-simple API — encrypt with a public key, done

Here's what using it looks like:

import { encryptRSAOAEP } from '@taronk/react-native-rsa-oaep';

const publicKey = `-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...
-----END PUBLIC KEY-----`;

const encrypted = await encryptRSAOAEP('my secret data', publicKey);
// Returns a base64-encoded ciphertext your server can decrypt with the private key

That's it. No configuration, no padding flags, no base64 juggling.

Why Cross-Platform Compatibility Matters

The most common real-world scenario is this: your React Native app encrypts sensitive data (a token, a password, PII) using the server's public key, and your Node.js / Java / Python backend decrypts it with the private key.

This only works if both sides agree on the padding scheme. OAEP is the modern standard — and it's what you get with:

// Node.js server-side decryption
crypto.privateDecrypt(
  { key: privateKey, padding: crypto.constants.RSA_PKCS1_OAEP_PADDING },
  Buffer.from(encryptedData, 'base64')
);

My package is built to produce output that this decrypts correctly, out of the box.

The Tricky Parts

1. React Native's JS engine doesn't have window.crypto.subtle reliably

The Web Crypto API (SubtleCrypto) is available in browsers but inconsistent in React Native's Hermes and JSC engines. I had to use a carefully chosen pure-JS cryptography implementation under the hood that produces standards-compliant output.

2. PEM key parsing

Public keys come in different formats — PKCS#8, PKCS#1, with or without headers. The package handles all common PEM formats so you can paste the key from your backend directly without transformation.

3. Base64 output

The output is standard base64, making it safe to include in JSON payloads and HTTP requests without additional encoding.

Install It

npm install @taronk/react-native-rsa-oaep

When Should You Use This?

  • Encrypting sensitive fields before sending to a server
  • Secure key exchange (encrypting an AES session key with RSA)
  • Any scenario where your backend expects RSA-OAEP encrypted data

What's Next

I'm working on adding:

  • Support for decrypt (for scenarios where the private key lives on the device)
  • SHA-256 and SHA-512 hash options for the OAEP mask generation function

Feedback, issues, and PRs are welcome on GitHub. If this package saved you time, a ⭐ on the repo means a lot.

Check out the package: npmjs.com/package/@taronk/react-native-rsa-oaep