dumbtv
dumbtv takes the ads, screen tracking and update nags out of your Fire TV over ADB. No root, none of your apps touched, every step can be undone. Free and open source.
A .NET C# library for building secure, end-to-end encrypted communication applications with industry-standard encryption protocols.
SecurityC#GitHub @rbenzingOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
Loading the full README. The saved excerpt is shown below.
Secure end-to-end encryption for .NET — modern cryptographic protocols, production-ready
🔒 End-to-End Encrypted • 🔑 X3DH + Double Ratchet • 📱 Multi-Device • 🏢 Enterprise-Ready
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.Read the full README ↗Secure end-to-end encryption for .NET — modern cryptographic protocols, production-ready
🔒 End-to-End Encrypted • 🔑 X3DH + Double Ratchet • 📱 Multi-Device • 🏢 Enterprise-Ready
Quick Start • Features • Documentation • License
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.
// Install via NuGet
// dotnet add package LibEmiddle --version 2.7.0
using LibEmiddle.API;
using LibEmiddle.Domain.Enums;
// Configure the client
var options = new LibEmiddleClientOptions
{
TransportType = TransportType.Http,
ServerEndpoint = "https://your-server.com",
EnableMultiDevice = true,
EnableMessageHistory = true
};
// Create and initialize the client
using var client = new LibEmiddleClient(options);
await client.InitializeAsync();
// Start a secure conversation
var chatSession = await client.CreateChatSessionAsync(recipientPublicKey, "user123");
var encryptedMessage = await chatSession.EncryptAsync("Hello, secure world!");
PN header field lets messages that arrive across a ratchet step still decrypt (v2.7)LibEmiddleClient for all operations (IAsyncDisposable support)LibEmiddleException with typed LibEmiddleErrorCode for precise error handlingResilienceManagerNote: 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.
// 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));
var chatSession = await client.CreateChatSessionAsync(
bundleBytes,
recipientUserId: "[email protected]",
options: new ChatSessionOptions
{
RotationStrategy = KeyRotationStrategy.Aggressive,
EnableMessageHistory = true
});
// Subsequent contacts: a bare 32-byte identity key is sufficient
// (the bundle is looked up from the local cache).
var chatSession = await client.CreateChatSessionAsync(
recipientPublicKey, // 32-byte Ed25519 identity key
recipientUserId: "[email protected]",
options: new ChatSessionOptions { RotationStrategy = KeyRotationStrategy.Standard });
// Send encrypted messages
var encryptedMessage = await chatSession.EncryptAsync("Hello Alice!");
// Receive and decrypt messages
var decryptedMessage = await chatSession.DecryptAsync(incomingEncryptedMessage);
Console.WriteLine($"Received: {decryptedMessage}");
// Send message directly by recipient key (creates session if needed)
var directMessage = await client.SendChatMessageAsync(
recipientPublicKey,
"Direct message without explicit session creation");
// Handle incoming messages with events
chatSession.MessageReceived += (sender, args) =>
{
Console.WriteLine($"New message: {args.DecryptedContent}");
};
// Enable multi-device support in client options
var options = new LibEmiddleClientOptions
{
EnableMultiDevice = true,
MaxLinkedDevices = 5
};
using var client = new LibEmiddleClient(options);
await client.InitializeAsync();
// Link a new device
var linkMessage = client.CreateDeviceLinkMessage(newDevicePublicKey);
// Process device link on the new device
var success = await client.ProcessDeviceLinkMessageAsync(linkMessage);
// Synchronize data across devices
var syncData = Encoding.UTF8.GetBytes("Session data to sync");
var syncMessages = client.CreateSyncMessages(syncData);
// Send sync messages to all linked devices
foreach (var (deviceId, message) in syncMessages)
{
await client.SendToDeviceAsync(deviceId, message);
}
// Revoke a compromised device
await client.RevokeDeviceAsync(compromisedDevicePublicKey, "Device lost");
// Create a new group
var groupSession = await client.CreateGroupAsync(
groupId: "team-secure-chat",
groupName: "Development Team",
options: new GroupSessionOptions
{
RotationStrategy = KeyRotationStrategy.Standard,
MaxMembers = 50
});
// Add members to the group
await groupSession.AddMemberAsync(member1PublicKey, MemberRole.Admin);
await groupSession.AddMemberAsync(member2PublicKey, MemberRole.Member);
// Send encrypted group messages
var encryptedGroupMessage = await client.SendGroupMessageAsync(
"team-secure-chat",
"Confidential team discussion");
// Join an existing group using distribution message
var joinedGroup = await client.JoinGroupAsync(distributionMessage);
// Handle group events
groupSession.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)
await groupSession.RotateKeysAsync();
// Leave the group
await client.LeaveGroupAsync("team-secure-chat");
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.
// Perfect for testing and local development
var options = new LibEmiddleClientOptions
{
TransportType = TransportType.InMemory
};
using var client = new LibEmiddleClient(options);
await client.InitializeAsync();
// Production-ready HTTP REST API transport
var options = new LibEmiddleClientOptions
{
TransportType = TransportType.Http,
ServerEndpoint = "https://messaging-server.example.com/api",
NetworkTimeoutMs = 30000,
EnableStrictCertificateValidation = true,
CustomHeaders = new Dictionary<string, string>
{
["Authorization"] = "Bearer your-jwt-token"
}
};
using var client = new LibEmiddleClient(options);
await client.InitializeAsync();
// Listen for incoming messages
client.MessageReceived += async (sender, args) =>
{
Console.WriteLine($"From: {Convert.ToBase64String(args.Message.SenderKey)[..8]}...");
Console.WriteLine($"Message: {args.DecryptedContent}");
// Optionally mark as read
await client.MarkMessageAsReadAsync(args.Message.Id);
};
// Start listening (default 5 second polling interval)
await client.StartListeningAsync();
// For low-latency applications, use shorter polling
await client.StartListeningAsync(pollingInterval: 1000); // 1 second
// Stop listening when done
await client.StopListeningAsync();
// Send a message (automatically encrypted with Double Ratchet)
await client.SendChatMessageAsync(recipientPublicKey, "Hello!");
// Or use ChatSession for more control (requires bundle cached or pass bundleBytes on first use)
var session = await client.CreateChatSessionAsync(recipientPublicKey, "[email protected]");
await client.SendChatMessageAsync(recipientPublicKey, "Secure message");
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.
// Comprehensive client configuration
var options = new LibEmiddleClientOptions
{
// Storage configuration
IdentityKeyPath = "keys/identity.key",
SessionStoragePath = "data/sessions",
KeyStoragePath = "data/keys",
// Transport settings
TransportType = TransportType.Http,
ServerEndpoint = "https://api.example.com",
NetworkTimeoutMs = 30000,
// Security policies
SecurityPolicy = new SecurityPolicyOptions
{
RequirePerfectForwardSecrecy = true,
RequireMessageAuthentication = true,
MinimumProtocolVersion = "2.0",
AllowInsecureConnections = false
},
// Key management
DefaultRotationStrategy = KeyRotationStrategy.Aggressive,
MaxOneTimePreKeys = 100,
MaxSkippedMessageKeys = 1000,
EnableAutomaticKeyRotation = true,
// Multi-device support
EnableMultiDevice = true,
MaxLinkedDevices = 10,
// Performance and reliability
EnableMessageHistory = true,
MaxMessageHistoryPerSession = 1000,
EnableSecureMemory = true,
EnableSessionPersistence = true,
// Retry configuration
RetryOptions = new RetryOptions
{
MaxRetries = 3,
BaseDelayMs = 1000,
MaxDelayMs = 30000,
BackoffMultiplier = 2.0
}
};
using var client = new LibEmiddleClient(options);
// Get all active sessions
var activeSessions = await client.GetActiveSessionsAsync();
// Get specific session by ID
var session = await client.GetSessionAsync(sessionId);
// Get chat sessions with a specific user
var userSessions = await client.GetChatSessionsAsync(userPublicKey);
// Session lifecycle management
await session.ActivateAsync();
await session.SuspendAsync("Temporary suspension");
await session.ResumeAsync();
await session.TerminateAsync();
// Session persistence and recovery
await client.SaveSessionAsync(session);
var recoveredSession = await client.LoadSessionAsync(sessionId);
// Session metadata and history
session.Metadata["custom_field"] = "value";
var messageHistory = session.GetMessageHistory();
// Session events
session.StateChanged += (sender, args) =>
{
Console.WriteLine($"Session {args.SessionId} state changed to {args.NewState}");
};
// Enable message batching for improved throughput
var options = new LibEmiddleClientOptions
{
FeatureFlags = new FeatureFlags
{
EnableMessageBatching = true
},
BatchingOptions = new BatchingOptions
{
MaxBatchSize = 50,
BatchTimeoutMs = 1000,
CompressionLevel = CompressionLevel.Balanced
}
};
// Messages are automatically batched and compressed
await client.SendChatMessageAsync(recipientKey, "Message 1");
await client.SendChatMessageAsync(recipientKey, "Message 2");
await client.SendChatMessageAsync(recipientKey, "Message 3");
// All three messages sent in a single compressed batch
// Configure post-quantum crypto algorithms (preparation for future)
var options = new LibEmiddleClientOptions
{
PostQuantumOptions = new PostQuantumOptions
{
Algorithm = PostQuantumAlgorithm.Kyber1024,
EnableHybridMode = true, // Classical + Post-quantum
KeyExchangeMode = KeyExchangeMode.Hybrid
}
};
// The system will use hybrid classical+PQ when available
using var client = new LibEmiddleClient(options);
// Enable comprehensive monitoring and diagnostics
var options = new LibEmiddleClientOptions
{
FeatureFlags = new FeatureFlags
{
EnableDiagnostics = true,
EnableResilienceManager = true
},
ResilienceOptions = new ResilienceOptions
{
RetryPolicy = RetryPolicy.ExponentialBackoff,
HealthCheckIntervalMs = 30000,
EnableFailover = true
}
};
using var client = new LibEmiddleClient(options);
// Access diagnostics information
var diagnostics = client.GetDiagnostics();
Console.WriteLine($"Active Sessions: {diagnostics.ActiveSessions}");
Console.WriteLine($"Messages Sent: {diagnostics.MessagesSent}");
Console.WriteLine($"Network Quality: {diagnostics.NetworkQuality}");
// Monitor resilience events
client.ResilienceManager.ConnectionRestored += (sender, args) =>
{
Console.WriteLine($"Connection restored after {args.DowntimeMs}ms");
};
// Configure connection pooling for high-throughput scenarios
var options = new LibEmiddleClientOptions
{
ConnectionPoolOptions = new ConnectionPoolOptions
{
MinPoolSize = 5,
MaxPoolSize = 20,
ConnectionTimeoutMs = 30000,
IdleTimeoutMs = 300000,
EnableLoadBalancing = true
}
};
// Connections are automatically managed and reused
using var client = new LibEmiddleClient(options);
// Configure sophisticated key rotation policies
var rotationPolicy = new KeyRotationPolicy
{
Strategy = KeyRotationStrategy.Adaptive,
TimeBasedRotationIntervalHours = 24,
MessageCountThreshold = 10000,
RiskBasedRotation = true,
BackupKeyCount = 3
};
await client.SetAdvancedKeyRotationPolicyAsync(sessionId, rotationPolicy);
// Monitor key rotation events
client.KeyRotated += (sender, args) =>
{
Console.WriteLine($"Keys rotated for session {args.SessionId}: {args.RotationReason}");
};
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.AfterEveryMessageis unchanged.
sodium_memzero, including superseded root keys, chain keys, retired ratchet private keys, and evicted skipped-message keysNot every type in the public surface is backed by a real implementation. This table is the authoritative list — treat anything marked Stub as unavailable.
| Area | Status | Notes |
|---|---|---|
| X3DH + Double Ratchet | ✅ Production | Signal-compliant key agreement and ratcheting |
| AES-256-GCM / Ed25519 / X25519 | ✅ Production | All via libsodium |
| Chat & group sessions | ✅ Production | Replay protection, forward secrecy, member management |
| Multi-device linking & sync | ✅ Production | Encrypted persistent device list |
| Session persistence | ✅ Production | Argon2id-derived keys, atomic writes |
| HTTP / InMemory transport | ✅ Production | |
| Resilience (retry, circuit breaker, timeout) | ✅ Production | ResilienceManager |
| Post-quantum crypto | ⚠️ Stub | PostQuantumCryptoStub 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 | ⚠️ Stub | Echoes sent bytes back as received |
| Session backup manager | ⚠️ Stub | Returns hardcoded checksums; writes nothing to disk |
| Connection pool | ⚠️ Stub | Returns a connection that echoes sends as receives |
| Advanced key rotation scheduling | ⚠️ Stub | Task.Delay then a synthetic result; no keys are rotated |
All stubs are targeted for real implementations in v3.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+.
dotnet add package LibEmiddle --version 2.7.0
Install-Package LibEmiddle -Version 2.7.0
Direct peer-to-peer encrypted communication using WebRTC data channels:
Status: API stub only — WebRTCTransportStub echoes sent bytes back as received bytes. Not functional.
Target: v3.0 release
// Future API (not yet functional)
var webRtcOptions = new LibEmiddleClientOptions
{
TransportType = TransportType.WebRTC,
WebRTCOptions = new WebRTCOptions
{
ICEServers = new[] { "stun:stun.l.google.com:19302" },
EnableAdaptiveBitrate = true
}
};
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
We welcome contributions! Please see our contributing guidelines and:
The Documentation/ folder contains comprehensive technical documentation including:
Built by Russell Benzing. Reach out at [email protected].
If LibEmiddle is useful to you, you can support the work: