Encryption
npm install rn-encryptionrn-encryption LibraryThis guide explains how to directly access methods from the rn-encryption library in a React Native project, including usage examples for AES, RSA, Hashing, HMAC, Random String, and Base64 utilities.
- Mobile (iOS & Android): Utilizes native implementations through JSI (JavaScript Interface) via Turbo Modules for encryption.
- Web: Leverages crypto.subtle for encryption functionality. https://www.npmjs.com/package/web-secure-encryption is being used to support encryption for web.
---
1. Library Installation
2. Requirements
3. Setup in React Native
4. Direct Method Import
5. API Overview
6. Usage Examples
7. Troubleshooting
8. Best Practices
9. FAQ
10. Security Best Practices
---
Install the library using npm or yarn:
``bash
expo install rn-encryption
$3
For Android:
`bash
cd android && ./gradlew clean && cd ..
npx react-native run-android
`For iOS:
`bash
cd ios && pod install && cd ..
npx react-native run-ios
`---
2.Requirements
### 2.1 New Architecture required
New architecture required. React native >= 0.76.5 Works with Expo Bare Workflow & Vanilla React Native
### 2.2 iOS: Cryptokit from swift is being used for encryption. Minimin support iOS version is 13.0---
⚙️ 3. Setup in React Native
No additional configuration is required. The methods can be directly imported and used.
---
📦 4. Direct Method Import
You can directly import the methods you need:
`tsx
import {
encryptAES,
decryptAES,
encryptRSA,
decryptRSA,
hashSHA256,
hashSHA512,
hmacSHA256,
base64Encode,
base64Decode,
generateRandomString,
generateAESKey,
generateRSAKeyPair,
generateECDSAKeyPair,
signDataECDSA,
verifySignatureECDSA,
encryptAsyncAES,
decryptAsyncAES,
encryptAsyncRSA,
decryptAsyncRSA,
encryptFile,
decryptFile,
} from 'rn-encryption';;
`- Each method can be accessed directly without a default object wrapper.
- Please note that encryptFile/decryptFile methods are not available for web yet.
- All web methods have promises while few native methods can be called without promises.
---
📚 5. API Overview
$3
- generateAESKey(keySize: number): string
- encryptAES(data: string, key: string): string
- decryptAES(data: string, key: string): string$3
- generateRSAKeyPair(): keypair
- encryptRSA(data: string, publicKey: string): string
- decryptRSA(data: string, privateKey: string): string$3
- hashSHA256(input: string): string
- hashSHA512(input: string): string$3
- hmacSHA256(data: string, key: string): string$3
- generateRandomString(input: number): string$3
- base64Encode(input: string): string
- base64Decode(input: string): string$3
- generateECDSAKeyPair(): keypair
- signDataECDSA(data: string, key: string): string
- verifySignatureECDSA(data: string,signatureBase64: string, key: string): boolean$3
- encryptAsyncAES(data: string, key: string): Promise
- decryptAsyncAES(data: string, key: string): Promise
- encryptAsyncRSA(data: string, key: string): Promise
- decryptAsyncRSA(data: string, key: string): Promise
- encryptFile(inputPath: string,outputPath: string, key: string): Promise
- decryptFile(inputPath: string, key: string): Promise
---🛠️ 6.Native Usage Examples
`tsx
import { useState } from 'react';
import { View, StyleSheet, Text, Button } from 'react-native';
import {
encryptAES,
decryptAES,
encryptRSA,
decryptRSA,
hashSHA256,
hashSHA512,
hmacSHA256,
base64Encode,
base64Decode,
generateRandomString,
generateAESKey,
generateRSAKeyPair,
generateECDSAKeyPair,
signDataECDSA,
verifySignatureECDSA,
encryptAsyncAES,
decryptAsyncAES,
encryptAsyncRSA,
decryptAsyncRSA,
encryptFile,
decryptFile
} from 'rn-encryption';
import RNFS from 'react-native-fs';interface EncryptionError {
name: string;
message: string;
}
export default function DashboardScreen() {
const [result, setResult] = useState(''); // Encryption/Decryption result
const inputPath =
${RNFS.DocumentDirectoryPath}/data.txt;
const outputPath = ${RNFS.DocumentDirectoryPath}/data.enc;
const decryptedPath = ${RNFS.DocumentDirectoryPath}/data-decrypted.txt; function handleRSAEncryption() {
const plaintext = 'Hello, RSA Encryption!';
const generatedKeys = generateRSAKeyPair();
try {
// Step 1: Encrypt the plaintext using the Public Key
const encryptedData = encryptRSA(plaintext, generatedKeys.publicKey);
// Step 2: Decrypt the encrypted data using the Private Key
const decryptedData = decryptRSA(encryptedData, generatedKeys.privateKey);
// Step 3: Validation
if (decryptedData === plaintext) {
console.log('✅ RSA Encryption and Decryption Successful!');
} else {
console.error('❌ Decrypted data does not match original plaintext!');
}
} catch (error) {
console.error('⚠️ RSA Error:', error);
}
}
async function handleAsyncRSAEncryption() {
const plaintext = 'Hello, RSA Encryption!';
const generatedKeys = generateRSAKeyPair();
try {
// Step 1: Encrypt the plaintext using the Public Key
const encryptedData = await encryptAsyncRSA(
plaintext,
generatedKeys.publicKey
);
// Step 2: Decrypt the encrypted data using the Private Key
const decryptedData = await decryptAsyncRSA(
encryptedData,
generatedKeys.privateKey
);
// Step 3: Validation
if (decryptedData === plaintext) {
console.log('✅ RSA Encryption and Decryption Successful!');
} else {
console.error('❌ Decrypted data does not match original plaintext!');
}
} catch (error) {
console.error('⚠️ RSA Error:', error);
}
}
const handleAESEncryption = () => {
const sampleObject = {
name: 'John Doe',
age: 30,
roles: ['admin', 'editor'],
};
try {
const generatedKey = generateAESKey(256);
const jsonString = JSON.stringify(sampleObject);
const encryptedString = encryptAES(jsonString, generatedKey);
// Decrypt and parse JSON
const decryptedJsonString = decryptAES(encryptedString, generatedKey);
const decryptedObject = JSON.parse(decryptedJsonString);
console.log('Decrypted Object:', decryptedObject);
} catch (err: unknown) {
if (err instanceof Error) {
let error = err.cause as EncryptionError;
console.log('❌ Error:123', error.message);
} else {
console.log('❌ Unknown Error:', err);
}
setResult('An error occurred during encryption/decryption.');
}
};
const handleAsyncESEncryption = async () => {
const sampleObject = {
name: 'John Doe',
age: 30,
roles: ['admin', 'editor'],
};
try {
const generatedKey = generateAESKey(256);
const jsonString = JSON.stringify(sampleObject);
const encryptedString = await encryptAsyncAES(jsonString, generatedKey);
console.log('encrypted Object:', encryptedString);
// Decrypt and parse JSON
const decryptedJsonString = await decryptAsyncAES(
encryptedString,
generatedKey
);
const decryptedObject = JSON.parse(decryptedJsonString);
console.log('Decrypted Object:', decryptedObject);
} catch (err: unknown) {
if (err instanceof Error) {
let error = err.cause as EncryptionError;
console.log('❌ Error:123', error.message);
} else {
console.log('❌ Unknown Error:', err);
}
setResult('An error occurred during encryption/decryption.');
}
};
const hashing = () => {
try {
console.log('--- Hashing ---');
const sha256Hash = hashSHA256('Hello Hashing');
console.log('SHA-256 Hash:', sha256Hash);
const sha512Hash = hashSHA512('Hello Hashing');
console.log('SHA-512 Hash:', sha512Hash);
} catch (err) {
console.log('error is', err);
}
};
const hmac = () => {
try {
console.log('--- HMAC ---');
const hmackey = generateHMACKey(256);
const hmachash = hmacSHA256('Hello HMAC', hmackey);
const hmackey512 = generateHMACKey(512);
const hmachash512 = hmacSHA256('Hello HMAC', hmackey512);
console.log('HMAC-SHA256:', hmachash, hmachash512);
} catch (err) {
console.log('error is', err);
}
};
const signData = () => {
const keyPair = generateECDSAKeyPair();
const data = 'Hello, ECDSA!';
const signature = signDataECDSA(data, keyPair.privateKey);
const isValid = verifySignatureECDSA(data, signature, keyPair.publicKey);
console.log('Signature:', signature);
console.log('Is Valid Signature:', isValid);
};
const base64 = () => {
try {
console.log('--- Base64 Encoding/Decoding ---');
const base64Encoded = base64Encode('Hello Base64 Encoding');
console.log('Base64 Encoded:', base64Encoded);
const base64Decoded = base64Decode(base64Encoded);
console.log('Base64 Decoded:', base64Decoded);
} catch (err) {
console.log('error is', err);
}
};
const createRandomString = () => {
try {
console.log('--- Utilities ---');
const randomString = generateRandomString(16);
console.log('Random String:', randomString);
} catch (err) {
console.log('error is', err);
}
};
async function handleEncryptFileAES() {
try {
// Step 1: Write Sample Data to a File
await RNFS.writeFile(inputPath, 'This is a sensitive file content.', 'utf8');
console.log(
File written at: ${inputPath}); const generatedKey = generateAESKey(256);
console.log('generatedKey ', generatedKey);
// Step 2: Encrypt the File
const encryptedFilePath = await encryptFile(inputPath, outputPath, generatedKey);
console.log('Encrypted File Path:', encryptedFilePath);
// Step 3: Verify Encrypted File
const encryptedFileExists = await RNFS.exists(outputPath);
console.log('Encrypted File Exists:', encryptedFileExists);
const decryptedContent = await decryptFile(outputPath, generatedKey);
console.log('Decrypted File Content:', decryptedContent);
// Step 5: Write Decrypted Content to a New File
await RNFS.writeFile(decryptedPath, decryptedContent, 'utf8');
console.log(
Decrypted file saved at: ${decryptedPath});
} catch (error) {
console.error('Encryption Error:', error);
}
}
return (
title="Async Encrypt & Decrypt AES"
onPress={handleAsyncESEncryption}
/>
title="Encrypt & Decrypt File"
onPress={handleEncryptFileAES}
/>
title="Encrypt & Decrypt RSA"
onPress={handleAsyncRSAEncryption}
/>
{result}
);
}
const styles = StyleSheet.create({
inputContainer: {
marginVertical: 20,
alignItems: 'center',
width: '80%',
},
textInput: {
borderWidth: 1,
borderColor: '#ccc',
borderRadius: 5,
padding: 10,
width: '100%',
marginTop: 10,
},
resultText: {
marginVertical: 20,
textAlign: 'center',
fontSize: 16,
},
counterWrapper: {
height: 150,
justifyContent: 'center',
alignItems: 'center',
},
counterView: {
width: 280,
height: 140,
},
text: {
marginBottom: 20,
fontSize: 16,
},
});
`🛠️ 7.Web Usage Examples
`tsx
import { View, Text, StyleSheet, Button } from 'react-native';
import { generateAESKey, encryptAES, decryptAES, generateRSAKeyPair, encryptRSA, decryptRSA, generateECDSAKeyPair, signDataECDSA, verifySignatureECDSA, generateHMACKey, hmacSHA256, hmacSHA512, hashSHA256, hashSHA512, generateRandomString, base64Decode, base64Encode } from 'rn-encryption';export default function HomeScreen() {
const handleAESEncryption = async () => {
const sampleObject = {
name: 'John Doe',
age: 30,
roles: ['admin', 'editor'],
};
try {
const generatedKey = await generateAESKey();
const jsonString = JSON.stringify(sampleObject);
const encryptedString = await encryptAES(jsonString, generatedKey);
// Decrypt and parse JSON
const decryptedJsonString = await decryptAES(encryptedString, generatedKey);
const decryptedObject = JSON.parse(decryptedJsonString);
console.log('Decrypted Object:', generatedKey, );
} catch (err: unknown) {
console.log('❌ Error:123', err);
}
};
async function handleAsyncRSAEncryption() {
const plaintext = 'Hello, RSA Encryption!';
const generatedKeys = await generateRSAKeyPair();
try {
// Step 1: Encrypt the plaintext using the Public Key
const encryptedData = await encryptRSA(
plaintext,
generatedKeys.publicKey
);
// Step 2: Decrypt the encrypted data using the Private Key
const decryptedData = await decryptRSA(
encryptedData,
generatedKeys.privateKey
);
// Step 3: Validation
if (decryptedData === plaintext) {
console.log('✅ RSA Encryption and Decryption Successful!');
} else {
console.error('❌ Decrypted data does not match original plaintext!');
}
} catch (error) {
console.error('⚠️ RSA Error:', error);
}
}
const hashing = async () => {
try {
console.log('--- Hashing ---');
const sha256Hash = await hashSHA256('Hello Hashing');
console.log('SHA-256 Hash:', sha256Hash);
const sha512Hash = await hashSHA512('Hello Hashing');
console.log('SHA-512 Hash:', sha512Hash);
} catch (err) {
console.log('error is', err);
}
};
const hmac = async() => {
try {
const macKey = await generateHMACKey(256)
console.log('--- HMAC ---',macKey);
const hmachash = await hmacSHA256('Hello HMAC', macKey);
console.log('HMAC-SHA256:', hmachash);
} catch (err) {
console.log('error is', err);
}
};
const base64 = async () => {
try {
console.log('--- Base64 Encoding/Decoding ---');
const base64Encoded = await base64Encode('Hello Base64 Encoding');
console.log('Base64 Encoded:', base64Encoded);
const base64Decoded =await base64Decode(base64Encoded);
console.log('Base64 Decoded:', base64Decoded);
} catch (err) {
console.log('error is', err);
}
};
const createRandomString = async () => {
try {
console.log('--- Utilities ---');
const randomString = await generateRandomString(16);
console.log('Random String:', randomString);
} catch (err) {
console.log('error is', err);
}
};
const signData = async () => {
const keyPair = await generateECDSAKeyPair();
const data = 'Hello, ECDSA!';
const signature = await signDataECDSA(data, keyPair.privateKey);
const isValid = await verifySignatureECDSA(data, signature, keyPair.publicKey);
console.log('Signature:', signature);
console.log('Is Valid Signature:', isValid);
};
return (
Dynamic Routing Example
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 16,
justifyContent: 'center',
backgroundColor: '#f4f4f4',
},
header: {
fontSize: 20,
fontWeight: 'bold',
marginBottom: 16,
textAlign: 'center',
},
item: {
padding: 16,
marginVertical: 8,
backgroundColor: '#fff',
borderRadius: 8,
shadowColor: '#000',
shadowOpacity: 0.1,
shadowRadius: 4,
elevation: 2,
},
text: {
fontSize: 16,
},
});
`Keychain Integration for keys
- Key Storage: It is recommended to save encryption keys in Keychain (iOS) and Keystore (Android) for enhanced security.
- Example Implementation: You can refer to an example in this repository for guidance.
- Customization: The provided example serves as a sample implementation and can be modified according to specific requirements.---
🐞 8. Troubleshooting
1. Library Not Found:
- Run
npx react-native link rn-encryption.
- Clean and rebuild the project.2. AES Key Size Error:
- Ensure the AES key is 16, 24, or 32 characters.
3. RSA Key Parsing Issue:
- Verify the RSA key is in Base64-encoded PEM format.
4. Permission Issues:
- Ensure native permissions are set correctly in AndroidManifest.xml or iOS Podfile.
---
✅ 9. Best Practices
1. Do Not Hardcode Keys: Use
.env or secure storage for keys.
2. Handle Errors Gracefully: Wrap calls in try-catch blocks.
3. Validate Key Sizes: Ensure AES and RSA keys meet size requirements.---
❓ 10. FAQ
Q: Does the library support both Android and iOS?
A: Partially,
rn-encryption` fully supports ios and encryptAES & decryptAES for Android platforms.Q: Can I use the library in Expo?
A: Yes, if you're using Expo Bare Workflow.
Q: How do I debug encryption issues?
A: Add console logs and verify that keys and data are correctly passed.
---
1. Use Strong Keys: Always use AES-256 for symmetric encryption and RSA-2048 for asymmetric encryption.
2. Key Storage: Store keys securely using Android Keystore and iOS Keychain.
3. Avoid Hardcoding Keys: Do not hardcode encryption keys directly in the app.
| Feature | Android (JCA) | iOS (CryptoKit) |
|--------------------------------|-------------------------------------|----------------------------------|
| Symmetric Encryption | ✅ AES-256-GCM | ✅ AES-256-GCM |
| Asymmetric Encryption | ✅ RSA-2048 | ✅ RSA-2048 |
| Key Derivation | ✅ PBKDF2 | ✅ PBKDF2 / ✅ HKDF |
| Hashing | ✅ SHA-256, ✅ SHA-512 | ✅ SHA-256, ✅ SHA-512 |
| Message Authentication | ✅ HMAC-SHA256 | ✅ HMAC-SHA256 |
| Digital Signatures | ✅ ECDSA | ✅ ECDSA (via CryptoKit) |
| Key Management | ✅ Android Keystore | ✅ iOS Keychain |
| Initialization Vector (IV) | ✅ SecureRandom (12/16 Bytes) | ✅ Randomized IV (12 Bytes) |
| Authentication Tag | ✅ Built-in (GCM Mode) | ✅ Built-in (GCM Mode) |
| Error Handling | ✅ Strong Validation | ✅ Strong Validation |
| Performance | ⚡ Optimized for Android | ⚡ Optimized for iOS |
| Parallel Processing | ✅ Supported in GCM | ✅ Supported in GCM |
| Cryptographic Library | ✅ Java Cryptography (JCA) | ✅ CryptoKit |