Encryption and Decryption in ASP.NET Core Web API

Encryption and Decryption in ASP.NET Core Web API

In this article, I will discuss how to Implement AES Encryption and Decryption in ASP.NET Core Web API Application with an Example. Please read our previous article discussing how to Implement HMAC Authentication in an ASP.NET Core Web API Application with an Example. In ASP.NET Core Web API, Encryption and Decryption are used to protect sensitive data.

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 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.

Techniques for Encryption and Decryption in ASP.NET Core Web API:
  • Symmetric Encryption: In the case of Symmetric Encryption, it uses the same key for both encryption and decryption. For example, AES (Advanced Encryption Standard) and DES (Data Encryption Standard).
  • Asymmetric Encryption: Uses a pair of keys (public and private). The public key encrypts data, and the private key decrypts it. For example, RSA.
What is the Advanced Encryption Standard (AES) Algorithm?

The Advanced Encryption Standard (AES) is a symmetric key encryption algorithm used worldwide to secure data. The U.S. National Institute of Standards and Technology (NIST) established it as an encryption standard in 2001. AES protects sensitive information in both government and commercial sectors.

Working Flow of AES Algorithm :

AES uses the same key for encrypting and decrypting data, which means both the sender and the receiver must have access to the same secret key. Please have a look at the following diagram to understand the AES algorithm’s working flow.

Encryption and Decryption in ASP.NET Core Web API

Let us understand each term and working flow of the AES Algorithm:

  • Sender: The sender is the entity (can be a person, system, or device) that initiates the encryption process. The sender has plaintext that they wish to transmit to a receiver securely.
  • Plaintext: Plaintext refers to the original readable data or message that needs to be encrypted. It could be any sensitive data, such as passwords or personal information, that needs to be encrypted before being sent over the Internet. In the context of AES, the plaintext is processed in fixed-size blocks (typically 128 bits) during the encryption process.
  • Secret Key: The secret key is a parameter used in the AES algorithm to encrypt and decrypt messages. To maintain security, it must be known only to the sender and the receiver. The secret key should be securely stored and managed to maintain its confidentiality. In AES, the key can be 128, 192, or 256 bits long, depending on the level of security required.
  • Encryption Server: An encryption server is a dedicated server or service that performs the encryption process. In a typical setup, it receives plaintext and a secret key from the sender, encrypts the data using AES, and then sends the ciphertext to the intended receiver or makes it available for secure transmission.
  • Secure Channel: A secure channel is a method of communication that ensures the confidentiality and integrity of the data transmitted between sender and receiver. It is typically secured through cryptographic techniques and protocols to prevent unauthorized access and tampering during transmission.
  • Ciphertext: Ciphertext is the encrypted version of the plaintext produced by the AES algorithm that is unreadable without the appropriate decryption key. It is transmitted over the secure channel from the sender to the receiver to ensure that sensitive data cannot be read if intercepted.
  • Decryption Server: Similar to an encryption server, a decryption server is responsible for converting ciphertext back to plaintext using the appropriate secret key. It uses the same secret key that was used for encryption (in the case of AES, which is symmetric encryption) to reverse the encryption process.
  • Receiver: This is the entity that receives the encrypted data (ciphertext). The receiver is responsible for decrypting the ciphertext back into plaintext using the secret key.
Example to Understand AES Algorithm in ASP.NET Core Web API:

Let us understand how to implement Encryption and Decryption using the AES Algorithm to secure our services. We will create two applications: one ASP.NET Core Web API application that exposes the endpoints and another Console application that consumes the API Endpoints. But here, we need to transfer the data (both the Request Body and the Response Body) in ciphertext, i.e., in an encrypted format.

Creating Server Application:

Implementing AES encryption and decryption in an ASP.NET Core Web API involves several steps, including creating the encryption service, configuring API to use this service, and then applying the encryption and decryption methods where needed.

First, create a new ASP.NET Core Web API Project named AESServerAPP. Then, create a folder named Models within the Project root directory.

Define a Key Storage Service

Create a service to manage keys and IVs of the Clients. This service will be responsible for retrieving the correct key and IV based on the client ID. So, create a class file named KeyManagementService.cs and then copy and paste the following code. Here, we have hard-coded the client details, but you will get the same from the database in real-time.

namespace AESServerAPP.Models
{
    public class KeyManagementService
    {
        public static List<ClientKeyIV> listKeyIvs = new List<ClientKeyIV>()
        {
            new ClientKeyIV(){ClientId = "DefaultClient", Key = "Yyj9nVLtBLwPANTqZNFHrofcH/AbvJlaUbytoHT8Qd8=", IV="/X9EAc4vBALd31ye7N3L1g=="},
            new ClientKeyIV(){ClientId = "Client1", Key = "gi1D2eDd8Tg565ZbfRWc00j9xKtBka4ZHu0Sen+Drgc=", IV="Qb4nTgWS7UBo2YU7G/gJCg=="},
            new ClientKeyIV(){ClientId = "Client2", Key = "mPjeDLj4jq5AnX/0WeDXBewm05AIOqbV83MfNTWap7A=", IV="3Y/S5SC3qFNaSbfSKEKxxA=="},
            new ClientKeyIV(){ClientId = "Client3", Key = "J0N55pEAha+B0Oyggc4zWV1GE9iWiW/m7W5DuUo0W3M=", IV="8PiYfRaj4e5JumnpLh0FzA=="},
        };
         
        public static ClientKeyIV?  GetKeyAndIV(string clientId)
        {
            return listKeyIvs.FirstOrDefault(i => i.ClientId.ToLower() == clientId.ToLower());
        }
    }

    public class ClientKeyIV
    {
        public string ClientId { get; set; }
        public string Key { get; set; }
        public string IV { get; set; }
    }
}
Create a Service for AES Encryption and Decryption:

Next, we need to create a service to manage encryption and decryption using the AES algorithm. So, create a class file named AesEncryptionService.cs and then copy and paste the following code:

using System.Security.Cryptography;

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);

            // Throw an exception if no client configuration is found (invalid clientId).
            if (client == null)
                throw new Exception("Invalid Client Id");

            // Convert the base64-encoded key to a byte array.
            byte[] _key = Convert.FromBase64String(client.Key);

            // Convert the base64-encoded IV to a byte array.
            byte[] _iv = Convert.FromBase64String(client.IV);

            // Create a new instance of the AES algorithm.
            using (var aesAlg = Aes.Create())
            {
                // Set the key for the AES algorithm.
                aesAlg.Key = _key;
                // Set the IV for the AES algorithm.
                aesAlg.IV = _iv;

                // Create an encryptor from the AES instance to encrypt data.
                var encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
                // MemoryStream is used to hold the encrypted bytes.
                using (var msEncrypt = new MemoryStream())
                {
                    // CryptoStream for cryptographic transformation of data.
                    using (var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                    // StreamWriter to write the plaintext to the stream in a particular encoding.
                    using (var swEncrypt = new StreamWriter(csEncrypt))
                    {
                        // Write the plaintext to the crypto stream to perform encryption.
                        swEncrypt.Write(plainText);
                    }
                    // Convert the encrypted bytes from the memory stream to a base64 string.
                    return Convert.ToBase64String(msEncrypt.ToArray());
                }
            }
        }

        // 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);

            // Throw an exception if no client configuration is found (invalid clientId).
            if (client == null)
                throw new Exception("Invalid Client Id");

            // Convert the base64-encoded key to a byte array.
            byte[] _key = Convert.FromBase64String(client.Key);
            // Convert the base64-encoded IV to a byte array.
            byte[] _iv = Convert.FromBase64String(client.IV);

            // Convert the base64-encoded ciphertext into a byte array.
            var buffer = Convert.FromBase64String(cipherText);

            // Create a new instance of the AES algorithm.
            using (var aesAlg = Aes.Create())
            {
                // Set the key for the AES algorithm.
                aesAlg.Key = _key;
                // Set the IV for the AES algorithm.
                aesAlg.IV = _iv;

                // Create a decryptor from the AES instance to decrypt data.
                var decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
                // MemoryStream is used to read the encrypted bytes.
                using (var msDecrypt = new MemoryStream(buffer))
                {
                    // CryptoStream for cryptographic transformation of data.
                    using (var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                    // StreamReader to read the decrypted plaintext from the stream.
                    using (var srDecrypt = new StreamReader(csDecrypt))
                    {
                        // Read the decrypted text from the crypto stream and return it.
                        return srDecrypt.ReadToEnd();
                    }
                }
            }
        }
    }
}
EncryptString Method:

This method encrypts 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 decrypts 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 is important for maintaining the integrity and confidentiality of the data.

Creating Employee Model:

Next, we need to create the Employee model, which will hold the data in memory. So, within the Models folder, create a class file named Employee.cs and then copy and paste the following code:

namespace AESServerAPP.Models
{
    public class Employee
    {
        public int? Id { get; set; }
        public string Name { get; set; }
        public decimal Salary { get; set; }
    }
}
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 the action method will return 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 }
        };

        // Endpoint to get all employees, results are encrypted.
        [HttpGet]
        public ActionResult<IEnumerable<string>> GetEmployees()
        {
            // Extract 'ClientId' from request headers or use 'DefaultClient' if not present.
            var clientId = Request.Headers["ClientId"].FirstOrDefault() ?? "DefaultClient";
            // Serialize and encrypt the list of employees using AES.
            var encryptedEmployees = AesEncryptionService.EncryptString(clientId, JsonSerializer.Serialize(_employees));

            // Return the encrypted string as a successful result.
            return Ok(encryptedEmployees);
        }

        // Endpoint to get a single employee by ID, result is encrypted.
        [HttpGet("{id}")]
        public ActionResult<string> GetEmployee(int id)
        {
            // Extract 'ClientId' from request headers or use 'DefaultClient' if not present.
            var clientId = Request.Headers["ClientId"].FirstOrDefault() ?? "DefaultClient";
            // Find the employee by ID.
            var employee = _employees.FirstOrDefault(e => e.Id == id);
            if (employee == null)
            {
                return NotFound();
            }
            // Serialize and encrypt the employee's data.
            var encryptedEmployee = AesEncryptionService.EncryptString(clientId, JsonSerializer.Serialize(employee));
            return Ok(encryptedEmployee);
        }

        // Endpoint to add a new employee, input and output are encrypted.
        [HttpPost]
        public ActionResult<string> PostEmployee([FromBody] string encryptedEmployee)
        {
            // Extract 'ClientId' from request headers or use 'DefaultClient' if not present.
            var clientId = Request.Headers["ClientId"].FirstOrDefault() ?? "DefaultClient";
            // Decrypt and deserialize the employee data from the request.
            var decryptedEmployee = JsonSerializer.Deserialize<Employee>(AesEncryptionService.DecryptString(clientId, encryptedEmployee));
            if (decryptedEmployee == null)
            {
                return BadRequest("Invalid employee data");
            }
            // Assign a new ID to the employee and add them to the list.
            decryptedEmployee.Id = _employees.Max(e => e.Id) + 1;
            _employees.Add(decryptedEmployee);
            // Encrypt and serialize the new employee's data to send back.
            var encryptedResponse = AesEncryptionService.EncryptString(clientId, JsonSerializer.Serialize(decryptedEmployee));
            return CreatedAtAction("GetEmployee", new { id = decryptedEmployee.Id }, encryptedResponse);
        }

        // Endpoint to update an existing employee, input is encrypted.
        [HttpPut("{id}")]
        public IActionResult PutEmployee(int id, [FromBody] string encryptedEmployee)
        {
            // Extract 'ClientId' from request headers or use 'DefaultClient' if not present.
            var clientId = Request.Headers["ClientId"].FirstOrDefault() ?? "DefaultClient";
            // Decrypt and deserialize the incoming employee data.
            var decryptedEmployee = JsonSerializer.Deserialize<Employee>(AesEncryptionService.DecryptString(clientId, encryptedEmployee));
            var existingEmployee = _employees.FirstOrDefault(e => e.Id == id);
            if (existingEmployee == null)
            {
                return NotFound();
            }
            // Update the existing employee's details.
            existingEmployee.Name = decryptedEmployee.Name;
            existingEmployee.Salary = decryptedEmployee.Salary;
            return NoContent();
        }

        // Endpoint to delete an employee by ID.
        [HttpDelete("{id}")]
        public IActionResult DeleteEmployee(int id)
        {
            var employee = _employees.FirstOrDefault(e => e.Id == id);
            if (employee == null)
            {
                return NotFound();
            }
            // Remove the employee from the list.
            _employees.Remove(employee);
            return NoContent();
        }
    }
}
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
// Asynchronous main function.
static async Task Main(string[] args)
{
// HttpClient is used to make HTTP requests.
using (HttpClient client = new HttpClient())
{
// Add the ClientId to the default request headers.
client.DefaultRequestHeaders.Add("ClientId", ClientId);
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}");
}
// Fetching a specific employee by ID.
Console.WriteLine("\nFetching employee with ID 1...");
HttpRequestMessage getOneRequest = new HttpRequestMessage(HttpMethod.Get, $"{BaseUrl}/1");
HttpResponseMessage getOneResponse = await client.SendAsync(getOneRequest);
string encryptedGetOneResponse = await getOneResponse.Content.ReadAsStringAsync();
string decryptedGetOneResponse = DecryptString(encryptedGetOneResponse);
Console.WriteLine("Decrypted response (Employee ID 1):");
Console.WriteLine(decryptedGetOneResponse);
Employee employee = JsonSerializer.Deserialize<Employee>(decryptedGetOneResponse);
Console.WriteLine($"Employee Details - ID: {employee.Id}, Name: {employee.Name}, Salary: {employee.Salary}");
// Adding a new employee.
Console.WriteLine("\nAdding a new employee...");
var newEmployee = new Employee { Name = "David Brown", Salary = 65000 };
var encryptedEmployee = EncryptString(JsonSerializer.Serialize(newEmployee));
string jsonPayload = $"\"{encryptedEmployee}\"";
var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json");
HttpRequestMessage postRequest = new HttpRequestMessage(HttpMethod.Post, BaseUrl) { Content = content };
HttpResponseMessage postResponse = await client.SendAsync(postRequest);
string encryptedPostResponse = await postResponse.Content.ReadAsStringAsync();
string decryptedPostResponse = DecryptString(encryptedPostResponse);
Console.WriteLine("Decrypted response (New Employee):");
Console.WriteLine(decryptedPostResponse);
// Updating an existing employee.
Console.WriteLine("\nUpdating employee with ID 1...");
var updatedEmployee = new Employee { Name = "David Brown Updated", Salary = 70000 };
encryptedEmployee = EncryptString(JsonSerializer.Serialize(updatedEmployee));
jsonPayload = $"\"{encryptedEmployee}\"";
content = new StringContent(jsonPayload, Encoding.UTF8, "application/json");
HttpRequestMessage putRequest = new HttpRequestMessage(HttpMethod.Put, $"{BaseUrl}/1") { Content = content };
HttpResponseMessage putResponse = await client.SendAsync(putRequest);
Console.WriteLine(putResponse.IsSuccessStatusCode ? "Update successful" : "Update failed");
// 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}");
}
}
// Wait for a key press before closing the console window.
Console.ReadKey();
}
// 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);
// Convert the base64-encoded IV into a byte array.
byte[] _iv = Convert.FromBase64String(IV);
// Create a new AES instance to perform the symmetric algorithm.
using (var aesAlg = Aes.Create())
{
// Assign the encryption key to the AES algorithm.
aesAlg.Key = _key;
// Assign the initialization vector to the AES algorithm.
aesAlg.IV = _iv;
// Create an encryptor object to transform the data.
var encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
// Create a memory stream to hold the encrypted data.
using (var msEncrypt = new MemoryStream())
{
// Create a cryptographic stream that encrypts data and writes it to the memory stream.
using (var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
// Create a stream writer to write the plain text data to the crypto stream.
using (var swEncrypt = new StreamWriter(csEncrypt))
{
swEncrypt.Write(plainText);
}
// Convert the encrypted data from the memory stream to a base64 string.
return Convert.ToBase64String(msEncrypt.ToArray());
}
}
}
}
// 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);
// Convert the base64-encoded IV into a byte array.
byte[] _iv = Convert.FromBase64String(IV);
// Convert the base64-encoded cipher text into a byte array.
var buffer = Convert.FromBase64String(cipherText);
// Create a new AES instance to perform the symmetric algorithm.
using (var aesAlg = Aes.Create())
{
// Assign the decryption key to the AES algorithm.
aesAlg.Key = _key;
// Assign the initialization vector to the AES algorithm.
aesAlg.IV = _iv;
// Create a decryptor object to transform the encrypted data back into plain text.
var decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
// Create a memory stream to read the encrypted data.
using (var msDecrypt = new MemoryStream(buffer))
{
// Create a cryptographic stream that reads and decrypts data from the memory stream.
using (var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
// Create a stream reader to read the decrypted plain text data from the crypto stream.
using (var srDecrypt = new StreamReader(csDecrypt))
{
// Return the decrypted text read from the stream reader.
return srDecrypt.ReadToEnd();
}
}
}
}
}
// 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. You should see the output as expected, as shown in the image below.

How to Implement AES Encryption and Decryption in the ASP.NET Core Web API Application

Key Generator Console Application:

Now, create a new Console Application to generate 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();
}
// Method to generate an AES key and Initialization Vector (IV)
private static void GenerateAesKeyAndIV()
{
// Create a new AES object to generate keys.
// 'using' statement ensures that the AES instance is disposed correctly
using (Aes aesAlg = Aes.Create())
{
// Set the size of the encryption key to 256 bits, offering strong security
aesAlg.KeySize = 256;
// Generate a random key based on the key size set above
aesAlg.GenerateKey();
// Generate a random initialization vector (IV)
aesAlg.GenerateIV();
// 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);
// Output the base64-encoded AES key to the console
Console.WriteLine("AES Key (Base64): " + key);
// Output the base64-encoded AES IV to the console
Console.WriteLine("AES IV (Base64): " + iv);
}
}
}
}
Why Encryption and Decryption in ASP.NET Core Web API?

Encryption and Decryption are important security features in any web application, including those built using ASP.NET Core Web API. The following are the reasons why Encryption and Decryption are important in Web Applications:

  • Protecting Sensitive Data: Encryption helps protect sensitive data such as personal user information, payment details, and confidential business data. By encrypting data, it becomes unreadable to unauthorized users. Even if an attacker manages to intercept the data, without the proper decryption key, the information remains useless.
  • Ensuring Data Integrity: Encryption ensures that data has not been altered in transit. This helps maintain data integrity, ensuring that the data sent is exactly what is received on the other end.
  • Meeting Compliance Requirements: Many industries are governed by regulatory standards that require the protection of sensitive data. For example, the Health Insurance Portability and Accountability Act (HIPAA) in healthcare, the Payment Card Industry Data Security Standard (PCI DSS) for payment data, and the General Data Protection Regulation (GDPR) in the EU. Encryption helps in complying with these regulations.
  • Securing Communication: Data is frequently transmitted over the internet when using a Web API. Encryption ensures that this data is protected during transmission.
  • Building Trust: Implementing robust security measures, including encryption, helps build trust with your users. If they know your application is secure, they are more likely to trust it with their personal and sensitive information.
What are MemoryStream, CryptoStream, StreamWriter, and StreamReader Objects?

The classes MemoryStream, CryptoStream, StreamWriter in Encryption, and StreamReader in Decryption are used together to handle the encryption and decryption of data with AES. Let us have a look at each of these classes:

MemoryStream

MemoryStream 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 the 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 afterward.
  • Usage in Decryption: In the DecryptString method, MemoryStream is initialized with the byte array representing the encrypted data (converted from base64). This allows 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).

How They Work Together

In both methods, these streams are layered together to handle the data transformation seamlessly:

  • For encryption: StreamWriter -> CryptoStream -> MemoryStream
  • For decryption: MemoryStream -> CryptoStream -> StreamReader

In the next article, I will discuss how to Implement RSA Asymmetric Encryption and Decryption in ASP.NET Core Web API Applications. Here, in this article, I explain how to Implement AES Encryption and Decryption in the ASP.NET Core Web API Application with an Example. I hope you enjoy this Encryption and Decryption in ASP.NET Core Web API article.

Leave a Reply

Your email address will not be published. Required fields are marked *