Serilog.Sinks.File.Encrypt
2.0.0
dotnet add package Serilog.Sinks.File.Encrypt --version 2.0.0
NuGet\Install-Package Serilog.Sinks.File.Encrypt -Version 2.0.0
<PackageReference Include="Serilog.Sinks.File.Encrypt" Version="2.0.0" />
<PackageVersion Include="Serilog.Sinks.File.Encrypt" Version="2.0.0" />
<PackageReference Include="Serilog.Sinks.File.Encrypt" />
paket add Serilog.Sinks.File.Encrypt --version 2.0.0
#r "nuget: Serilog.Sinks.File.Encrypt, 2.0.0"
#:package Serilog.Sinks.File.Encrypt@2.0.0
#addin nuget:?package=Serilog.Sinks.File.Encrypt&version=2.0.0
#tool nuget:?package=Serilog.Sinks.File.Encrypt&version=2.0.0
Serilog.Sinks.File.Encrypt
A Serilog.File.Sink hook that encrypts log files using RSA and AES encryption. This package provides secure logging by encrypting log data before writing to disk, ensuring sensitive information remains protected.
🚧 Newly Released 🚧 This library is newly released. APIs may change in future versions. Please report any issues you encounter or suggestions for improvement.
Features
- Hybrid Encryption: Uses RSA encryption for key exchange and AES for efficient data encryption
- Seamless Integration: Plugs directly into Serilog.File.Sink using file lifecycle hooks
- Memory-Optimized: Producer-consumer architecture for efficient processing of large files
- CLI Tool Integration: Companion CLI tool for key generation and log decryption
- Optimal Performance: Optimized encryption performance using hybrid encryption.
Use Cases
- Secure logging of sensitive application data especially in desktop applications.
- Compliance with data protection regulations by encrypting log files.
- Protection against unauthorized access to log files in shared or cloud environments.
Performance
Production-ready performance with minimal overhead:
- ✅ 6-17% time overhead in real-world scenarios (well under typical targets)
- ✅ 200K+ logs/second throughput with buffered writes
- ✅ 1.6-2.2x memory overhead for typical usage patterns
- 🚀 Buffered writes recommended - Encrypted buffered I/O outperforms non-encrypted unbuffered
Buffering Trade-off: While buffered writes provide excellent performance, they carry a risk of data loss if the application crashes before flushing. Always call Log.CloseAndFlush() on application shutdown.
For detailed benchmarks and analysis, see the Benchmark Documentation.
Installation
Install the package via NuGet:
dotnet add package Serilog.Sinks.File.Encrypt
For key management and decryption capabilities, also install the CLI tool:
dotnet tool install --global Serilog.Sinks.File.Encrypt.Cli
Quick Start
1. Generate RSA Key Pair
Generate an RSA key pair using the CLI tool:
serilog-encrypt generate --output ./keys
This creates:
public_key.xml: Used for encryption (safe to include with your application)private_key.xml: Used for decryption (keep secure, do not distribute)
2. Configure Serilog with Encryption
using Serilog;
using Serilog.Sinks.File.Encrypt;
// Load your public key
string publicKeyXml = File.ReadAllText("./keys/public_key.xml");
// Configure Serilog with encryption (default: unbuffered for data safety)
Log.Logger = new LoggerConfiguration()
.WriteTo.File(
path: "logs/app.log",
hooks: new EncryptHooks(publicKeyXml))
.CreateLogger();
// Log as usual
Log.Information("This message will be encrypted!");
// Always flush on shutdown
Log.CloseAndFlush();
💡 Performance Tip: For high-volume scenarios where you can tolerate potential data loss on crashes, use
buffered: trueto reduce overhead from 15-17% to 6-8%. See the Advanced Usage section below.
3. Decrypt Logs
Use the CLI tool to decrypt your log files:
serilog-encrypt decrypt --key ./keys/private_key.xml --file logs/app.log --output logs/app-decrypted.log
Advanced Usage
High-Performance Configuration (Buffered Mode)
For high-volume logging scenarios where you can tolerate potential data loss on crashes:
using Serilog;
using Serilog.Sinks.File.Encrypt;
string publicKeyXml = File.ReadAllText("./keys/public_key.xml");
Log.Logger = new LoggerConfiguration()
.WriteTo.File(
path: "logs/app.log",
buffered: true, // Enables high-performance mode
flushToDiskInterval: TimeSpan.FromSeconds(1),
hooks: new EncryptHooks(publicKeyXml))
.CreateLogger();
// CRITICAL: Always flush on shutdown
Log.CloseAndFlush();
⚠️ Warning: Buffered writes risk data loss on crashes. Only use when:
- Application has reliable shutdown handling
- You can tolerate loss of recent logs (up to
flushToDiskInterval) - Performance is critical (background workers, high-volume systems)
Programmatic Key Generation
using Serilog.Sinks.File.Encrypt;
// Generate a new RSA key pair
var (publicKey, privateKey) = EncryptionUtils.GenerateRsaKeyPair(4096);
// Save keys to files
File.WriteAllText("public_key.xml", publicKey);
File.WriteAllText("private_key.xml", privateKey);
Programmatic Decryption
For large files, use the memory-optimized streaming API:
using Serilog.Sinks.File.Encrypt;
// File-to-file decryption
string privateKeyXml = File.ReadAllText("private_key.xml");
await EncryptionUtils.DecryptFileLogAsync(
"logs/app.log",
"logs/decrypted.log",
privateKeyXml);
// Stream-to-stream decryption with custom options
var options = new StreamingOptions
{
BufferSize = 64 * 1024, // 64KB chunks
QueueDepth = 20, // Queue depth
ContinueOnError = true // Continue on corruption
ErrorHandlingMode = ErrorHandlingMode.WriteToErrorLog, // Log errors to a separate file
ErrorLogPath = "decryption-errors.log" // Custom error log path
};
using var input = File.OpenRead("large-log.encrypted");
using var output = File.Create("large-log.decrypted");
await EncryptionUtils.DecryptLogFileAsync(input, output, privateKey, options);
Error Handling Modes
Choose how to handle decryption errors:
using Serilog.Sinks.File.Encrypt.Models;
// Skip corrupted sections silently (DEFAULT - ideal for JSON/structured logs)
var skipOptions = new StreamingOptions
{
ErrorHandlingMode = ErrorHandlingMode.Skip // This is the default
};
// Write error messages inline to output (use only for human-readable logs)
var inlineOptions = new StreamingOptions
{
ErrorHandlingMode = ErrorHandlingMode.WriteInline
};
// Write errors to separate log file (for troubleshooting)
var errorLogOptions = new StreamingOptions
{
ErrorHandlingMode = ErrorHandlingMode.WriteToErrorLog,
ErrorLogPath = "decryption-errors.log"
};
// Throw exception on first error (strict validation)
var strictOptions = new StreamingOptions
{
ErrorHandlingMode = ErrorHandlingMode.ThrowException,
ContinueOnError = false
};
await EncryptionUtils.DecryptLogFileAsync(input, output, privateKey, skipOptions);
Error Handling Use Cases
Skip Mode - For Structured Logging (JSON, Compact JSON):
// Prevents corrupted error messages from breaking JSON parsing
var options = new StreamingOptions { ErrorHandlingMode = ErrorHandlingMode.Skip };
await EncryptionUtils.DecryptLogFileAsync(input, output, privateKey, options);
WriteToErrorLog Mode - For Production Troubleshooting:
// Clean output + separate error tracking
var options = new StreamingOptions
{
ErrorHandlingMode = ErrorHandlingMode.WriteToErrorLog,
ErrorLogPath = "errors.log" // Optional, auto-generated if omitted
};
await EncryptionUtils.DecryptLogFileAsync(input, output, privateKey, options);
ThrowException Mode - For Data Integrity Validation:
// Fail fast on any corruption
var options = new StreamingOptions
{
ErrorHandlingMode = ErrorHandlingMode.ThrowException,
ContinueOnError = false
};
try
{
await EncryptionUtils.DecryptLogFileAsync(input, output, privateKey, options);
}
catch (CryptographicException ex)
{
Console.WriteLine($"Decryption failed: {ex.Message}");
}
Web Application Example
var builder = WebApplication.CreateBuilder(args);
// Load public key from configuration
string publicKeyXml = builder.Configuration["Logging:PublicKeyXml"];
builder.Host.UseSerilog((context, configuration) =>
configuration
.ReadFrom.Configuration(context.Configuration)
.WriteTo.File(
path: "logs/webapp-.log",
rollingInterval: RollingInterval.Day,
hooks: new EncryptHooks(publicKeyXml)));
var app = builder.Build();
app.Run();
API Reference
Key Management
(string publicKey, string privateKey) EncryptionUtils.GenerateRsaKeyPair(int keySize = 2048)
Decryption
// File-to-file async decryption
Task EncryptionUtils.DecryptLogFileAsync(string encryptedFilePath, string outputFilePath, string rsaPrivateKey, StreamingOptions? options = null, CancellationToken cancellationToken = default)
// Stream-to-stream async decryption
Task EncryptionUtils.DecryptLogFileAsync(Stream inputStream, Stream outputStream, string rsaPrivateKey, StreamingOptions? options = null, CancellationToken cancellationToken = default)
StreamingOptions
public class StreamingOptions
{
public int BufferSize { get; init; } = 16 * 1024; // 16KB default
public int QueueDepth { get; init; } = 10; // Queue depth
public bool ContinueOnError { get; init; } = true; // Error handling
public ErrorHandlingMode ErrorHandlingMode { get; init; } = Skip; // Error mode (default: Skip)
public string? ErrorLogPath { get; init; } // Error log file path
}
ErrorHandlingMode
public enum ErrorHandlingMode
{
Skip = 0, // Skip errors silently (DEFAULT - safe for all log formats)
WriteInline = 1, // Write error messages inline (use only for human-readable logs)
WriteToErrorLog = 2, // Write errors to separate log file
ThrowException = 3 // Throw exception on first error
}
Security Considerations
- Keep private keys secure and never include them in your application deployment
- Store private keys in secure key management systems in production
- Use 2048-bit RSA keys minimum (4096-bit for enhanced security)
- Restrict access to encrypted log files and private keys
CLI Tool
The companion CLI tool provides key management and decryption with full error handling control:
# Generate keys
serilog-encrypt generate --output /path/to/keys
# Decrypt with default settings
serilog-encrypt decrypt --key private_key.xml --file log.txt --output decrypted.txt
# Decrypt with error handling options
serilog-encrypt decrypt -k key.xml -f log.txt -o out.txt -e Skip # Skip errors
serilog-encrypt decrypt -k key.xml -f log.txt -o out.txt -e WriteToErrorLog --error-log errors.log # Log errors
serilog-encrypt decrypt -k key.xml -f log.txt -o out.txt -e ThrowException # Fail on errors
For detailed CLI documentation, see the CLI tool documentation.
Requirements
- .NET 8.0 or higher
- A project using Serilog.Sinks.File
- RSA key pair for encryption/decryption in XML format (generated via CLI tool or programmatically)
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. 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 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. |
-
net10.0
- Serilog.Sinks.File (>= 7.0.0)
-
net8.0
- Serilog.Sinks.File (>= 7.0.0)
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 |
|---|---|---|
| 2.0.0 | 657 | 12/2/2025 |
| 1.0.0 | 405 | 12/1/2025 |
| 0.50.1 | 171 | 11/27/2025 |
| 0.0.0-alpha.0.27 | 126 | 11/27/2025 |
| 0.0.0-alpha.0.17 | 135 | 11/25/2025 |
| 0.0.0-alpha.0.14 | 130 | 11/24/2025 |
| 0.0.0-alpha.0.13 | 126 | 11/24/2025 |
| 0.0.0-alpha.0.12 | 133 | 11/24/2025 |