AgeSharp 0.1.0-preview.4

This is a prerelease version of AgeSharp.
dotnet add package AgeSharp --version 0.1.0-preview.4
                    
NuGet\Install-Package AgeSharp -Version 0.1.0-preview.4
                    
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="AgeSharp" Version="0.1.0-preview.4" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="AgeSharp" Version="0.1.0-preview.4" />
                    
Directory.Packages.props
<PackageReference Include="AgeSharp" />
                    
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 AgeSharp --version 0.1.0-preview.4
                    
#r "nuget: AgeSharp, 0.1.0-preview.4"
                    
#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 AgeSharp@0.1.0-preview.4
                    
#: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=AgeSharp&version=0.1.0-preview.4&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=AgeSharp&version=0.1.0-preview.4&prerelease
                    
Install as a Cake Tool

<p align="center"> <picture> <source media="(prefers-color-scheme: dark)" srcset="https://github.com/FiloSottile/age/blob/main/logo/logo_white.svg"> <source media="(prefers-color-scheme: light)" srcset="https://github.com/FiloSottile/age/blob/main/logo/logo.svg"> <img alt="The age logo, a wireframe of St. Peters dome in Rome, with the text: age, file encryption" width="600" src="https://github.com/FiloSottile/age/blob/main/logo/logo.svg"> </picture> </p>

NuGet codecov

AgeSharp is a C# implementation of the age file encryption format, fully interoperable with the reference Go implementation and other age-compatible tools.

It depends only on BouncyCastle.Cryptography and targets .NET 10.

Features

  • All standard recipient types: X25519, scrypt/passphrase, SSH-Ed25519, SSH-RSA
  • Post-quantum ML-KEM-768-X25519 hybrid encryption
  • Plugin protocol — interoperates with age-plugin-* binaries
  • Encrypt to multiple recipients
  • ASCII armor support
  • Pull-based streaming (EncryptReader / DecryptReader)
  • Detached header APIs (EncryptDetached / DecryptDetached)
  • Random-access decryption (AgeRandomAccess) — seek into encrypted files
  • Header inspection without decryption (AgeHeader.Parse)
  • Encrypted identity files (passphrase-protected)
  • Recipients file parsing (-R style files with comments)
  • Fully interoperable — files produced by AgeSharp decrypt with age, rage, and vice versa

Installation

dotnet add package AgeSharp

Usage

Encrypt and decrypt

using Age;
using Age.Recipients;

using var identity = X25519Identity.Generate();
var recipient = identity.Recipient;

using var input = new MemoryStream("Hello, age!"u8.ToArray());
using var encrypted = new MemoryStream();
AgeEncrypt.Encrypt(input, encrypted, recipient);

encrypted.Position = 0;
using var decrypted = new MemoryStream();
AgeEncrypt.Decrypt(encrypted, decrypted, identity);

Passphrase encryption

var passphrase = new ScryptRecipient("correct-horse-battery-staple");

using var input = new MemoryStream("Hello, age!"u8.ToArray());
using var encrypted = new MemoryStream();
AgeEncrypt.Encrypt(input, encrypted, passphrase);

encrypted.Position = 0;
using var decrypted = new MemoryStream();
AgeEncrypt.Decrypt(encrypted, decrypted, passphrase);

ASCII armor

AgeEncrypt.Encrypt(input, encrypted, armor: true, recipient);

// -----BEGIN AGE ENCRYPTED FILE-----
// YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA...
// -----END AGE ENCRYPTED FILE-----

Multiple recipients

using var alice = X25519Identity.Generate();
using var bob = X25519Identity.Generate();

AgeEncrypt.Encrypt(input, encrypted, alice.Recipient, bob.Recipient);

// Either identity can decrypt
AgeEncrypt.Decrypt(encrypted, decrypted, bob);

SSH keys

var recipient = SshEd25519Recipient.Parse("ssh-ed25519 AAAA...");
var identity = SshEd25519Identity.CreateFromFile("/path/to/id_ed25519");

AgeEncrypt.Encrypt(input, encrypted, recipient);

encrypted.Position = 0;
AgeEncrypt.Decrypt(encrypted, decrypted, identity);

Post-quantum (ML-KEM-768-X25519)

using var identity = MlKem768X25519Identity.Generate();
var recipient = identity.Recipient;

AgeEncrypt.Encrypt(input, encrypted, recipient);

Pull-based streaming

Returns a readable Stream — header and key setup is eager, payload encryption/decryption is lazy (chunk-by-chunk on Read()).

// Encrypt: returns a Stream you read ciphertext from
using var encryptedStream = AgeEncrypt.EncryptReader(plaintext, recipient);
encryptedStream.CopyTo(networkStream);

// Decrypt: returns a Stream you read plaintext from
using var decryptedStream = AgeEncrypt.DecryptReader(ciphertext, identity);
decryptedStream.CopyTo(outputStream);

Detached headers

Splits the age header and payload into separate streams — useful for storing the header and payload in different locations.

// Encrypt with separate header and payload
AgeEncrypt.EncryptDetached(input, headerOutput, payloadOutput, recipient);

// Decrypt from separate streams
AgeEncrypt.DecryptDetached(headerInput, payloadInput, output, identity);

Random-access decryption

Seek into an encrypted file and decrypt individual chunks without reading the whole file — useful for encrypted archives, databases, and large files.

using var ra = new AgeRandomAccess(ciphertext, identity);

Console.WriteLine($"Plaintext length: {ra.PlaintextLength}");

// Read 100 bytes at offset 50000
var buf = new byte[100];
ra.ReadAt(50000, buf);

// Or get a seekable Stream
using var stream = ra.GetStream();
stream.Seek(50000, SeekOrigin.Begin);
stream.Read(buf);

Header inspection

Parse the header of an encrypted file without decrypting it.

var header = AgeHeader.Parse(stream);

Console.WriteLine($"Recipients: {header.RecipientCount}");
Console.WriteLine($"Armored: {header.IsArmored}");
Console.WriteLine($"Payload offset: {header.PayloadOffset}");

foreach (var stanza in header.Recipients)
    Console.WriteLine($"  {stanza.Type}: {stanza.Args[0]}");

Parse existing keys

using var identity = AgeKeygen.ParseIdentity("AGE-SECRET-KEY-1...");
var recipient = AgeKeygen.ParseRecipient("age1...");

Custom recipients and identities

Implement IRecipient and IIdentity to integrate custom key types, remote secrets managers, or age plugins.

public class MyRecipient : IRecipient
{
    public string? Label => null; // or a security label to prevent mixing

    public Stanza Wrap(ReadOnlySpan<byte> fileKey)
    {
        // Wrap the file key using your custom scheme
        return new Stanza("MyType", ["arg1"], wrappedKey);
    }
}

public class MyIdentity : IIdentity
{
    public byte[]? Unwrap(IReadOnlyList<Stanza> stanzas)
    {
        // Return the file key if matched, null if not
    }
}

CLI

AgeSharp ships a CLI compatible with the age command.

# Encrypt
age -r age1... -o encrypted.age plaintext.txt

# Decrypt
age -d -i key.txt -o plaintext.txt encrypted.age

# Generate a key pair
age-keygen -o key.txt

# Inspect an encrypted file (no decryption needed)
age inspect encrypted.age

Feature comparison

See FEATURE_COMPARISON.md for a detailed comparison with the Go reference implementation and Rust's rage.

See also

  • age-encryption.org/v1 — the age format specification
  • age — the reference Go implementation and CLI
  • rage — a Rust implementation of age
  • awesome-age — age plugins, tools, and integrations
Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  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.1.0-preview.4 30 2/25/2026
0.1.0-preview.3 29 2/25/2026
0.1.0-preview.2 36 2/25/2026
0.1.0-preview.1 33 2/24/2026