Daily Knowledge Drop
.NET has built in methods to protect and unprotected
sensitive data.
These methods are typically used to protect sensitive data, but could be used to protect any data. It could also be used to expose information for a given period of time only, after which trying unprotecting the data will not work.
Configuration
There are effectively three steps to using the data protection apis:
- Create the
protector
from a data protection provider - Invoke the
Protect
method to protect the data specified - Invoke the
Unprotect
method to convert the specified protected value to plain text
In the startup of the application, the protector is configured as follows:
// register base data protection
// with DI container
builder.Services
.AddDataProtection()
.SetDefaultKeyLifetime(TimeSpan.FromDays(7));
// register the protector with DI
builder.Services
.AddTransient<ITimeLimitedDataProtector>(sp =>
{
// specify where the provider key information will be stored
IDataProtectionProvider? provider = DataProtectionProvider
.Create(new DirectoryInfo(@"secrets"));
// specify the purpose string for the creator
IDataProtector? protector = provider
.CreateProtector("customerdata");
return protector.ToTimeLimitedDataProtector();
});
Some notes on the above:
- The key information is stored in a
secrets
folder on the host machine. As such, the key information is only available to that one machine. If multiple machines need to access the key information, there are other storage providers available (Azure KeyVault, DbContext) - The protector is created with a specific purpose,
customerdata
above. A value protected using a specific purpose, cannot be unprotected using a different purpose value.
Protect
To protect a string, the Protect
method is called. Below, an endpoint has been defined which has the ITimeLimitedDataProtector protector implementation (configured in the previous step) injected:
// get the value to protect from the route
app.MapGet("/protect/{protectValue}", (
[FromRoute]string protectValue,
ITimeLimitedDataProtector protector) =>
{
// return the protected value
return protector.Protect(protectValue);
});
Invoking the endpoint /protect/abc123
results in the following protected value being returned:
CfDJ8BdtcMmju6ZKiKJtRHvTt2BidaZbPEirTP_KEi4-_2xVBYbs58hqVxWGQmTQBjQaO_tXTiFRAxGUPGSqXkvlfIzhd80r3AavXi0m3PiCXYfuaRhmnrzCXk6apOIqXOCvHA
Unprotect
Unprotecting is as simple as protecting a value - the Unprotect
method is called, with the previously protected value supplied:
app.MapGet("/unprotect/{unprotectValue}", (
[FromRoute] string unprotectValue,
ITimeLimitedDataProtector protector) =>
{
return protector.Unprotect(unprotectValue);
});
Invoking the endpoint /unprotect/CfDJ8BdtcMmju6ZKiKJtRHvTt2BidaZbPEirTP_KEi4-_2xVBYbs58hqVxWGQmTQBjQaO_tXTiFRAxGUPGSqXkvlfIzhd80r3AavXi0m3PiCXYfuaRhmnrzCXk6apOIqXOCvHA
results in the following output:
abc123
Notes
When needing to protect sensitive data (for example, authentication cookie or bearer token) this set of classes and functionality provides an easy, simple and effective way to protect the data.
References
Piotr Penza
ASP.NET Core Data Protection Overview
Configure ASP.NET Core Data Protection
Daily Drop 188: 24-10-2022
At the start of 2022 I set myself the goal of learning one new coding related piece of knowledge a day.
It could be anything - some.NET / C# functionality I wasn't aware of, a design practice, a cool new coding technique, or just something I find interesting. It could be something I knew at one point but had forgotten, or something completely new, which I may or may never actually use.
The Daily Drop is a record of these pieces of knowledge - writing about and summarizing them helps re-enforce the information for myself, as well as potentially helps others learn something new as well.On This Page