React Native Quick Crypto
Guides

Large File Encryption

Optimizing performance with chunked encryption and streams

Encrypting Large Files

When encrypting large files (like videos or high-res images), loading the entire file into memory as a single Buffer or string will likely crash your app (OOM - Out Of Memory error).

To handle this, we process the file in chunks using Cipher's streaming interface (.update()).

The Concept

Instead of converting File -> Buffer -> Encrypted, we do:

Implementation

This pattern works with any file system library (e.g., react-native-fs, expo-file-system, or react-native-blob-util). We'll use pseudocode for file IO.

Initialize Streaming Cipher

Create the cipher instance. It maintains internal state between updates, so reuse it for the whole stream.

import QuickCrypto from 'react-native-quick-crypto';

const key = QuickCrypto.randomBytes(32);
const iv = QuickCrypto.randomBytes(16); // AES-CBC needs 16 bytes

const cipher = QuickCrypto.createCipheriv('aes-256-cbc', key, iv);

The Processing Loop

Read the file in manageable chunks (e.g., 1MB to 5MB).

const CHUNK_SIZE = 1024 * 1024; // 1MB chunks
let offset = 0;
const fileSize = await FileSystem.getSize(path);

// Open output stream/file
await FileSystem.write(outputPath, '', 'utf8'); // Clear file

while (offset < fileSize) {
  // Read Chunk
  const chunkBase64 = await FileSystem.read(path, { 
    position: offset, 
    length: CHUNK_SIZE, 
    encoding: 'base64' 
  });
  
  // Encrypt Chunk
  const encryptedHex = cipher.update(chunkBase64, 'base64', 'hex');
  
  // Write/Append Chunk
  await FileSystem.append(outputPath, encryptedHex, 'hex');
  
  offset += CHUNK_SIZE;
}

Finalize

After the loop, call .final() to process any remaining internal buffer and padding. This step is critical!

// Finalize
const finalHex = cipher.final('hex');

if (finalHex.length > 0) {
  await FileSystem.append(outputPath, finalHex, 'hex');
}

console.log('Encryption Complete! 🔒');

Memory Usage Comparison

Method500MB VideoRAM UsageOutcome
All-At-Oncecipher.update(fullFile)> 1.2 GBCRASH 💥
Chunkedcipher.update(1MB)~5 MBSUCCESS

Production Readiness

Handling critical user data requires robustness:

  • Integrity Checks: Always calculate a Hash (SHA-256) of the file while encrypting to verify decryption later.
  • Resume Capability: If the app crashes at 90%, you need logic to effectively resume or clean up partially written files.
  • Error Handling: File I/O can fail (disk full, permissions). Wrap operations in try/catch blocks.

On this page