VaettirNet.Olm 0.0.6

dotnet add package VaettirNet.Olm --version 0.0.6
                    
NuGet\Install-Package VaettirNet.Olm -Version 0.0.6
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="VaettirNet.Olm" Version="0.0.6" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="VaettirNet.Olm" Version="0.0.6" />
                    
Directory.Packages.props
<PackageReference Include="VaettirNet.Olm" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add VaettirNet.Olm --version 0.0.6
                    
#r "nuget: VaettirNet.Olm, 0.0.6"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package VaettirNet.Olm@0.0.6
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=VaettirNet.Olm&version=0.0.6
                    
Install as a Cake Addin
#tool nuget:?package=VaettirNet.Olm&version=0.0.6
                    
Install as a Cake Tool

VaettirNet.Olm

Build Status NuGet License: MIT

A .NET implementation of the Olm cryptographic ratchet protocol. Olm is an implementation of the Double Ratchet Algorithm, providing strong end-to-end encryption for messaging applications with forward secrecy and break-in recovery properties.

Features

  • Complete implementation of the Olm cryptographic ratchet protocol
  • X3DH (Extended Triple Diffie-Hellman) key agreement protocol for initial key exchange
  • Double Ratchet Algorithm providing strong forward secrecy and post-compromise security
  • Support for out-of-order message delivery
  • Prevention of replay attacks
  • Modern C# 13 implementation targeting .NET 9.0
  • Built on BouncyCastle for cryptographic primitives

Installation

Install the package via NuGet:

dotnet add package VaettirNet.Olm

Or via the Package Manager Console:

Install-Package VaettirNet.Olm

The package is automatically versioned using GitVersion and follows semantic versioning. You can check the latest version on NuGet.

Usage

Key Generation

Generating the necessary keys for encryption:

// Generate identity keys (long-term keys)
var aliceIdentity = X3DHPrivateIdentityKey.Generate();
var bobIdentity = X3DHPrivateIdentityKey.Generate();

// Generate ephemeral key for Alice
var aliceEphemeral = X3DHPrivateEphemeralKey.Generate();

// Generate pre-key for Bob
var bobPreKey = X3DHPrivatePreKey.Generate();

Establishing a Session

Alice initiates a session with Bob:

// Alice initiates a session with Bob
var aliceSession = OlmSession.Initiate(
    aliceIdentity,               // Alice's identity key
    bobIdentity.GetPublic(),     // Bob's public identity key
    aliceEphemeral,              // Alice's ephemeral key
    bobPreKey.GetPublic()        // Bob's public pre-key
);

// Alice sends a first message
var firstMessage = new PlainText("Hello Bob!"u8.ToArray());
var encryptedMessage = aliceSession.CreateOutputMessage(firstMessage);
// encryptedMessage will be an OlmPreKeyMessage for the first message

Bob receives and accepts the session:

// Bob receives the OlmPreKeyMessage and accepts the session
if (OlmSession.TryAcceptNewInbound(
    bobIdentity,              // Bob's identity key
    bobPreKey,                // Bob's pre-key
    encryptedMessage,         // The OlmPreKeyMessage from Alice
    out var bobSession,       // The newly created session
    out var decryptedMessage  // The decrypted message
))
{
    // Session established successfully
    // decryptedMessage contains "Hello Bob!"
    Console.WriteLine(Encoding.UTF8.GetString(decryptedMessage.Data.Span));
}

Sending and Receiving Messages

Once a session is established, messages can be exchanged:

// Bob sends a reply
var bobReply = new PlainText("Hi Alice!"u8.ToArray());
var encryptedReply = bobSession.CreateOutputMessage(bobReply);

// Alice receives and decrypts Bob's message
if (aliceSession.TryReceive(encryptedReply, out var decryptedReply))
{
    Console.WriteLine(Encoding.UTF8.GetString(decryptedReply.Data.Span)); // "Hi Alice!"
}

Handling Out-of-Order Messages

The library supports out-of-order message delivery:

// Alice sends multiple messages
var message1 = aliceSession.CreateOutputMessage(new PlainText("Message 1"u8.ToArray()));
var message2 = aliceSession.CreateOutputMessage(new PlainText("Message 2"u8.ToArray()));
var message3 = aliceSession.CreateOutputMessage(new PlainText("Message 3"u8.ToArray()));

// Bob can receive them in any order
bobSession.TryReceive(message3, out var decrypted3);
bobSession.TryReceive(message1, out var decrypted1);
bobSession.TryReceive(message2, out var decrypted2);

// All messages will be decrypted correctly

Shared Secret Derivation

For more advanced use cases, you can work directly with the X3DH shared secret:

// Create a shared secret using the X3DH protocol
X3DHSharedSecret aliceSecret = new();
aliceSecret.DeriveInitial(
    aliceIdentity,            // Alice's identity key
    bobIdentity.GetPublic(),  // Bob's public identity key
    aliceEphemeral,           // Alice's ephemeral key
    bobPreKey.GetPublic()     // Bob's public pre-key
);

// Bob computes the same shared secret
X3DHSharedSecret bobSecret = new();
bobSecret.DeriveResponse(
    bobIdentity,              // Bob's identity key
    aliceIdentity.GetPublic(), // Alice's public identity key
    aliceEphemeral.GetPublic(), // Alice's public ephemeral key
    bobPreKey                 // Bob's pre-key
);

// Both shared secrets should be identical

Architecture

VaettirNet.Olm implements the Olm protocol with a focus on security and performance:

  • X3DH Key Exchange: Secure initial key agreement protocol using multiple Diffie-Hellman operations to establish a shared secret.
  • Double Ratchet Algorithm: Combines a Diffie-Hellman key exchange with a KDF ratchet to provide forward secrecy and break-in recovery.
  • Message Keys: One-time keys are derived for each message to ensure messages remain secure even if session keys are compromised.

Security Considerations

  • Forward Secrecy: If keys are compromised, previously sent messages remain secure.
  • Break-in Recovery: The protocol can recover security if keys are compromised.
  • Key Rotation: Regularly rotate pre-keys and ephemeral keys for maximum security.
  • Replay Protection: Built-in protection against message replay attacks.
  • Side-Channel Mitigation: Uses constant-time operations for cryptographic comparisons to prevent timing attacks.

Requirements

  • .NET 9.0
  • Dependencies:
    • BouncyCastle.Cryptography
    • System.Runtime.Caching

Advanced Usage

Session Management

In a real-world application, you'll need to manage multiple sessions:

// Create a session store (you would implement ISessionStore)
private Dictionary<string, OlmSession> _sessions = new();

// Store a session by recipient ID
public void StoreSession(string recipientId, OlmSession session)
{
    _sessions[recipientId] = session;
}

// Retrieve a session
public OlmSession GetSession(string recipientId)
{
    return _sessions.TryGetValue(recipientId, out var session) ? session : null;
}

Handling Large Messages

The library can handle messages of arbitrary size:

// For large messages, you might want to use streams
public byte[] EncryptLargeFile(OlmSession session, byte[] fileData)
{
    var plainText = new PlainText(fileData);
    var encrypted = session.CreateOutputMessage(plainText);

    // Serialize the encrypted message
    var buffer = new byte[1024 * 1024]; // Adjust size as needed
    encrypted.TryWrite(buffer, out var bytesWritten);

    return buffer[..bytesWritten];
}

Integration with Matrix Protocol

This library can be used as part of a Matrix client implementation for end-to-end encryption:

// Example of integrating with Matrix protocol
public async Task SendEncryptedMatrixMessage(string roomId, string recipientUserId, string messageText)
{
    // Get or create session for recipient
    var session = GetSessionForUser(recipientUserId);

    // Encrypt the message content
    var plainText = new PlainText(Encoding.UTF8.GetBytes(messageText));
    var encrypted = session.CreateOutputMessage(plainText);

    // Serialize to bytes for transmission
    var buffer = new byte[8192];
    encrypted.TryWrite(buffer, out var bytesWritten);

    // Convert to Base64 for JSON transmission
    var base64Payload = Convert.ToBase64String(buffer[..bytesWritten]);

    // Send via Matrix API (implementation depends on your Matrix client)
    await matrixClient.SendEncryptedEvent(roomId, "m.room.encrypted", new {
        algorithm = "m.olm.v1.curve25519-aes-sha2",
        sender_key = myIdentityKey.GetPublic().ToString(),
        ciphertext = new Dictionary<string, object> {
            { recipientCurve25519Identity, new {
                body = base64Payload,
                type = encrypted is OlmPreKeyMessage ? 0 : 1
            }}
        }
    });
}

Build and Development

  1. Clone the repository: git clone https://github.com/ChadNedzlek/Olm.Net.git
  2. Restore dependencies: dotnet restore
  3. Build the project: dotnet build -c Release
  4. Run tests: dotnet test --no-build --verbosity normal --configuration Release
  5. Run benchmarks: dotnet run -c Release --project Olm.Benchmarks

Versioning

This project uses GitVersion for semantic versioning. The version is automatically determined based on Git history and tags.

Implementation Details

VaettirNet.Olm is a complete implementation of the Olm protocol specification with these key components:

  • X3DHPrivateKey/X3DHPublicKey: Base classes for all key types, handling secure key operations
  • X3DHSharedSecret: Handles the derivation of shared secrets using the X3DH protocol
  • OlmSession: Manages an encryption session between two parties
  • OlmRatchet: Implements the Double Ratchet Algorithm for message encryption/decryption
  • OlmMessage/OlmPreKeyMessage: Represents encrypted messages with proper serialization

The implementation uses modern C# 13 features including ref structs for efficient memory usage, native inline arrays for storage optimization, and pattern matching for robust message parsing.

Relationship to Matrix

This library can be used as the core encryption component for Matrix clients. The Olm protocol is used in Matrix for end-to-end encrypted direct messages, while its extension, Megolm, is used for group communications.

License

This project is licensed under the MIT License - see the license information in the package metadata for details.

Author

Chad Nedzlek

Repository

GitHub Repository

Product Compatible and additional computed target framework versions.
.NET net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.0.6 480 7/22/2025