| status | title | description | tags | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
draft |
ktsu.Abstractions |
A library providing a comprehensive set of interfaces for compression, encryption, hashing, obfuscation, serialization, and filesystem access with zero-allocation Try* methods and convenient default implementations. |
|
A comprehensive library of interfaces that define a consistent, high-performance API for common cross-cutting concerns:
- Compression:
ICompressionProvider- compress/decompress data with Span and Stream support - Encryption:
IEncryptionProvider- encrypt/decrypt data with key and IV management - Hashing:
IHashProvider- hash data with configurable output length - Obfuscation:
IObfuscationProvider- reversible obfuscation/deobfuscation - Serialization:
ISerializationProvider- serialize/deserialize objects with TextReader/TextWriter support - Filesystem:
IFileSystemProvider- file system operations abstraction
Each interface supports both zero-allocation Try* and Stream based methods and convenient self-allocating methods, with comprehensive async support.
This package multi-targets common frameworks for broad compatibility:
- netstandard2.1
- net5.0, net6.0, net7.0, net8.0, net9.0
Supported OS: Windows, Linux, macOS.
Via dotnet CLI:
dotnet add package ktsu.AbstractionsVia NuGet Package Manager:
Install-Package ktsu.AbstractionsVia PackageReference in csproj:
<ItemGroup>
<PackageReference Include="ktsu.Abstractions" Version="1.0.0" />
</ItemGroup>Using the implementations from the ktsu.Common package via DI:
using ktsu.Abstractions;
using ktsu.Common;
using Microsoft.Extensions.DependencyInjection;
IServiceCollection services = new ServiceCollection();
services.AddTransient<ICompressionProvider, ktsu.Common.GZipCompressionProvider>();
services.AddTransient<IEncryptionProvider, ktsu.Common.AesEncryptionProvider>();
services.AddTransient<IHashProvider, ktsu.Common.Sha256HashProvider>();
services.AddTransient<IObfuscationProvider, ktsu.Common.Base64ObfuscationProvider>();
services.AddTransient<ISerializationProvider, ktsu.Common.JsonSerializationProvider>();
services.AddTransient<IFileSystemProvider, ktsu.Common.FileSystemProvider>();
using IServiceProvider provider = services.BuildServiceProvider();
ICompressionProvider compressionProvider = provider.GetRequiredService<ICompressionProvider>();
IEncryptionProvider encryptionProvider = provider.GetRequiredService<IEncryptionProvider>();
IHashProvider hashProvider = provider.GetRequiredService<IHashProvider>();All interfaces follow a consistent pattern:
- Core methods: Zero-allocation
Try*methods that work withSpan<byte>andStreamparameters - Convenience methods: Allocating methods that call the Try* methods and handle buffer management
- Async support:
Task-based async versions of all operations withCancellationTokensupport - String overloads: UTF8-encoded string variants for convenience
Here's how to implement a custom MD5 hash provider:
using System.Security.Cryptography;
using ktsu.Abstractions;
public sealed class MyMD5HashProvider : IHashProvider
{
public int HashLengthBytes => 16; // MD5 produces 128-bit (16-byte) hashes
// Zero-allocation implementation
public bool TryHash(ReadOnlySpan<byte> data, Span<byte> destination)
{
if (destination.Length < HashLengthBytes)
{
return false;
}
using var md5 = MD5.Create();
byte[] hashBytes = md5.ComputeHash(data.ToArray());
hashBytes.AsSpan().CopyTo(destination);
return true;
}
// Stream implementation
public bool TryHash(Stream data, Span<byte> destination)
{
if (destination.Length < HashLengthBytes)
{
return false;
}
using var md5 = MD5.Create();
byte[] hashBytes = md5.ComputeHash(data);
hashBytes.AsSpan().CopyTo(destination);
return true;
}
// All other methods (Hash(), HashAsync(), etc.) are provided by default implementations
}using System.Text;
using ktsu.Abstractions;
using Microsoft.Extensions.DependencyInjection;
IServiceCollection services = new ServiceCollection();
services.AddTransient<IHashProvider, MyMD5HashProvider>();
using IServiceProvider provider = services.BuildServiceProvider();
IHashProvider hashProvider = provider.GetRequiredService<IHashProvider>();
// Using the convenience method (allocates and manages buffer)
byte[] inputData = Encoding.UTF8.GetBytes("Hello, World!");
byte[] hash = hashProvider.Hash(inputData);
// Using string convenience method
string textHash = Convert.ToHexString(hashProvider.Hash("Hello, World!"));
// Using the zero-allocation Try method
Span<byte> hashBuffer = stackalloc byte[hashProvider.HashLengthBytes];
if (hashProvider.TryHash(inputData, hashBuffer))
{
string result = Convert.ToHexString(hashBuffer);
}
// Async usage
byte[] asyncHash = await hashProvider.HashAsync(inputData);- Core methods support zero-allocation and streaming implementations: The fundamental operations use
Try*methods that work with caller-providedSpan<byte>orStreamdestinations, returning boolean success indicators. - Default implementations provide convenience: Interfaces include default implementations for allocating methods (
Hash(),Compress(), etc.) that handle buffer management and forward to the Try* methods. - Comprehensive async support: All operations have async variants with proper
CancellationTokensupport. - String convenience methods: UTF8-encoded string overloads are provided where appropriate for developer convenience.
- Minimal implementation burden: Implementers only need to provide the core Try* methods; all other functionality is inherited through default interface implementations.
- Obfuscation in
IObfuscationProvideris not cryptography. Use it only for non-security scenarios (e.g., casual hiding). For confidentiality and integrity, use strong, vetted cryptography viaIEncryptionProviderimplementations. - Implementations of
IEncryptionProvidershould rely on proven libraries (e.g., .NET BCL crypto, libsodium bindings) and follow best practices (AEAD modes, random IVs/nonces, key management).
- Provider implementations should be stateless or internally synchronized and safe to register as singletons in DI.
- If an implementation maintains internal mutable state, document the concurrency model and recommended lifetime.
- Consistency: A single, predictable surface across implementations
- Testability: Swap implementations and mock easily, especially for filesystem
- Separation of concerns: Keep app code free of vendor-specific details
- Fork the repo and create a feature branch
- Implement or refine providers/analyzers and add tests
- Open a pull request
Licensed under the MIT License. See LICENSE.md for details.