Skip to content

Repository files navigation

LibEmiddle

BuildCoverageLicense: AGPL v3.NETVersionBuy Me A Coffee

Secure end-to-end encryption for .NET — modern cryptographic protocols, production-ready

🔒 End-to-End Encrypted • 🔑 X3DH + Double Ratchet • 📱 Multi-Device • 🏢 Enterprise-Ready

Quick StartFeaturesDocumentationLicense


A comprehensive, production-ready end-to-end encryption library for .NET applications implementing modern cryptographic protocols with a focus on security, privacy, and usability. Now with advanced features including post-quantum cryptography preparation, WebRTC transport, message batching, and enterprise-grade monitoring capabilities.


🚀 Quick Start

// Install via NuGet// dotnet add package LibEmiddle --version 2.7.0usingLibEmiddle.API;usingLibEmiddle.Domain.Enums;// Configure the clientvaroptions=newLibEmiddleClientOptions{TransportType=TransportType.Http,ServerEndpoint="https://your-server.com",EnableMultiDevice=true,EnableMessageHistory=true};// Create and initialize the clientusingvarclient=newLibEmiddleClient(options);awaitclient.InitializeAsync();// Start a secure conversationvarchatSession=awaitclient.CreateChatSessionAsync(recipientPublicKey,"user123");varencryptedMessage=awaitchatSession.EncryptAsync("Hello, secure world!");

✨ Core Features

🔒 Advanced Cryptographic Protocols

  • X3DH Key Exchange - Extended Triple Diffie-Hellman for secure initial key agreement
  • Double Ratchet Algorithm - Continuous key rotation for forward secrecy
  • AES-GCM Encryption - Authenticated encryption with strong integrity guarantees
  • Ed25519 & X25519 - Modern elliptic curve cryptography for digital signatures and key exchange
  • Post-Quantum Cryptography - API scaffolding only; see Future Roadmap before use
  • Advanced Key Rotation - Sophisticated key rotation policies and monitoring
  • Replay Attack Protection - Per-sender message ID deduplication in both chat and group sessions
  • Post-Removal Forward Secrecy - Group chain key rotated immediately on member removal
  • Out-of-Order Delivery - Signal PN header field lets messages that arrive across a ratchet step still decrypt (v2.7)

💬 Communication Patterns

  • One-to-One Messaging - Secure private conversations with forward secrecy
  • Group Messaging - Efficient encrypted group chats with advanced member management
  • Multi-Device Support - Seamless synchronization with encrypted persistent device list
  • Asynchronous Communication - Robust mailbox system with delivery and read receipts
  • Message Batching - Efficient bulk messaging with compression support (v2.5)
  • Flexible Transport Layer - HTTP and InMemory transports (WebRTC planned for v3.0)
  • Out-of-Order Tolerance - Skipped message keys are retained across DH ratchet steps, so delayed or reordered messages still decrypt

🏗️ Architecture Highlights

  • Unified Client API - Single LibEmiddleClient for all operations (IAsyncDisposable support)
  • Modular Design - Pluggable transport, storage, and crypto providers
  • Session Management - Automatic session persistence and recovery with backup capabilities
  • Structured Exceptions - LibEmiddleException with typed LibEmiddleErrorCode for precise error handling
  • Event-Driven - Real-time message handling with comprehensive events
  • Feature Flags - Gradual rollout and configuration of new capabilities (v2.5)
  • Enterprise Monitoring - Built-in diagnostics, plus retry / circuit-breaker / timeout via ResilienceManager

Note: connection pooling, session backup, advanced key-rotation scheduling, WebRTC transport, and post-quantum crypto are present as API stubs only — they satisfy their interfaces but perform no real work. See Feature Maturity before depending on them.


💬 Individual Chat Sessions

// First contact: supply the recipient's full X3DHPublicBundle as UTF-8 JSON bytes.// The library caches the bundle for future lookups by identity key.byte[]bundleBytes=Encoding.UTF8.GetBytes(JsonSerializer.Serialize(recipientBundle));varchatSession=awaitclient.CreateChatSessionAsync(bundleBytes,recipientUserId:"alice@example.com",options:newChatSessionOptions{RotationStrategy=KeyRotationStrategy.Aggressive,EnableMessageHistory=true});// Subsequent contacts: a bare 32-byte identity key is sufficient// (the bundle is looked up from the local cache).varchatSession=awaitclient.CreateChatSessionAsync(recipientPublicKey,// 32-byte Ed25519 identity keyrecipientUserId:"alice@example.com",options:newChatSessionOptions{RotationStrategy=KeyRotationStrategy.Standard});// Send encrypted messagesvarencryptedMessage=awaitchatSession.EncryptAsync("Hello Alice!");// Receive and decrypt messagesvardecryptedMessage=awaitchatSession.DecryptAsync(incomingEncryptedMessage);Console.WriteLine($"Received: {decryptedMessage}");// Send message directly by recipient key (creates session if needed)vardirectMessage=awaitclient.SendChatMessageAsync(recipientPublicKey,"Direct message without explicit session creation");// Handle incoming messages with eventschatSession.MessageReceived+=(sender,args)=>{Console.WriteLine($"New message: {args.DecryptedContent}");};

🚀 Multi-Device Management

// Enable multi-device support in client optionsvaroptions=newLibEmiddleClientOptions{EnableMultiDevice=true,MaxLinkedDevices=5};usingvarclient=newLibEmiddleClient(options);awaitclient.InitializeAsync();// Link a new devicevarlinkMessage=client.CreateDeviceLinkMessage(newDevicePublicKey);// Process device link on the new devicevarsuccess=awaitclient.ProcessDeviceLinkMessageAsync(linkMessage);// Synchronize data across devicesvarsyncData=Encoding.UTF8.GetBytes("Session data to sync");varsyncMessages=client.CreateSyncMessages(syncData);// Send sync messages to all linked devicesforeach(var(deviceId,message)insyncMessages){awaitclient.SendToDeviceAsync(deviceId,message);}// Revoke a compromised deviceawaitclient.RevokeDeviceAsync(compromisedDevicePublicKey,"Device lost");

🔐 Enhanced Group Messaging

// Create a new groupvargroupSession=awaitclient.CreateGroupAsync(groupId:"team-secure-chat",groupName:"Development Team",options:newGroupSessionOptions{RotationStrategy=KeyRotationStrategy.Standard,MaxMembers=50});// Add members to the groupawaitgroupSession.AddMemberAsync(member1PublicKey,MemberRole.Admin);awaitgroupSession.AddMemberAsync(member2PublicKey,MemberRole.Member);// Send encrypted group messagesvarencryptedGroupMessage=awaitclient.SendGroupMessageAsync("team-secure-chat","Confidential team discussion");// Join an existing group using distribution messagevarjoinedGroup=awaitclient.JoinGroupAsync(distributionMessage);// Handle group eventsgroupSession.MemberAdded+=(sender,args)=>{Console.WriteLine($"Member {args.MemberPublicKey} joined the group");};groupSession.MessageReceived+=(sender,args)=>{Console.WriteLine($"Group message: {args.DecryptedContent}");};// Rotate group keys (admin only)awaitgroupSession.RotateKeysAsync();// Leave the groupawaitclient.LeaveGroupAsync("team-secure-chat");

📬 Mailbox Transport System

LibEmiddle uses a flexible mailbox transport system for asynchronous encrypted message delivery. The transport layer handles message routing while encryption is managed by the Double Ratchet protocol.

Transport Types

InMemory Transport (Testing & Development)

// Perfect for testing and local developmentvaroptions=newLibEmiddleClientOptions{TransportType=TransportType.InMemory};usingvarclient=newLibEmiddleClient(options);awaitclient.InitializeAsync();

HTTP Transport (Production)

// Production-ready HTTP REST API transportvaroptions=newLibEmiddleClientOptions{TransportType=TransportType.Http,ServerEndpoint="https://messaging-server.example.com/api",NetworkTimeoutMs=30000,EnableStrictCertificateValidation=true,CustomHeaders=newDictionary<string,string>{["Authorization"]="Bearer your-jwt-token"}};usingvarclient=newLibEmiddleClient(options);awaitclient.InitializeAsync();

Receiving Messages

// Listen for incoming messagesclient.MessageReceived+=async(sender,args)=>{Console.WriteLine($"From: {Convert.ToBase64String(args.Message.SenderKey)[..8]}...");Console.WriteLine($"Message: {args.DecryptedContent}");// Optionally mark as readawaitclient.MarkMessageAsReadAsync(args.Message.Id);};// Start listening (default 5 second polling interval)awaitclient.StartListeningAsync();// For low-latency applications, use shorter pollingawaitclient.StartListeningAsync(pollingInterval:1000);// 1 second// Stop listening when doneawaitclient.StopListeningAsync();

Sending Messages

// Send a message (automatically encrypted with Double Ratchet)awaitclient.SendChatMessageAsync(recipientPublicKey,"Hello!");// Or use ChatSession for more control (requires bundle cached or pass bundleBytes on first use)varsession=awaitclient.CreateChatSessionAsync(recipientPublicKey,"user@example.com");awaitclient.SendChatMessageAsync(recipientPublicKey,"Secure message");

Architecture Overview

Application → LibEmiddleClient → ChatSession → MailboxManager (encrypts)
→ IMailboxTransport → HttpMailboxTransport → Server

Key Point: Only MailboxManager handles encryption/decryption. Transport layers work with already-encrypted messages.

For a complete guide, see Mailbox Transport Guide and Message Flow Diagram.


🔒 Advanced Configuration

// Comprehensive client configurationvaroptions=newLibEmiddleClientOptions{// Storage configurationIdentityKeyPath="keys/identity.key",SessionStoragePath="data/sessions",KeyStoragePath="data/keys",// Transport settingsTransportType=TransportType.Http,ServerEndpoint="https://api.example.com",NetworkTimeoutMs=30000,// Security policiesSecurityPolicy=newSecurityPolicyOptions{RequirePerfectForwardSecrecy=true,RequireMessageAuthentication=true,MinimumProtocolVersion="2.0",AllowInsecureConnections=false},// Key managementDefaultRotationStrategy=KeyRotationStrategy.Aggressive,MaxOneTimePreKeys=100,MaxSkippedMessageKeys=1000,EnableAutomaticKeyRotation=true,// Multi-device supportEnableMultiDevice=true,MaxLinkedDevices=10,// Performance and reliabilityEnableMessageHistory=true,MaxMessageHistoryPerSession=1000,EnableSecureMemory=true,EnableSessionPersistence=true,// Retry configurationRetryOptions=newRetryOptions{MaxRetries=3,BaseDelayMs=1000,MaxDelayMs=30000,BackoffMultiplier=2.0}};usingvarclient=newLibEmiddleClient(options);

🔍 Session Management

// Get all active sessionsvaractiveSessions=awaitclient.GetActiveSessionsAsync();// Get specific session by IDvarsession=awaitclient.GetSessionAsync(sessionId);// Get chat sessions with a specific uservaruserSessions=awaitclient.GetChatSessionsAsync(userPublicKey);// Session lifecycle managementawaitsession.ActivateAsync();awaitsession.SuspendAsync("Temporary suspension");awaitsession.ResumeAsync();awaitsession.TerminateAsync();// Session persistence and recoveryawaitclient.SaveSessionAsync(session);varrecoveredSession=awaitclient.LoadSessionAsync(sessionId);// Session metadata and historysession.Metadata["custom_field"]="value";varmessageHistory=session.GetMessageHistory();// Session eventssession.StateChanged+=(sender,args)=>{Console.WriteLine($"Session {args.SessionId} state changed to {args.NewState}");};

🆕 Advanced Features

📦 Message Batching

// Enable message batching for improved throughputvaroptions=newLibEmiddleClientOptions{FeatureFlags=newFeatureFlags{EnableMessageBatching=true},BatchingOptions=newBatchingOptions{MaxBatchSize=50,BatchTimeoutMs=1000,CompressionLevel=CompressionLevel.Balanced}};// Messages are automatically batched and compressedawaitclient.SendChatMessageAsync(recipientKey,"Message 1");awaitclient.SendChatMessageAsync(recipientKey,"Message 2");awaitclient.SendChatMessageAsync(recipientKey,"Message 3");// All three messages sent in a single compressed batch

🔐 Post-Quantum Cryptography Preparation

// Configure post-quantum crypto algorithms (preparation for future)varoptions=newLibEmiddleClientOptions{PostQuantumOptions=newPostQuantumOptions{Algorithm=PostQuantumAlgorithm.Kyber1024,EnableHybridMode=true,// Classical + Post-quantumKeyExchangeMode=KeyExchangeMode.Hybrid}};// The system will use hybrid classical+PQ when availableusingvarclient=newLibEmiddleClient(options);

📊 Enterprise Monitoring & Diagnostics

// Enable comprehensive monitoring and diagnosticsvaroptions=newLibEmiddleClientOptions{FeatureFlags=newFeatureFlags{EnableDiagnostics=true,EnableResilienceManager=true},ResilienceOptions=newResilienceOptions{RetryPolicy=RetryPolicy.ExponentialBackoff,HealthCheckIntervalMs=30000,EnableFailover=true}};usingvarclient=newLibEmiddleClient(options);// Access diagnostics informationvardiagnostics=client.GetDiagnostics();Console.WriteLine($"Active Sessions: {diagnostics.ActiveSessions}");Console.WriteLine($"Messages Sent: {diagnostics.MessagesSent}");Console.WriteLine($"Network Quality: {diagnostics.NetworkQuality}");// Monitor resilience eventsclient.ResilienceManager.ConnectionRestored+=(sender,args)=>{Console.WriteLine($"Connection restored after {args.DowntimeMs}ms");};

🏊‍♂️ Connection Pooling

// Configure connection pooling for high-throughput scenariosvaroptions=newLibEmiddleClientOptions{ConnectionPoolOptions=newConnectionPoolOptions{MinPoolSize=5,MaxPoolSize=20,ConnectionTimeoutMs=30000,IdleTimeoutMs=300000,EnableLoadBalancing=true}};// Connections are automatically managed and reusedusingvarclient=newLibEmiddleClient(options);

🔄 Advanced Key Rotation

// Configure sophisticated key rotation policiesvarrotationPolicy=newKeyRotationPolicy{Strategy=KeyRotationStrategy.Adaptive,TimeBasedRotationIntervalHours=24,MessageCountThreshold=10000,RiskBasedRotation=true,BackupKeyCount=3};awaitclient.SetAdvancedKeyRotationPolicyAsync(sessionId,rotationPolicy);// Monitor key rotation eventsclient.KeyRotated+=(sender,args)=>{Console.WriteLine($"Keys rotated for session {args.SessionId}: {args.RotationReason}");};

🛡️ Security Features

Forward Secrecy & Post-Compromise Security

  • Symmetric Ratchet - Every message key is derived, used once, then zeroed; used keys are never persisted
  • DH Ratchet - A new Diffie-Hellman ratchet step runs on receipt of a peer's new ratchet key, giving post-compromise recovery
  • Perfect Forward Secrecy - Past messages remain secure even if current keys are compromised
  • Post-Removal Forward Secrecy - Group chain keys rotate immediately when a member is removed

On KeyRotationStrategy.Standard (changed in v2.7): the DH ratchet advances only in response to a peer's new ratchet key, per the Signal specification. Earlier versions also rotated the sender's ratchet key every 20 messages; because a DH ratchet step is only valid once the peer holds the new public key, that could diverge both sides' DH inputs and permanently break a session where both parties were actively sending. Forward secrecy within a chain comes from the symmetric ratchet and is unaffected. KeyRotationStrategy.AfterEveryMessage is unchanged.

Authentication & Integrity

  • Message Authentication - AES-256-GCM authenticates every message body
  • Replay Protection - 500-entry FIFO deduplication in chat sessions, per-sender message IDs in groups
  • Tampering Detection - Immediate detection of ciphertext modification
  • Key Validation - X25519 public keys are checked against the full libsodium small-order point blacklist

Memory Security

  • Secure Memory Handling - Key material is pinned and zeroed via sodium_memzero, including superseded root keys, chain keys, retired ratchet private keys, and evicted skipped-message keys
  • Key Derivation - HKDF for protocol keys; Argon2id (memory-hard, 64 MB, per-key random salt) for password-based keys
  • Constant-Time Operations - Protection against timing attacks

🧪 Feature Maturity

Not every type in the public surface is backed by a real implementation. This table is the authoritative list — treat anything marked Stub as unavailable.

AreaStatusNotes
X3DH + Double Ratchet✅ ProductionSignal-compliant key agreement and ratcheting
AES-256-GCM / Ed25519 / X25519✅ ProductionAll via libsodium
Chat & group sessions✅ ProductionReplay protection, forward secrecy, member management
Multi-device linking & sync✅ ProductionEncrypted persistent device list
Session persistence✅ ProductionArgon2id-derived keys, atomic writes
HTTP / InMemory transport✅ Production
Resilience (retry, circuit breaker, timeout)✅ ProductionResilienceManager
Post-quantum crypto⚠️StubPostQuantumCryptoStub returns random bytes for all Kyber/Dilithium/Falcon operations and its VerifyAsync returns true for any correctly-sized signature. Do not use for any security decision.
WebRTC transport⚠️StubEchoes sent bytes back as received
Session backup manager⚠️StubReturns hardcoded checksums; writes nothing to disk
Connection pool⚠️StubReturns a connection that echoes sends as receives
Advanced key rotation scheduling⚠️StubTask.Delay then a synthetic result; no keys are rotated

All stubs are targeted for real implementations in v3.0.


⬆️ Upgrading to 2.7.0

Breaking — password-protected key storage.StoreKeyAsync() / RetrieveKeyAsync() now derive their encryption key with a fresh random Argon2id salt per stored key instead of a fixed application-wide salt. The stored blob layout changed from nonce‖ciphertext to salt‖nonce‖ciphertext, so password-protected keys written by 2.6.x and earlier cannot be read by 2.7.0. Re-store any affected keys before upgrading, or keep a 2.6.x reader available to migrate them. Keys stored without a password are unaffected, as are session files and device lists.

Behavioral — KeyRotationStrategy.Standard. No longer performs a send-count-based DH ratchet rotation; see Forward Secrecy & Post-Compromise Security. No API change and no action required.

Wire format — additive and backward compatible.EncryptedMessage gained PreviousChainLength (the Signal PN header field). It defaults to 0 when absent, so 2.7.0 reads messages from older peers. Older peers ignore the field. Out-of-order delivery across a ratchet step only recovers when both sides run 2.7.0+.


📦 Installation

NuGet Package

dotnet add package LibEmiddle --version 2.7.0

Package Manager Console

Install-Package LibEmiddle -Version 2.7.0

Requirements

  • .NET 8.0 or .NET 10.0 (both LTS)
  • Windows, Linux, or macOS
  • libsodium native library (included in package)

🔮 Future Roadmap

Planned Features

WebRTC Transport (Under Development)

Direct peer-to-peer encrypted communication using WebRTC data channels:

  • Low-latency P2P messaging without server intermediaries
  • NAT traversal with ICE/STUN/TURN support
  • Adaptive bitrate based on network conditions
  • Network quality monitoring and automatic fallback

Status: API stub only — WebRTCTransportStub echoes sent bytes back as received bytes. Not functional.

Target: v3.0 release

// Future API (not yet functional)varwebRtcOptions=newLibEmiddleClientOptions{TransportType=TransportType.WebRTC,WebRTCOptions=newWebRTCOptions{ICEServers=new[]{"stun:stun.l.google.com:19302"},EnableAdaptiveBitrate=true}};

Other Planned Enhancements

  • Real-time presence indicators
  • Message search and indexing
  • Advanced group permissions and roles
  • Cross-platform push notifications
  • Server-side message filtering
  • WebSocket transport with server push (alternative to polling)

📄 License

This project is licensed under the GNU Affero General Public License v3.0 (AGPL-3.0).

⚠️Important: If you modify this software and provide it as a service over a network (e.g., SaaS), you must make the complete source code of your modified version available to all users.

See LICENSE file for details or visit https://www.gnu.org/licenses/agpl-3.0.html


🤝 Contributing

We welcome contributions! Please see our contributing guidelines and:

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Add tests for new functionality
  5. Submit a pull request

📚 Documentation

The Documentation/ folder contains comprehensive technical documentation including:

  • Mailbox Transport Guide: Complete guide to the mailbox transport system (Mailbox-Transport-Guide.md)
  • Message Flow Diagrams: Mermaid sequence diagrams showing complete message flow (Message-Flow-Sequence.md)
  • Architecture Diagrams: Full system architecture and component interactions
  • Sequence Diagrams: Detailed protocol flows for all major operations
    • 1-to-1 Chat establishment and messaging
    • Group Chat creation and management
    • Device linking and revocation processes
    • Advanced key rotation workflows
    • Post-quantum key exchange preparation
    • Message batching and compression flows
  • Technical Specifications: In-depth coverage of cryptographic protocols and security features

👤 About the Author

Built by Russell Benzing. Reach out at me@russellbenzing.com.


💬 Support

If LibEmiddle is useful to you, you can support the work:

Buy Me A Coffee


🔗 References

About

A .NET C# library for building secure, end-to-end encrypted communication applications with industry-standard encryption protocols.

Topics

Resources

Code of conduct

Stars

1 star

Watchers

1 watching

Forks

Releases

Used by

Contributors

Languages