Part - 3 Encryption and Decryption in ASP - NET Core Web API
Part - 3 Encryption and Decryption in ASP - NET Core Web API
What is Encryption?
Encryption is the process of converting plain text or other forms of readable data into an unreadable
format called ciphertext. This prevents unauthorized access, ensuring that only those with the correct
decryption key can access the original data. In ASP.NET Core Web API, we encrypt the sensitive data
before sending it over the network to the clients.
What is Decryption?
Decryption is the process of converting encrypted data back into its original form (plaintext). This is
typically done using a key that was used during the encryption process. In ASP.NET Core Web API,
decryption is used when data is received in an encrypted form and needs to be processed or
displayed.
First create a new ASP.NET Core Web API Project named AESServerAPP. Then create a folder
named Models within the Project root directory.
namespace AESServerAPP.Models
{
public class AesEncryptionService
{
// Method to encrypt a plaintext string using AES encryption with a client-specific key and
IV.
public static string EncryptString(string clientId, string plainText)
{
// Retrieve the AES key and IV using the clientId from a key management service.
var client = KeyManagementService.GetKeyAndIV(clientId);
// Method to decrypt a ciphertext string using AES decryption with a client-specific key
and IV.
public static string DecryptString(string clientId, string cipherText)
{
// Retrieve the AES key and IV using the clientId from a key management service.
var client = KeyManagementService.GetKeyAndIV(clientId);
EncryptString Method:
This method is used to encrypt a given plaintext string using the Advanced Encryption Standard (AES)
algorithm. It uses a client-specific key and initialization vector (IV) for encryption, which are obtained
from a key management service using the client's ID. The method ensures secure encryption of
sensitive data, returning the encrypted data as a base64 encoded string, suitable for safe
transmission.
DecryptString Method:
This method is used to decrypt a previously encrypted base64 encoded string (ciphertext) using the
AES algorithm. Similar to the encryption process, it retrieves the client-specific AES key and IV. This
method allows the recovery of the original plaintext from the ciphertext, assuming that the correct key
and IV are used, which are important for maintaining the integrity and confidentiality of the data.
EmployeesController:
Next, create the EmployeesController to perform the database CRUD operations using the Employee
model. Here, the action method will receive the input data in encrypted format and also the action
method returns the response data in encrypted format. So, create an API Empty Controller named
EmployeesController within the Controllers folder and then copy and paste the following code. The
following code is self-explained, so please go through the comment lines.
using AESServerAPP.Models;
using Microsoft.AspNetCore.Mvc;
using System.Text.Json;
namespace AESServerAPP.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class EmployeesController : ControllerBase
{
// Static list to act as our database.
private static List<Employee> _employees = new List<Employee>
{
new Employee { Id = 1, Name = "Alice Smith", Salary = 75000 },
new Employee { Id = 2, Name = "Bob Johnson", Salary = 60000 },
new Employee { Id = 3, Name = "Carol White", Salary = 55000 }
};
AESClientAPP
Next, we need to create the Client APP consuming the service with AES encryption and decryption.
For this, we are going to create a Console Application. So, create a Console Application named
AESClientAPP. Once you create the Console Application, modify the Program class code as follows:
using System.Security.Cryptography;
using System.Text.Json;
using System.Text;
namespace AESClientAPP
{
public class Program
{
// Base URL of the API server.
private static readonly string BaseUrl = "https://localhost:7029/api/Employees"; // Base
API URL
private static readonly string ClientId = "Client1"; // Client identifier for AES encryption
private static readonly string Key =
"gi1D2eDd8Tg565ZbfRWc00j9xKtBka4ZHu0Sen+Drgc="; // Base64-encoded AES key
private static readonly string IV = "Qb4nTgWS7UBo2YU7G/gJCg=="; // Base64-encoded
AES IV
try
{
// Fetching all employees data.
Console.WriteLine("Fetching all employees...");
HttpRequestMessage getAllRequest = new HttpRequestMessage(HttpMethod.Get,
BaseUrl);
HttpResponseMessage getAllResponse = await client.SendAsync(getAllRequest);
string encryptedGetAllResponse = await
getAllResponse.Content.ReadAsStringAsync();
string decryptedGetAllResponse = DecryptString(encryptedGetAllResponse);
Console.WriteLine("Decrypted response (All Employees):");
Console.WriteLine(decryptedGetAllResponse);
List<Employee> employees =
JsonSerializer.Deserialize<List<Employee>>(decryptedGetAllResponse);
foreach (var emp in employees)
{
Console.WriteLine($"Employee Details - ID: {emp.Id}, Name: {emp.Name},
Salary: {emp.Salary}");
}
// Deleting an employee.
Console.WriteLine("\nDeleting employee with ID 2...");
HttpRequestMessage deleteRequest = new
HttpRequestMessage(HttpMethod.Delete, $"{BaseUrl}/2");
HttpResponseMessage deleteResponse = await client.SendAsync(deleteRequest);
Console.WriteLine(deleteResponse.IsSuccessStatusCode ? "Deletion
successful" : "Deletion failed");
}
catch (Exception ex)
{
// Handle and report any errors that occur during the HTTP requests.
Console.WriteLine($"Error: {ex.Message}");
}
}
// Encrypts a plaintext string using AES and returns the base64-encoded cipher text.
private static string EncryptString(string plainText)
{
// Convert the base64-encoded key into a byte array.
byte[] _key = Convert.FromBase64String(Key);
// Decrypts a base64-encoded cipher text string using AES and returns the plaintext.
private static string DecryptString(string cipherText)
{
// Convert the base64-encoded key into a byte array.
byte[] _key = Convert.FromBase64String(Key);
// Create a decryptor object to transform the encrypted data back into plain text.
var decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
// Definition of the Employee class used to serialize and deserialize employee data.
public class Employee
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Salary { get; set; }
}
}
}
Now, first run the ASP.NET Core Web API Project and then run the Console Application and you
should see the output as expected as shown in the below image.
Key Generator Console Application:
Now, create a new Console Application for generating the Valid Key and IV. So, create a Dot Net
Console Application named KeyGeneratorService. Then modify the Program class as follows. The
following code is self-explained, so please go through the comment line for a better understanding.
using System.Security.Cryptography;
namespace KeyGeneratorService
{
// Main class of the KeyGeneratorService program
public class Program
{
// Entry point of the console application
static void Main(string[] args)
{
// Call the method to generate AES key and IV
GenerateAesKeyAndIV();
// Wait for a key press to prevent the console from closing immediately
Console.ReadKey();
}
// Convert the generated key to a base64 string for easier readability and storage
string key = Convert.ToBase64String(aesAlg.Key);
// Convert the generated IV to a base64 string for easier readability and storage
string iv = Convert.ToBase64String(aesAlg.IV);
MemoryStream
MemoryStream is a stream that stores data in memory as bytes. It doesn't require a backing store like
a file, making it fast and flexible for scenarios where temporary storage is needed.
Usage in Encryption: In EncryptString method, a MemoryStream instance is used to hold
the encrypted bytes as they are processed. This is convenient because we can dynamically
write data as it is encrypted and then easily convert the entire content to a byte array or
base64 string afterwards.
Usage in Decryption: In the DecryptString method, MemoryStream is initialized with the byte
array that represents the encrypted data (converted from base64). This allows the
CryptoStream to read from this buffer directly to perform decryption.
CryptoStream
CryptoStream provides a way to link data streams to cryptographic transformations. It can be used for
both encrypting and decrypting data, depending on how it is set up.
Usage in Encryption: In the EncryptString method, the CryptoStream is linked to the
MemoryStream and set up with an encryptor object (aesAlg.CreateEncryptor()). As data is
written to this stream, it is automatically encrypted using the specified AES key and IV, and
then passed to the memory stream.
Usage in Decryption: In the DecryptString method, CryptoStream is set up with a decryptor
object (aesAlg.CreateDecryptor()). It reads from a MemoryStream containing the encrypted
data and decrypts it as the data is being read.
StreamWriter:
StreamWriter is used to write characters to a stream in a specific encoding (by default, UTF-8). In the
EncryptString method, StreamWriter is used to write the plaintext string to the CryptoStream. This
converts the plaintext string into a byte stream in a specified encoding and passes it through the
encryption process implemented in CryptoStream.
StreamReader:
Conversely, StreamReader is used to read characters from a byte stream into a string. In the
DecryptString method, StreamReader reads the decrypted byte stream from the CryptoStream and
converts it back into a readable string (the original plaintext).