Skip to main content
RapidDev - Software Development Agency
flutterflow-tutorials

How to Create a File Encryption System Before Storage in FlutterFlow

Encrypt files on the device before uploading to Firebase Storage using a Custom Action with the encrypt Dart package. Derive a strong AES-256 key from the user's passphrase via PBKDF2 with a unique salt stored in the Firestore file document. On download, retrieve the encrypted bytes, decrypt with the same passphrase, and display or save the file locally.

What you'll learn

  • How to derive a strong AES-256 encryption key from a user passphrase using PBKDF2
  • How to encrypt file bytes with AES-256-CBC before uploading to Firebase Storage
  • How to store encryption metadata (salt, IV) in Firestore alongside the file reference
  • How to decrypt downloaded files using the same passphrase and stored metadata
  • How to build a file manager UI that shows encrypted files with lock status indicators
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Beginner7 min read30-40 minFlutterFlow Free+ (Firebase Storage requires Blaze plan for large files)March 2026RapidDev Engineering Team
TL;DR

Encrypt files on the device before uploading to Firebase Storage using a Custom Action with the encrypt Dart package. Derive a strong AES-256 key from the user's passphrase via PBKDF2 with a unique salt stored in the Firestore file document. On download, retrieve the encrypted bytes, decrypt with the same passphrase, and display or save the file locally.

Client-Side File Encryption with AES-256 in FlutterFlow

Standard Firebase Storage protects files with access rules, but anyone with storage access can read file contents. Client-side encryption adds a second layer: files are encrypted on the device before upload, so even a storage breach exposes only unreadable ciphertext. This tutorial uses AES-256 encryption with PBKDF2 key derivation for strong, password-based protection.

Prerequisites

  • A FlutterFlow project with Firestore and Firebase Storage configured
  • Firebase Authentication set up with user accounts
  • Basic understanding of file upload and download in FlutterFlow
  • The encrypt Dart package added as a Custom Action dependency

Step-by-step guide

1

Set up the Firestore document model for encrypted file metadata

Create an encrypted_files collection with fields: userId (Reference), fileName (String, original file name), storagePath (String, Firebase Storage path), salt (String, base64-encoded random salt used for key derivation), iv (String, base64-encoded initialization vector used for AES encryption), fileSize (Int, original file size in bytes), mimeType (String), uploadedAt (Timestamp), isEncrypted (Boolean, always true for this collection). The salt and IV are not secret — they are safe to store alongside the file reference. The security comes from the passphrase that only the user knows.

Expected result: Firestore has an encrypted_files collection storing metadata needed to decrypt each file, but not the encryption key itself.

2

Build the Custom Action for PBKDF2 key derivation and AES-256 encryption

Create a Custom Action named encryptAndUploadFile with parameters: fileBytes (FFUploadedFile), passphrase (String), fileName (String). Add the encrypt and crypto packages as dependencies. In the action: generate a random 16-byte salt and a random 16-byte IV using SecureRandom. Derive the 256-bit AES key using PBKDF2 with HMAC-SHA256, 100000 iterations, the salt, and the passphrase. Create an AES Encrypter in CBC mode with the derived key. Encrypt the file bytes with the IV. Upload the encrypted bytes to Firebase Storage at encrypted/{userId}/{timestamp}_{fileName}. Create the Firestore encrypted_files doc with the salt, IV (both base64-encoded), storage path, and file metadata. Return success.

Expected result: Files are encrypted client-side with AES-256 and uploaded as ciphertext. The salt and IV are stored in Firestore for later decryption.

3

Build the Custom Action for file decryption on download

Create a Custom Action named decryptAndDownloadFile with parameters: encryptedFileDoc (Document Reference), passphrase (String). The action reads the Firestore doc to get the salt, IV, and storagePath. Downloads the encrypted bytes from Firebase Storage. Decodes the base64 salt and IV. Derives the same AES-256 key using PBKDF2 with the same salt and passphrase. Decrypts the ciphertext with AES-CBC using the key and IV. If decryption fails (wrong passphrase), the decrypt call throws — catch this and return an error message. On success, return the decrypted bytes for display or local file save.

Expected result: Entering the correct passphrase decrypts the file successfully. A wrong passphrase produces a clear error message without crashing.

4

Build the encrypted file manager UI with upload and password entry

Create a MyEncryptedFilesPage. Add an Upload FAB that opens a BottomSheet with a file picker (FlutterFlowUploadButton) and a TextField for the encryption passphrase (obscured). On Submit, call the encryptAndUploadFile Custom Action with the selected file and passphrase. Show a CircularProgressIndicator during upload. Below the FAB, display a ListView querying encrypted_files where userId equals the current user, ordered by uploadedAt desc. Each list item shows a Container card with a lock Icon, file name Text, file size Text, and upload date Text. Tapping a file opens a Dialog with a password TextField. On Submit, call decryptAndDownloadFile. Show the decrypted file or a download option on success.

Expected result: Users can upload files with a passphrase, see their encrypted files listed with lock icons, and decrypt any file by entering the correct passphrase.

5

Add passphrase strength validation and secure sharing support

Before encryption, validate the passphrase: minimum 8 characters, at least one uppercase letter, one number. Show a strength indicator (weak/medium/strong) below the passphrase field using Conditional Styling on a Container. For file sharing between users, implement a Cloud Function shareEncryptedFile(fileDocId, recipientUserId) that duplicates the encrypted_files metadata doc for the recipient. The recipient still needs the passphrase from the sender (shared out of band). Display shared files with a different icon (share icon instead of lock icon) and the sharer's name.

Expected result: Users receive feedback on passphrase strength before encrypting, and can share encrypted file access with other users who know the passphrase.

Complete working example

FlutterFlow File Encryption System Setup
1FIRESTORE DATA MODEL:
2 encrypted_files/{docId}
3 userId: Reference (users)
4 fileName: String (e.g., 'contract.pdf')
5 storagePath: String (e.g., 'encrypted/uid123/1711700000_contract.pdf')
6 salt: String (base64, 16 bytes)
7 iv: String (base64, 16 bytes)
8 fileSize: Int (original bytes)
9 mimeType: String (e.g., 'application/pdf')
10 uploadedAt: Timestamp
11 isEncrypted: Boolean (true)
12 sharedBy: Reference (users, nullable)
13
14CUSTOM ACTION: encryptAndUploadFile
15 Input: fileBytes, passphrase, fileName
16 Process:
17 1. salt = SecureRandom(16 bytes)
18 2. iv = SecureRandom(16 bytes)
19 3. key = PBKDF2(passphrase, salt, iterations:100000, bits:256)
20 4. encrypter = AES(key, mode: CBC)
21 5. encrypted = encrypter.encrypt(fileBytes, iv: iv)
22 6. Upload encrypted.bytes to Storage
23 7. Create Firestore doc with salt, iv (base64), storagePath
24 Returns: success or error
25
26CUSTOM ACTION: decryptAndDownloadFile
27 Input: fileDocRef, passphrase
28 Process:
29 1. Read doc salt, iv, storagePath
30 2. Download encrypted bytes from Storage
31 3. key = PBKDF2(passphrase, base64Decode(salt), 100000, 256)
32 4. decrypter = AES(key, mode: CBC)
33 5. decrypted = decrypter.decrypt(encrypted, iv: base64Decode(iv))
34 Returns: decrypted bytes or error
35
36PAGE: MyEncryptedFilesPage
37 Scaffold
38 AppBar (title: "Encrypted Files")
39 Backend Query: encrypted_files where userId == currentUser
40 ListView
41 Card (padding: 12)
42 Row
43 Icon (lock, blue)
44 Expanded Column
45 Text (fileName, bodyLarge)
46 Text (fileSize formatted + uploadedAt, bodySmall, grey)
47 IconButton (download)
48 On Tap Show Dialog with passphrase TextField
49 On Submit decryptAndDownloadFile
50 FAB (icon: add)
51 On Tap BottomSheet
52 Column
53 FlutterFlowUploadButton
54 TextField (passphrase, obscured)
55 Passphrase strength indicator
56 Button "Encrypt & Upload"
57 On Tap encryptAndUploadFile

Common mistakes when creating a File Encryption System Before Storage in FlutterFlow

Why it's a problem: Using the user's password directly as the AES encryption key

How to avoid: Use PBKDF2 with HMAC-SHA256 and 100,000 iterations to derive a strong 256-bit key from any passphrase. The salt prevents precomputed attacks.

Why it's a problem: Reusing the same initialization vector for every file encrypted with the same key

How to avoid: Generate a fresh random 16-byte IV for each file encryption. Store the IV in the Firestore document alongside the salt.

Why it's a problem: Storing the encryption key or passphrase in Firestore or Firebase Storage

How to avoid: Never store the key or passphrase. The user must enter it each time they want to decrypt. Store only the salt and IV, which are not secret.

Best practices

  • Generate a unique random salt and IV for every file encryption operation
  • Use at least 100,000 PBKDF2 iterations to make brute-force attacks computationally expensive
  • Validate passphrase strength before allowing encryption — minimum 8 characters with mixed case and numbers
  • Show a clear error message when decryption fails due to wrong passphrase rather than displaying corrupted data
  • Store file metadata (name, size, type) in Firestore so the file list loads without downloading encrypted content
  • Add a loading indicator during encryption and decryption since large files take noticeable processing time
  • Never log or print the passphrase or derived key in Custom Action debug output

Still stuck?

Copy one of these prompts to get a personalized, step-by-step explanation.

ChatGPT Prompt

I need to build file encryption in FlutterFlow that encrypts files on the device before uploading to Firebase Storage. Show me the PBKDF2 key derivation, AES-256-CBC encryption Custom Action, Firestore metadata model, and decryption flow.

FlutterFlow Prompt

Create a page called Encrypted Files with a list showing file name, file size, and a lock icon for each item. Add a floating action button that opens a bottom sheet with a file picker and a password field. Add a download button on each list item.

Frequently asked questions

Is client-side encryption in FlutterFlow truly secure?

Yes, when implemented correctly. AES-256 with PBKDF2 key derivation is industry-standard encryption. The security depends on passphrase strength — a strong passphrase makes brute-force attacks computationally infeasible.

What happens if the user forgets their encryption passphrase?

The file cannot be decrypted. There is no recovery mechanism by design — this is what makes encryption secure. Advise users to store passphrases in a password manager.

Can I encrypt files larger than 10MB in FlutterFlow?

AES encryption of large files can be slow on mobile devices. For files over 10MB, consider encrypting in a Cloud Function instead. The client uploads the raw file to a temporary secure location, the Cloud Function encrypts and moves it to permanent storage.

Does encrypting files affect Firebase Storage costs?

Encrypted files are roughly the same size as the originals (AES adds minimal padding). Storage costs remain essentially the same. The overhead is in processing time on the device, not storage space.

Can two users decrypt the same file with different passwords?

Not with this single-key approach. Both users need the same passphrase. For per-user access, implement RSA public-key encryption: encrypt the file key with each recipient's public key so each person decrypts with their own private key.

What if I need end-to-end encrypted file sharing across my app?

RapidDev has implemented end-to-end encryption systems in FlutterFlow apps with per-user key pairs, key exchange protocols, and encrypted file sharing for compliance-sensitive industries like healthcare and finance.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.