pvWay.Crypto.nc6
2.0.0
dotnet add package pvWay.Crypto.nc6 --version 2.0.0
NuGet\Install-Package pvWay.Crypto.nc6 -Version 2.0.0
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="pvWay.Crypto.nc6" Version="2.0.0" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add pvWay.Crypto.nc6 --version 2.0.0
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
#r "nuget: pvWay.Crypto.nc6, 2.0.0"
#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.
// Install pvWay.Crypto.nc6 as a Cake Addin #addin nuget:?package=pvWay.Crypto.nc6&version=2.0.0 // Install pvWay.Crypto.nc6 as a Cake Tool #tool nuget:?package=pvWay.Crypto.nc6&version=2.0.0
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
Crypto Nc6
Tiny utility encrypting/decrypting texts/objects to/from base64 strings
Interfaces
ICrypto
namespace pvWay.Crypto.nc6
{
public interface ICrypto: IAsyncDisposable, IDisposable
{
Task<string> EncryptStringAsync(string text);
Task<string> EncryptObjectAsync<T>(T data) where T: class;
Task<string> EncryptEphemeralStringAsync(
string text, TimeSpan? validity = null);
Task<string> EncryptEphemeralObjectAsync<T>(
T data, TimeSpan? validity = null)
where T : class;
Task<string> DecryptStringAsync(string base64Str);
/// <summary>
/// Tries to decrypt the payload
/// </summary>
/// <param name="base64Str">the encrypted payload</param>
/// <typeparam name="T">type of underlying object</typeparam>
/// <returns></returns>
Task<T> DecryptObjectAsync<T>(string base64Str) where T: class;
/// <summary>
/// Tries to decrypt the payload to primitive
/// </summary>
/// <param name="base64Str">the encrypted payload</param>
/// <returns>null if the payload has expired</returns>
Task<string?> DecryptEphemeralStringAsync(string base64Str);
/// <summary>
/// Tries to decrypt the payload to primitive
/// </summary>
/// <param name="base64Str">the encrypted payload</param>
/// <returns>null if the payload has expired</returns>
Task<T?> DecryptEphemeralObjectAsync<T>(string base64Str) where T : class;
}
}
Provisioning
You can use the AddPvWayCrypto ServiceCollection extension for provisioning the service
There are two overloads.
- using the IConfiguration config param
- using explicit params
...
/// <summary>
/// Provisions the Crypto Service
/// </summary>
/// <param name="services">IServiceCollection (this is an extension method)</param>
/// <param name="config">
/// Should contain the following keys: Key, InitializationVector, DefaultValidity, and ValidityUnit.
/// ValidityUnit can be 'second', 'minute', 'hour' or 'day' (plural words are supported as well)
/// </param>
/// <param name="lifetime">By default this will be Transient</param>
/// <exception cref="PvWayCryptoException"></exception>
public static void AddPvWayCrypto(
this IServiceCollection services,
IConfiguration config,
ServiceLifetime lifetime = ServiceLifetime.Transient)
{
var key = config["Key"]!;
var initializationVector = config["InitializationVector"]!;
var validityStr = config["DefaultValidity"]!;
var n = Convert.ToInt32(validityStr);
var validityUnit = config["ValidityUnit"]!.ToLower();
TimeSpan defaultValidity;
switch (validityUnit)
{
case "second":
case "seconds":
defaultValidity = TimeSpan.FromSeconds(n);
break;
case "minute":
case "minutes":
defaultValidity = TimeSpan.FromMinutes(n);
break;
case "hour":
case "hours":
defaultValidity = TimeSpan.FromHours(n);
break;
case "day":
case "days":
defaultValidity = TimeSpan.FromDays(n);
break;
default:
throw new PvWayCryptoException("Invalid validity unit");
}
var sd = new ServiceDescriptor(
typeof(ICrypto),
_ => new Crypto(
key, initializationVector, defaultValidity), lifetime);
services.TryAdd(sd);
}
/// <summary>
/// Provisions the Crypto Service
/// </summary>
/// <param name="services">this is an extension method</param>
/// <param name="key">should be exactly 32 characters long</param>
/// <param name="initializationVector">should be exactly 16 characters long</param>
/// <param name="defaultValidity">default validity for ephemeral encryption</param>
/// <param name="lifetime">Defaults to Transient</param>
public static void AddPvWayCrypto(
this IServiceCollection services,
string key, string initializationVector,
TimeSpan defaultValidity,
ServiceLifetime lifetime = ServiceLifetime.Transient)
{
var sd = new ServiceDescriptor(
typeof(ICrypto),
_ => new Crypto(
key, initializationVector, defaultValidity), lifetime);
services.TryAdd(sd);
}
...
Factory
There is also a static factory
...
/// <summary>
/// Factors the Crypto service. Provide a 32 char key and a 16 char iv
/// </summary>
/// <param name="key">should be exactly 32 characters long</param>
/// <param name="initializationVector">should be exactly 16 characters long</param>
/// <param name="defaultValidity">default validity for ephemeral encryption</param>
public static ICrypto Create(
string key, string initializationVector,
TimeSpan defaultValidity)
{
return new Crypto(key, initializationVector, defaultValidity);
}
...
Usage
See here after a short Console that use the nuGet
using CryptoNc6Console;
using pvWay.Crypto.nc6;
Console.WriteLine("Hello, pvWay Crypto nc6");
Console.WriteLine();
// the length of the key string needs to be exactly 32
const string keyString = "123456789 123456789 123456789 12";
// the length of the init vector string needs to be exactly 16
const string initializationVectorString = "0123456789ABCDEF";
// Factory the crypto object
// note that we mention 10 minutes as the default validity
// time for ephemeral objects or strings
var crypto = PvWayCryptoDi.Create(
keyString,
initializationVectorString,
TimeSpan.FromMinutes(10));
Console.WriteLine("Encrypting the word 'test'");
var b64 = await crypto.EncryptStringAsync("test");
Console.WriteLine($"The word 'test' was encrypted as '{b64}'");
Console.WriteLine("Retrieving the 'test' from the encrypted payload");
var text = await crypto.DecryptStringAsync(b64);
Console.WriteLine($"Got '{text}' back");
Console.WriteLine();
var mc = new MyClass
{
TheHeader = "Header",
TheBody = "Body",
TheFooter = "Footer"
};
Console.WriteLine("Encrypting the object MyClass(Header, Body, Footer)");
b64 = await crypto.EncryptObjectAsync(mc);
Console.WriteLine($"The MyClass object was encrypted as {b64}");
Console.WriteLine("Retrieving the MyClass object from the payload");
var mcBack = await crypto.DecryptObjectAsync<MyClass>(b64);
Console.WriteLine($"Got MyClass back '{mcBack.TheHeader} - {mcBack.TheBody} - {mcBack.TheFooter}'");
Console.WriteLine();
Console.WriteLine("Encrypting the object MyClass(Header, Body, Footer)");
Console.WriteLine("Payload will only stay valid for 1 second");
b64 = await crypto.EncryptEphemeralObjectAsync(
mc, TimeSpan.FromSeconds(1));
mcBack = await crypto.DecryptEphemeralObjectAsync<MyClass>(b64);
Console.WriteLine("Retrieving the MyClass object from the payload");
Console.WriteLine($"Got MyClass back '{mcBack!.TheHeader} - {mcBack.TheBody} - {mcBack.TheFooter}'");
Console.WriteLine("Ephemeral payload is still valid");
Console.WriteLine("Sleeping a while");
Thread.Sleep(1000);
Console.WriteLine("Retrieving the MyClass object from the payload");
mcBack = await crypto.DecryptEphemeralObjectAsync<MyClass>(b64);
if (mcBack != null)
throw new PvWayCryptoException("Payload should have expired");
Console.WriteLine("The object payload has expired as expected");
Console.WriteLine();
Console.WriteLine("Encrypting the ephemeral text 'Hello butterfly' " +
"that will only stay alive for 1 second");
b64 = await crypto.EncryptEphemeralStringAsync("Hello butterfly",
TimeSpan.FromSeconds(1));
Console.WriteLine("Retrieving the ephemeral text");
text = await crypto.DecryptEphemeralStringAsync(b64);
Console.WriteLine($"The text '{text}' is still valid");
Console.WriteLine("Sleeping a while");
Thread.Sleep(1000);
text = await crypto.DecryptEphemeralStringAsync(b64);
if (text != null)
throw new PvWayCryptoException("Payload should have expired");
Console.WriteLine("The text payload has expired as expected");
Happy coding
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. 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. |
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
-
net6.0
- Microsoft.Extensions.Configuration.Abstractions (>= 6.0.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 6.0.0)
- Newtonsoft.Json (>= 13.0.3)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Breaking changes. Service made injectable