Add protected memory sample

This commit is contained in:
paragon
2026-05-27 19:41:53 -04:00
parent 792c254a3c
commit a687110703
@@ -0,0 +1,90 @@
using TriunniaLabs.Arch.Microservice;
using TriunniaLabs.Memory.Protected;
namespace TriunniaLabs.Arch.Sample.Server
{
/// <summary>
/// A controller that shows how to work with the Protected Memory system.
/// </summary>
public class ProtectedMemorySampleController : ArchControllerBase
{
// Services
private readonly IProtectorFactory _protectorFactory;
private readonly IProtector<string> _stringProtector;
/// <summary>
/// Constructor.
/// </summary>
/// <param name="microserviceContext">Reference to the microservice context.</param>
/// <param name="protectorFactory">Reference to the protector factory.</param>
/// <param name="stringProtector">Reference to the string protector.</param>
public ProtectedMemorySampleController(IMicroserviceContext microserviceContext,
IProtectorFactory protectorFactory,
[FromKeyedServices("MyProtectorServiceKey")] IProtector<string> stringProtector)
: base(microserviceContext)
{
_stringProtector = stringProtector ?? throw new ArgumentNullException(nameof(stringProtector));
_protectorFactory = protectorFactory ?? throw new ArgumentNullException(nameof(protectorFactory));
}
/// <summary>
/// A sample method that shows how to work with the Protected Memory system.
/// </summary>
internal async Task SampleAsync()
{
// In Arch, all data is encrypted in memory via the Protected<T> type. This encryption extends to the database and data transfer objects.
var myString = "My String Value";
var myProtectedString = new Protected<string>(myString);
// The hash of a protected type's value is available for equality checking without exposing the encrypted value
var hash = myProtectedString.Hash;
// Decrypt the protected type to get its value
var value = myProtectedString.GetDecryptedValue(); // "My String Value"
// Or decrypt just enough to get the bytes (from the byte array converter) without restoring the actual value.
var bytes = myProtectedString.GetDecryptedValueAsBytes();
// The protected type can be serialized just by calling ToString(), and this is what is used in appsettings.json or in the database.
// The serialized string is completely encrypted. It cannot be decrypted without a matching configuration.
var serializedString = myProtectedString.ToString();
// The static FromEncrypted method can be used to deserialize
myProtectedString = Protected<string>.FromEncrypted(serializedString);
// Custom protections can be specified as well. This specific arrangement is called Standard Protection.
// It is the default that is used when no other algorithms are specified.
var byteArrayConverter = MessagePackByteArrayConverter<string>.Instance;
var sha256HashAlgorithm = Sha256HashAlgorithm.Instance;
var aesEncryption = AesHashEncryptionAlgorithm.Instance;
var stringConverter = Base64StringConverter.Instance;
myProtectedString = new Protected<string>(myString, byteArrayConverter, sha256HashAlgorithm, [aesEncryption], stringConverter);
// Use Protectors to protect values with pre-defined custom configurations
var protector = _protectorFactory.CreateProtector<string>(MessagePackByteArrayConverter<string>.ServiceKey,
Sha256HashAlgorithm.ServiceKey, [AesEncryptionAlgorithm.ServiceKey],
Base64StringConverter.ServiceKey);
// Protect the value using the protector
myProtectedString = protector.Protect(myString);
// Protectors are also used to receive serialized data
myProtectedString = protector.Receive(serializedString);
myProtectedString = _stringProtector.Receive(serializedString); // They can also be injected
}
private class MyProtectedSample
{
/// <summary>
/// Protector definitions are automatically scanned by the library and added to the service container.
/// If an algorithm or converter isn't specified, the default is used.
/// </summary>
[ByteArrayConverter<string>("MessagePackByteArrayConverter<string>.ServiceKey")]
[HashAlgorithm(HmacSha512HashAlgorithm.ServiceKey)]
[EncryptionAlgorithm(AesEncryptionAlgorithm.ServiceKey, Order = 1)]
[StringConverter(Base64StringConverter.ServiceKey)]
[Protector("MyProtectorServiceKey")] // Identifies the protector in the service collection
public string Value { get; set; } = "";
}
}
}