Enterprise-Grade Secure Messaging Platform
Privacy-first, end-to-end encrypted messaging designed for the modern world
π Quick Start β’ π Documentation β’ π§ Development β’ π£οΈ Roadmap β’ π€ Contributing
|
|
|
|
Enigmo follows a zero-trust architecture where the server never has access to plaintext messages
π enigmo/
βββ π± enigmo_app/ # Flutter Mobile & Web Client
β βββ lib/models/ # Data models and entities
β βββ lib/services/ # Business logic & crypto engine
β βββ lib/screens/ # UI screens and widgets
β βββ test/ # Comprehensive test suite
βββ π₯οΈ enigmo_server/ # Lightweight Dart Server
βββ bin/ # Server entrypoint
βββ lib/services/ # User management & routing
βββ test/ # Server-side tests
| π± Client (Flutter App) | π₯οΈ Server (Dart Backend) |
|---|---|
|
|
- π― Bootstrap: Clients publish Ed25519/X25519 public keys
- π€ Key Exchange: X25519 ECDH derives shared session secrets
- π Message Encryption: AEAD with nonce + MAC authentication
- β Digital Signing: Ed25519 signature for message integrity
- π‘ Zero-Knowledge Routing: Server forwards without decryption
|
π± ENIGMO FLUTTER APP |
π COMMUNICATION |
π₯οΈ ENIGMO DART SERVER |
Key Responsibilities:
|
π WebSocket β¬οΈ π REST API β¬οΈ π Zero-Knowledge |
Key Responsibilities:
|
The client application manages its connection to the WebSocket server through a simple state machine to ensure robust real-time communication.
stateDiagram-v2
[*] --> Disconnected
Disconnected --> Connecting: user.login()
Connecting --> Connected: WebSocket.onOpen
Connecting --> Disconnected: WebSocket.onError
Connected --> Authenticating: sendAuth(credentials)
Authenticating --> Online: server.authSuccess
Authenticating --> Connected: server.authFailure
Online --> Disconnected: user.logout() / connectionLost
Connected --> Disconnected: connectionLost
Built with defense-in-depth principles and modern cryptographic standards
| Security Layer | Implementation | Status |
|---|---|---|
| π Identity | Ed25519 keypairs with optional key pinning | β Implemented |
| π€ Key Agreement | X25519 ECDH for perfect forward secrecy | β Implemented |
| π Encryption | ChaCha20-Poly1305 AEAD (nonce + MAC) | β Implemented |
| βοΈ Authentication | Ed25519 digital signatures | β Implemented |
| π Replay Protection | Cryptographic nonces + monotonic counters | β Implemented |
| πββοΈ Forward Secrecy | Double-ratchet key rotation | π§ Roadmap |
| π Post-Quantum | Kyber/Dilithium hybrid | π§ Research |
- End-to-End Encryption: Only sender and recipient can read messages
- Perfect Forward Secrecy: Past messages remain secure if keys are compromised
- Message Authenticity: Cryptographic proof of sender identity
- Replay Protection: Each message can only be delivered once
- Zero-Knowledge Server: Server cannot decrypt or read message content
- Deniable Authentication: Recipients can verify, but can't prove to third parties
Client model EncryptedMessage (see enigmo_app/lib/services/crypto_engine.dart):
class EncryptedMessage {
final String encryptedData; // base64(cipherText)
final String nonce; // base64(nonce)
final String mac; // base64(auth tag)
final String signature; // base64(Ed25519 over cipherText)
}Server routes (see enigmo_server/bin/anongram_server.dart):
GET /api/healthβ server statusGET /api/statsβ server, user, message countersGET /wsβ WebSocket for realβtime messaging
This diagram illustrates the end-to-end encrypted message exchange between two clients, Alice and Bob, mediated by the Enigmo server.
sequenceDiagram
participant Alice as Alice's Client
participant Server as Enigmo Server
participant Bob as Bob's Client
Alice->>+Server: Publish Public Keys (Ed25519, X25519)
Server-->>-Alice: OK
Bob->>+Server: Publish Public Keys (Ed25519, X25519)
Server-->>-Bob: OK
Alice->>Server: Fetch Bob's Public Keys
Server->>Alice: Bob's Keys
Note over Alice, Bob: Alice now has Bob's keys and can derive a shared secret.
Alice->>Alice: Derive Shared Secret (X25519)
Alice->>Alice: Encrypt & Sign Message
Alice->>+Server: Send E2EE Message for Bob
Server->>+Bob: Forward E2EE Message
Server-->>-Alice: Delivered (Ack)
Bob->>Bob: Verify Signature (Ed25519)
Bob->>Bob: Derive Shared Secret (X25519)
Bob->>Bob: Decrypt Message
Bob-->>-Server: OK (Ack)
Here is a more granular breakdown of the cryptographic operations.
1. Key Agreement (ECDH)
Executed once per peer session to establish a symmetric encryption key.
// Alice wants to talk to Bob
// 1. Alice fetches Bob's public X25519 key from the server.
// 2. Alice uses her private X25519 key and Bob's public key.
function derive_shared_key(my_private_key: X25519_Priv, their_public_key: X25519_Pub) -> [u8; 32] {
// Perform Elliptic Curve Diffie-Hellman
let shared_secret = X25519(my_private_key, their_public_key);
// Use a Key Derivation Function (e.g., HKDF-SHA256) for cryptographic hygiene
// The context string prevents key reuse across different domains (e.g., attachments vs. messages).
let context = "enigmo-e2ee-message-v1";
let session_key = HKDF_SHA256(shared_secret, salt=null, info=context);
return session_key;
}2. Sending a Message
Alice encrypts and signs a message for Bob.
// 1. Derive the key for this session
const sessionKey = derive_shared_key(alice.x25519_priv, bob.x25519_pub);
// 2. Prepare the message and associated data
const plaintext = "Hello, Bob!";
const associated_data = JSON.stringify({ sender: alice.id, timestamp: Date.now() });
// 3. Encrypt using an Authenticated Encryption with Associated Data (AEAD) cipher
const nonce = crypto.randomBytes(24); // Must be unique for each message with the same key
const { ciphertext, mac } = AEAD_Encrypt(sessionKey, nonce, plaintext, associated_data);
// 4. Sign the *ciphertext* with long-term identity key to prevent tampering
const signature = Ed25519_Sign(alice.ed25519_priv, ciphertext);
// 5. Construct the final payload for the server
const payload = {
recipient: bob.id,
message: {
encryptedData: Base64.encode(ciphertext),
nonce: Base64.encode(nonce),
mac: Base64.encode(mac),
signature: Base64.encode(signature)
}
};
// 6. Send to server, which routes based on 'recipient'
websocket.send(JSON.stringify(payload));3. Receiving a Message
Bob receives the payload from the server and decrypts it.
// 1. Parse the incoming payload
const payload = JSON.parse(event.data);
const message = payload.message;
const senderId = payload.sender; // Server injects this
// 2. Fetch sender's public keys from local cache or server
const alice = get_user_keys(senderId);
// 3. Verify the signature on the ciphertext first
const is_valid_signature = Ed25519_Verify(
alice.ed25519_pub,
Base64.decode(message.encryptedData),
Base64.decode(message.signature)
);
if (!is_valid_signature) { throw new Error("Invalid signature! Message tampered."); }
// 4. If signature is valid, derive the same session key
const sessionKey = derive_shared_key(bob.x25519_priv, alice.x25519_pub);
// 5. Decrypt the message
const associated_data = JSON.stringify({ sender: senderId, timestamp: payload.timestamp });
const plaintext = AEAD_Decrypt(
sessionKey,
Base64.decode(message.nonce),
Base64.decode(message.encryptedData),
Base64.decode(message.mac),
associated_data
);
if (plaintext === null) { throw new Error("Decryption failed! MAC mismatch."); }
// 6. Render the plaintext message
console.log("New message:", plaintext);4. Server-Side Routing (Simplified)
The server's role is to act as a secure routing fabric. It never decrypts message content.
// High-level server logic for the WebSocket handler
// In-memory map to track active user connections
// In a production system, this would be backed by Redis or a similar store.
var active_connections = make(map[UserID]WebSocketConnection)
func WebSocketHandler(ws: WebSocketConnection) {
// 1. Authenticate the connection
// The client sends a token or public key to identify itself.
user_id, err := Authenticate(ws)
if err != nil {
ws.Close("Authentication failed")
return
}
// 2. Register the user's connection
active_connections[user_id] = ws
log.Printf("User %s connected", user_id)
// 3. Enter the message routing loop
for {
message, err := ws.ReadMessage()
if err != nil {
// Connection closed or error
delete(active_connections, user_id)
log.Printf("User %s disconnected", user_id)
break
}
// 4. Parse the outer envelope to find the recipient
// The server only reads metadata, not the encrypted 'message' object.
envelope, err := ParseEnvelope(message)
if err != nil {
ws.SendMessage("{"error": "Invalid envelope"}")
continue
}
// 5. Look up the recipient's connection
recipient_ws, found := active_connections[envelope.RecipientID]
if !found {
// Handle offline recipient (e.g., store for later delivery - see roadmap)
ws.SendMessage("{"error": "Recipient offline"}")
continue
}
// 6. Forward the *original, encrypted* message payload
// The server injects the sender's ID for the recipient's convenience.
forward_payload = AddSenderID(message, user_id)
err = recipient_ws.SendMessage(forward_payload)
if err != nil {
log.Printf("Failed to forward message to %s", envelope.RecipientID)
}
}
}Get Enigmo running in under 5 minutes
- Flutter SDK (stable channel) - Install Guide
- Dart SDK (included with Flutter)
- Development Environment: VS Code, Android Studio, or Xcode
- Platform Tools: iOS/Android toolchains per Flutter docs
# Clone and setup everything
git clone https://github.com/rokoss21/enigmo.git
cd enigmo
# Install all dependencies
make setup # or run the commands below manuallyπ Manual Setup (click to expand)
# Server dependencies
cd enigmo_server
dart pub get
# App dependencies
cd ../enigmo_app
flutter pub get
flutter pub run build_runner build # Generate code if needed
cd enigmo_server
# Development mode with hot reload
dart run bin/anongram_server.dart \
--host localhost \
--port 8080 \
--debug
|
cd enigmo_app
# iOS Simulator
flutter run -d ios
# Android Emulator
flutter run -d android
# Web Browser
flutter run -d web# Hot reload code
r
# Hot restart app
R
# Open DevTools
flutter pub global run devtools |
# Run all tests
make test
# Or manually:
cd enigmo_server && dart test --coverage
cd ../enigmo_app && flutter test --coverage
# Code formatting
dart format .
flutter format .
# Static analysis
dart analyze
flutter analyze| Platform | Command | Output |
|---|---|---|
| π€ **Android** | flutter build appbundle --release |
build/app/outputs/bundle/release/ |
| π **iOS** | flutter build ios --release |
build/ios/iphoneos/ |
| π **Web** | flutter build web --release |
build/web/ |
| π₯οΈ **Server** | dart compile exe bin/anongram_server.dart |
bin/anongram_server.exe |
ποΈ Detailed File Structure (click to expand)
π enigmo/ # Root monorepo
βββ π README.md # This file
βββ π Makefile # Build automation
βββ π docker-compose.yml # Development environment
βββ π .github/ # CI/CD workflows
β βββ workflows/
β βββ ci.yml # Continuous Integration
β βββ security.yml # Security scanning
β
βββ π± enigmo_app/ # Flutter Mobile & Web Client
β βββ π pubspec.yaml # Dependencies and metadata
β βββ π lib/
β β βββ π main.dart # Application entry point
β β βββ π models/ # Data models
β β β βββ message.dart # Message data structure
β β β βββ user.dart # User identity model
β β β βββ chat.dart # Chat conversation model
β β βββ π services/ # Business logic layer
β β β βββ π crypto_engine.dart # E2EE cryptographic operations
β β β βββ π key_manager.dart # Key storage and management
β β β βββ π network_service.dart # WebSocket & REST client
β β β βββ πΎ storage_service.dart # Local data persistence
β β βββ π screens/ # User interface screens
β β β βββ chat_screen.dart # Individual chat interface
β β β βββ chat_list_screen.dart # Chat list overview
β β β βββ settings_screen.dart # App configuration
β β βββ π widgets/ # Reusable UI components
β βββ π test/ # Test suites
β β βββ unit/ # Unit tests
β β βββ widget/ # Widget tests
β β βββ integration/ # E2E integration tests
β βββ π android/ # Android platform code
β βββ π ios/ # iOS platform code
β βββ π web/ # Web platform code
β
βββ π₯οΈ enigmo_server/ # Lightweight Dart Server
βββ π pubspec.yaml # Server dependencies
βββ π bin/
β βββ π anongram_server.dart # Server entry point
βββ π lib/
β βββ π models/ # Server data models
β β βββ user.dart # Server-side user model
β β βββ message.dart # Message routing model
β βββ π services/ # Server business logic
β β βββ π₯ user_manager.dart # User directory management
β β βββ π¨ message_manager.dart # Message routing logic
β β βββ π websocket_handler.dart # Real-time communication
β β βββ π auth_service.dart # Authentication handling
β βββ π utils/ # Utility functions
β βββ π logger.dart # Structured logging
βββ π test/ # Server test suites
β βββ unit/ # Server unit tests
β βββ integration/ # Server integration tests
βββ π Dockerfile # Container deployment
| Component | File | Purpose |
|---|---|---|
| π Crypto Engine | enigmo_app/lib/services/crypto_engine.dart |
Ed25519/X25519 operations, AEAD encryption |
| π Network Service | enigmo_app/lib/services/network_service.dart |
WebSocket client, REST API calls |
| π Key Manager | enigmo_app/lib/services/key_manager.dart |
Secure key storage and retrieval |
| π₯οΈ Server Main | enigmo_server/bin/anongram_server.dart |
HTTP server and WebSocket handler |
| π₯ User Manager | enigmo_server/lib/services/user_manager.dart |
Public key directory and user sessions |
| π¨ Message Router | enigmo_server/lib/services/message_manager.dart |
Zero-knowledge message forwarding |
Building the future of secure communication
- Core E2EE Implementation - Ed25519/X25519 cryptography
- Flutter Mobile Apps - iOS and Android clients
- WebSocket Server - Real-time message routing
- Comprehensive Testing - Unit, widget, and integration tests
- π Key Pinning & TOFU - Trust-on-first-use security model
- π± UI/UX Polish - Accessibility and user experience improvements
- π Telemetry Framework - Opt-in analytics and crash reporting
- π€ Offline Message Queue - Store and forward when disconnected
- π Smart Retry Logic - Exponential backoff with jitter
- π Encrypted Attachments - Files, images, and media sharing
- π Progressive Web App - Full-featured web client
- π₯ Health Monitoring - Advanced server observability
- π Message Deletion - Secure message expiration
- πββοΈ Perfect Forward Secrecy - Double-ratchet key rotation
- π± Multi-Device Sync - Per-device key management
- π₯ Group Messaging - Encrypted group conversations
- βοΈ Encrypted Backups - Secure key recovery system
- π OpenTelemetry - Enterprise observability stack
- ποΈ Database Integration - PostgreSQL, Redis support
- π₯ Voice & Video Calls - WebRTC P2P communication
- π Call Signaling - Secure call setup over WebSocket
- π¬ Screen Sharing - Encrypted screen collaboration
- ποΈ Voice Messages - Encrypted audio messaging
- πΉ Video Messages - Short-form video sharing
- π Media Encryption - E2EE for all multimedia content
- π‘οΈ Post-Quantum Crypto - Kyber/Dilithium hybrid schemes
- π΅οΈ Metadata Protection - Traffic analysis resistance
- π Zero-Knowledge Proofs - Advanced privacy primitives
- π Decentralized Architecture - P2P mesh networking
- π Hardware Security - HSM and secure enclave integration
- π€ AI Safety Tools - Content moderation without plaintext access
Security and code quality are not afterthoughtsβthey're built into every line of code
- π Test Coverage: >90% code coverage across all modules
- π§ Static Analysis: Dart analyzer with strict lint rules
- π Code Formatting: Automated formatting with
dart format - π Documentation: Comprehensive inline code documentation
- π Security Scanning: Automated vulnerability scanning
- β‘ Performance: Regular benchmarking and profiling
- π― Threat Modeling: Documented attack vectors and mitigations
- π Security Reviews: Peer review for all cryptographic code
- π§ͺ Penetration Testing: Regular security audits
- π Security Checklist: OWASP Mobile Security Guidelines
- π Dependency Scanning: Automated vulnerability detection
- π Security Metrics: Tracked security KPIs and incidents
We welcome contributions from developers, security researchers, and privacy advocates
- π΄ Fork the repository
- π Create a feature branch (
git checkout -b feature/amazing-feature) - β Test your changes thoroughly
- π Commit with conventional commits (
git commit -m 'feat: add amazing feature') - π Push to your branch (
git push origin feature/amazing-feature) - π¬ Open a Pull Request
- π§ͺ Include Tests: All new features must include comprehensive tests
- π Update Documentation: Keep README and code comments current
- π Security First: Follow secure coding practices
- π Conventional Commits: Use semantic commit messages
- π¨ Code Style: Follow project formatting and lint rules
- π¬ Be Respectful: Follow our Code of Conduct
- π Cryptography Review: Security audit and implementation review
- π Internationalization: Multi-language support
- βΏ Accessibility: Making the app usable for everyone
- π± Platform Features: Platform-specific optimizations
- π Documentation: Technical writing and tutorials
- π¨ UI/UX Design: User interface improvements
Apache License 2.0
Open source software that respects your freedom and privacy
- Signal Protocol: Inspiration for our cryptographic design
- Flutter Team: Amazing cross-platform framework
- Dart Team: Excellent server-side language and tooling
- Open Source Community: For making secure communication accessible
Need help? Have questions? Found a security issue?
Built with β€οΈ by Emil Rokossovskiy
"Privacy is not about having something to hide. Privacy is about having something to protect."
β Star this project if you believe in secure, private communication β