
Encrypt and Decrypt using ASP.NET Core Data Protection in ASP.NET WEB API
Web API
22 Articles
Table of Contents
What we gonna do?
In ASP.NET Core, Data Protection is a built-in API for handling encryption and decryption of sensitive data like authentication tokens, cookies, and custom application secrets. While Windows DPAPI is often used during development on Windows, it's not always suitable for production, especially in cross-platform environments. This is where ASP.NET Core Data Protection comes in.
Why we gonna do?
The main reason to use ASP.NET Core Data Protection over Windows DPAPI in production is its cross-platform support . DPAPI is tied to Windows and depends on user or machine-specific encryption, which doesn't scale well for containerized apps, Linux servers, or distributed environments. In contrast, ASP.NET Core's solution allows:
- Key sharing across multiple app instances
- Custom key storage and protection strategies
- Full control over key lifecycle and rotation
How we gonna do?
First, we need to implement a custom encryption class using the IProtection interface. This interface requires us to provide Encrypt and Decrypt methods.
To begin, install the necessary NuGet packages:
- Microsoft.AspNetCore.DataProtection
- Microsoft.Extensions.DependencyInjection
Inside our class:
- Inject IDataProtectionProvider via the constructor
- Create an IDataProtector using the CreateProtector("purpose") method
- Use _protector.Protect(text) to encrypt and _protector.Unprotect(encryptedText) to decrypt
using Microsoft.AspNetCore.DataProtection;
using System;
public class DataProtectionEncryption : IProtection
{
private readonly IDataProtector _protector;
public DataProtectionEncryption(IDataProtectionProvider provider)
{
ArgumentException.ThrowIfNullOrEmpty(provider, nameof(provider));
// You can use any string to represent the purpose of the encryption
_protector = provider.CreateProtector("ILoveDotNet.DataProtection.Sample");
}
public string Encrypt(string plainText)
{
ArgumentException.ThrowIfNullOrWhiteSpace(plainText, nameof(plainText));
return _protector.Protect(plainText);
}
public string Decrypt(string cipherText)
{
ArgumentException.ThrowIfNullOrWhiteSpace(cipherText, nameof(cipherText));
try
{
return _protector.Unprotect(cipherText);
}
catch
{
// Log or handle the exception as necessary
return string.Empty;
}
}
}
One thing to note is that this method creates and stores a physical encryption key on disk (by default). While the framework does offer protection mechanisms, you should still take steps to secure and manage your key ring, especially in production.
Here's an outline of how it's typically used in a console app:
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.DataProtection;
using System;
class Program
{
static void Main(string[] args)
{
// Setup DI container
var services = new ServiceCollection();
services.AddDataProtection();
services.AddSingleton<IProtection, DataProtectionEncryption>();
var serviceProvider = services.BuildServiceProvider();
// Resolve encryption service
var encryption = serviceProvider.GetRequiredService<IProtection>();
// Encrypt and decrypt sample text
string secret = "ilovedotnet";
string encrypted = encryption.Encrypt(secret);
string decrypted = encryption.Decrypt(encrypted);
Console.WriteLine($"Original: {secret}");
Console.WriteLine($"Encrypted: {encrypted}");
Console.WriteLine($"Decrypted: {decrypted}");
}
}
Additionally, based on the environment (development or production), you can configure different configuration providers and encryption methods. For instance:
- Development: Secrets stored in appsettings , encrypted with ASP.NET Core Data Protection
- Production: Secrets stored in Key Vault and encrypted with ASP.NET Core Data Protection
Summary
ASP.NET Core Data Protection provides a powerful, cross-platform way to handle encryption in both development and production environments. While Windows DPAPI works well for local windows development, Data Protection gives you flexibility and control in modern hosting environments like containers and Linux. Thanks to its integration with dependency injection and configuration providers, it's easy to swap out encryption strategies based on environment, ensuring your app stays secure and scalable.