TPJ.Encrypt is a simple .NET 10 package for common encryption and secret-handling tasks.
It includes:
PasswordHasherfor one-way password hashing usingArgon2idEncryptAesfor two-way AES encryption and decryptionAzureKeyVaulthelpers for reading secrets and connection strings from Azure Key Vault
Use this package when you need to:
- hash passwords securely before storing them
- verify passwords during login
- encrypt and decrypt text using AES
- use authenticated encryption with
AES-GCMfor new implementations - read secrets from Azure Key Vault in APIs or other .NET applications
Use PasswordHasher for passwords and other values that should not be decrypted later.
- hashes with
Argon2id - stores version and algorithm settings in metadata
- verifies passwords safely
- can tell you when an old hash should be rehashed
Use EncryptAes when you need to encrypt data and decrypt it later.
AES-CBCmethods for key/IV based encryptionAES-GCMmethods for authenticated encryption- sync and async methods
- helpers for generating keys, IVs, and nonces
For new code, prefer the authenticated
AES-GCMmethods such asEncryptWithAuthenticationandDecryptWithAuthentication.
Use AzureKeyVault when your app needs to:
- retrieve secrets from Azure Key Vault
- replace a password placeholder in a connection string
- register the Azure Key Vault provider for SQL Always Encrypted
dotnet add package TPJ.Encryptusing TPJ.Encrypt;
var (hash, metadata) = PasswordHasher.HashPassword("MySecurePassword123!");
Console.WriteLine($"Hash: {hash}");
Console.WriteLine($"Metadata: {metadata}");using TPJ.Encrypt;
var (hash, metadata) = PasswordHasher.HashPassword("MySecurePassword123!");
var isValid = PasswordHasher.VerifyPassword("MySecurePassword123!", hash, metadata);
var isInvalid = PasswordHasher.VerifyPassword("WrongPassword", hash, metadata);
Console.WriteLine(isValid); // True
Console.WriteLine(isInvalid); // Falseusing TPJ.Encrypt;
var (key, nonce) = EncryptAes.GenerateAesGcmKeyNonce();
var encrypted = EncryptAes.EncryptWithAuthentication("Hello world", key, nonce);
var decrypted = EncryptAes.DecryptWithAuthentication(encrypted, key);
Console.WriteLine(decrypted); // Hello worldusing TPJ.Encrypt;
var (keyBytes, nonceBytes) = EncryptAes.GenerateAesGcmKeyNonce();
var key = Convert.ToBase64String(keyBytes);
var nonce = Convert.ToBase64String(nonceBytes);
var encrypted = EncryptAes.EncryptWithAuthenticationToBase64("Secret message", key, nonce);
var decrypted = EncryptAes.DecryptWithAuthenticationFromBase64(encrypted, key);
Console.WriteLine(decrypted); // Secret messageThis example shows both password hashing and AES encryption in a simple console app.
using TPJ.Encrypt;
Console.WriteLine("TPJ.Encrypt console demo");
// Password hashing
var password = "MySecurePassword123!";
var (passwordHash, metadata) = PasswordHasher.HashPassword(password);
Console.WriteLine($"Password hash: {passwordHash}");
Console.WriteLine($"Password valid: {PasswordHasher.VerifyPassword(password, passwordHash, metadata)}");
// AES-GCM encryption
var (key, nonce) = EncryptAes.GenerateAesGcmKeyNonce();
var encryptedBytes = EncryptAes.EncryptWithAuthentication("Sensitive console data", key, nonce);
var decryptedText = EncryptAes.DecryptWithAuthentication(encryptedBytes, key);
Console.WriteLine($"Encrypted: {Convert.ToBase64String(encryptedBytes)}");
Console.WriteLine($"Decrypted: {decryptedText}");This example shows how to use the package in an ASP.NET Core minimal API.
using TPJ.Encrypt;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
var (key, nonce) = EncryptAes.GenerateAesGcmKeyNonce();
app.MapPost("/hash-password", (PasswordRequest request) =>
{
var (hash, metadata) = PasswordHasher.HashPassword(request.Value);
return Results.Ok(new { hash, metadata });
});
app.MapPost("/verify-password", (VerifyPasswordRequest request) =>
{
var isValid = PasswordHasher.VerifyPassword(request.Password, request.Hash, request.Metadata);
return Results.Ok(new { isValid });
});
app.MapPost("/encrypt", (TextRequest request) =>
{
var encrypted = EncryptAes.EncryptWithAuthentication(request.Value, key, nonce);
return Results.Ok(new { encrypted = Convert.ToBase64String(encrypted) });
});
app.MapPost("/decrypt", (EncryptedRequest request) =>
{
var encryptedBytes = Convert.FromBase64String(request.Value);
var decrypted = EncryptAes.DecryptWithAuthentication(encryptedBytes, key);
return Results.Ok(new { decrypted });
});
app.Run();
record PasswordRequest(string Value);
record VerifyPasswordRequest(string Password, string Hash, string Metadata);
record TextRequest(string Value);
record EncryptedRequest(string Value);POST /hash-password
{
"value": "MySecurePassword123!"
}POST /encrypt
{
"value": "Hello from the API"
}If you store secret names and credential settings in configuration, you can use AzureKeyVault to retrieve secrets.
using TPJ.Encrypt;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/db-connection", async (IConfiguration configuration) =>
{
var connectionString = await AzureKeyVault.GetConnectionStringAsync(configuration, "DefaultConnection");
return Results.Ok(new { connectionString });
});
app.Run();Example configuration structure:
{
"ConnectionStrings": {
"DefaultConnection": "Server=server-name;Database=my-db;User Id=my-user;Password=##Password##;"
},
"TPJ": {
"Encrypt": {
"Azure": {
"KeyVault": {
"Url": "https://your-keyvault-name.vault.azure.net/",
"Secrets": {
"DbPassword": "my-database-password-secret-name"
},
"EnvironmentVariables": {
"TenantId": "AZURE_TENANT_ID",
"ClientId": "AZURE_CLIENT_ID",
"ClientSecret": "AZURE_CLIENT_SECRET"
}
}
}
}
}
}- Use
PasswordHasherfor passwords, not reversible encryption. - Use
EncryptAeswhen you need to decrypt the data later. - Prefer
AES-GCMfor new development. - Store AES keys securely. Do not hard-code production secrets.
- Azure Key Vault support is optional and useful for APIs, services, and cloud-hosted apps.