rn-encryption
Version:
668 lines (558 loc) • 21.2 kB
Markdown
# 📚 **React Native Integration Guide for `rn-encryption` Library**
This 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.**
---
## 📑 **Table of Contents**
1. [Library Installation](#1-library-installation)
2. [Requirements](#2-new_arch_needed)
3. [Setup in React Native](#3-setup-in-react-native)
4. [Direct Method Import](#4-direct-method-import)
5. [API Overview](#5-api-overview)
6. [Usage Examples](#6-usage-examples)
7. [Troubleshooting](#7-troubleshooting)
8. [Best Practices](#8-best-practices)
9. [FAQ](#9-faq)
10. [Security Best Practices](#security-best-practices)
---
## 🚀 **1. Library Installation**
### 1.1 **Add Dependency**
Install the library using npm or yarn:
```bash
expo install @yourorg/native-encryption
# OR
npm install rn-encryption --save
# OR
yarn add rn-encryption
```
### 1.2 **Rebuild the Project**
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**
### 🔒 **AES Encryption/Decryption**
- **`generateAESKey(keySize: number): string`**
- **`encryptAES(data: string, key: string): string`**
- **`decryptAES(data: string, key: string): string`**
### 🔑 **RSA Encryption/Decryption**
- **`generateRSAKeyPair(): keypair`**
- **`encryptRSA(data: string, publicKey: string): string`**
- **`decryptRSA(data: string, privateKey: string): string`**
### 🛡️ **SHA Hashing**
- **`hashSHA256(input: string): string`**
- **`hashSHA512(input: string): string`**
### 📝 **HMAC-SHA256**
- **`hmacSHA256(data: string, key: string): string`**
### 🎲 **Random String Generation**
- **`generateRandomString(input: number): string`**
### 📝 **Base64 Encoding/Decoding**
- **`base64Encode(input: string): string`**
- **`base64Decode(input: string): string`**
### 🔒 **ECDA Encryption/Decryption**
- **`generateECDSAKeyPair(): keypair`**
- **`signDataECDSA(data: string, key: string): string`**
- **`verifySignatureECDSA(data: string,signatureBase64: string, key: string): boolean`**
### 🔒 **Asynchronous Methods**
- **`encryptAsyncAES(data: string, key: string): Promise<string>`**
- **`decryptAsyncAES(data: string, key: string): Promise<string>`**
- **`encryptAsyncRSA(data: string, key: string): Promise<string>`**
- **`decryptAsyncRSA(data: string, key: string): Promise<string>`**
- **`encryptFile(inputPath: string,outputPath: string, key: string): Promise<string>`**
- **`decryptFile(inputPath: string, key: string): Promise<string>`**
---
## 🛠️ **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 (
<View style={{ flex: 1, alignItems: 'center', paddingTop: 80 }}>
<Button title="Encrypt & Decrypt AES" onPress={handleAESEncryption} />
<Button
title="Async Encrypt & Decrypt AES"
onPress={handleAsyncESEncryption}
/>
<Button
title="Encrypt & Decrypt File"
onPress={handleEncryptFileAES}
/>
<Button title="Encrypt & Decrypt RSA" onPress={handleRSAEncryption} />
<Button
title="Encrypt & Decrypt RSA"
onPress={handleAsyncRSAEncryption}
/>
<Button title="Hashing" onPress={hashing} />
<Button title="HMAC" onPress={hmac} />
<Button title="Base64 Encoding" onPress={base64} />
<Button title="Generate random" onPress={createRandomString} />
<Button title="Sign & Validate data" onPress={signData} />
<Text style={styles.resultText}>{result}</Text>
</View>
);
}
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 (
<View style={styles.container}>
<Text style={styles.header}>Dynamic Routing Example</Text>
<Button title="Encrypt & Decrypt AES" onPress={handleAESEncryption} />
<Button title="Encrypt & Decrypt RSA" onPress={handleAsyncRSAEncryption} />
<Button title="Sign data" onPress={signData} />
<Button title="Hashing" onPress={hashing} />
<Button title="HMAC" onPress={hmac} />
<Button title="Base64 Encoding" onPress={base64} />
<Button title="Generate random" onPress={createRandomString} />
</View>
);
}
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.
---
## **11. Security Best Practices**
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.
### 📚 **Encryption Mechanisms: Android (JCA) vs iOS (CryptoKit)**
| **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 |