How we implemented client-side encrypted streaming in Flutter with Dart Isolates
Over the past few months, we built and launched RonikCloud ( https://ronikcloud.com/ ), a client-side encrypted cloud storage app built in Flutter across Web, Desktop (macOS, Windows, Linux), and Mobile (iOS, Android). In this article, we share our architectural choices, lessons learned, and how we solved client-side encrypted streaming performance in Flutter. The Problem: Cryptography vs 60/120…
Over the past few months, we developed and released RonikCloud, a cloud storage app with client-side encryption using Flutter across various platforms. In this article, we discuss our design decisions, lessons learned, and how we tackled client-side encrypted streaming performance in Flutter. The Challenge: Balancing Crypto and UI Performance Client-side encryption involves running intensive authenticated encryption operations (AES-GCM-256, XChaCha20-Poly1305) on multi-gigabyte files.
Executing this on the Dart main UI thread results in UI stuttering, frame drops, and frozen progress bars. Core Architecture Elements 1. Moving Crypto to Background Isolates By utilizing Dart's cryptography package, we stream data chunks through dedicated background worker isolates. Files are processed in memory-efficient chunks (5MB-16MB).
An isolate handles each chunk's encryption with authenticated tags, then streams the encrypted data directly into S3 pre-signed upload channels. This approach maintains 60fps/120fps UI performance even during large file transfers. 2. Envelope and Path Encryption (Zero Knowledge Filenames) File Payload: Encrypted locally before upload.
File & Folder Names: Encrypted client-side. The backend only stores random identifiers, discarding any plaintext filenames or folder structures. Separate Encryption Envelopes: New file data and protected filenames utilize different authenticated encryption envelopes. 3. Secure Web Fragments For web-based file sharing and encrypted requests, cryptographic keys are embedded solely in the URL hash fragment (#key=...).
Since browsers never transmit the hash to servers or proxies, our backend API never receives the shared key. The client extracts the fragment directly in browser memory and decrypts the streaming bytes locally. 4. Cross-Platform Sync Engine Both desktop (macOS, Windows, Linux) and mobile (iOS, Android) platforms use local filesystem event watchers with automatic conflict resolution.
Mobile platforms adapt to OS background execution limits with resumable upload chunking. Metadata Transparency We are transparent about what our app encrypts and shares: Client-Side Encrypted - File payloads, file/folder names, request secrets. Backend Access - Account relationships, subscription tiers, ciphertext object sizes, upload/modification timestamps, and network traffic.
Audit Status: RonikCloud currently operates in an open beta and has not yet passed an independent third-party audit. Community Questions: What criteria do you use to evaluate new client-side encrypted storage solutions? What are your preferred methods for handling memory-efficient streaming pipelines in Flutter/Dart? We welcome your feedback and insights!
Written by urgent.news from Dev.to's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.