Explicitly-invoked cryptography toolkit for .NET developers — AES-GCM and RSA encryption, RSA signing, HMAC and SHA hashing, and Base64/Base64URL helpers, all string-in/string-out.
[!NOTE] Looking for transparent EF Core column encryption instead — where an attribute on an entity property does the work automatically on save/load? That’s a different package: DKNet.EfCore.Encryption. Use
DKNet.Svc.Encryptionwhen you want to callEncrypt/Decryptyourself at the point you call it; useDKNet.EfCore.Encryptionwhen you want a column encrypted transparently, without the code that reads and writes the entity knowing. The two packages don’t share implementation.
IAesGcmEncryption handles nonce generation, tag handling, and
packaging into a single Base64 string, so call sites never assemble a cipher envelope by hand.CryptographicOperations.FixedTimeEquals on every Verify* call and key comparison — the choices that are easy to
get wrong are already made.varchar column with no byte-array plumbing.Use a .NET 10 console project. Install the package, then replace Program.cs with the example.
dotnet new console -f net10.0 -n EncDemo
cd EncDemo
dotnet add package DKNet.Svc.Encryption
dotnet add package Microsoft.Extensions.DependencyInjection
using DKNet.Svc.Encryption;
using DKNet.Svc.Encryption.Ciphers;
using Microsoft.Extensions.DependencyInjection;
var services = new ServiceCollection();
services.AddEncryptionServices(); // IShaHashing, IHmacHashing
services.AddAesGcmEncryption(new AesGcmEncryption().Key); // a throwaway demo key
using var provider = services.BuildServiceProvider();
var aesGcm = provider.GetRequiredService<IAesGcmEncryption>();
var package = aesGcm.EncryptString("4111-1111-1111-1111");
var plain = aesGcm.DecryptString(package);
Console.WriteLine(plain); // 4111-1111-1111-1111
Run with dotnet run. In a real application, source the key passed to AddAesGcmEncryption from configuration or a
key vault — never a freshly generated one.
Each registration call owns exactly one outcome: AddEncryptionServices always registers the two keyless hashing
services; AddAesGcmEncryption and AddRsaEncryption each register one singleton cipher built from the key you
pass in. Base64StringExtensions is a static extension class, never registered with DI. All three registration
methods skip registration when the service type already exists, so calling any of them twice is a no-op — the
first call’s key is the one the application keeps using.
EncryptString and DecryptString run against the instance’s own key — no key argument needed once resolved. The
diagram cannot show the per-call locking (AesGcmEncryption serializes Encrypt/Decrypt on the shared AesGcm
handle) or that a hand-built new AesGcmEncryption() generates its own random key instead of using the one
registered with DI. Each feature page below covers its own call path.
SaveAsync when the store itself must never see plaintext.