재우니의 블로그

 

 

 

ASP.NET CORE : 대칭 암호화 알고리즘 AES-256 (Advanced Encryption Standard) 구현하기 (Aes Class)

 

https://aspdotnet.tistory.com/3242

 

ASP.NET CORE : 대칭 암호화 알고리즘 AES(Advanced Encryption Standard) 구현하기 (Aes Class)

📌 암호화 기술 개요제공된 코드에 사용된 암호화 기술은 보안과 효율성으로 널리 알려진 대칭 암호화 알고리즘 AES(Advanced Encryption Standard)를 기반으로 합니다.📌  주요 개념:대칭 암호화:대

aspdotnet.tistory.com

 

 

 

ASP.NET CORE : 대칭 암호화 알고리즘 AES 시나리오 2가지로 구현하기

 

전체적인 코드는 MSSQL 데이터베이스와 Dapper를 사용하여 데이터를 암호화하고 저장한 후, 복호화하여 반환하는 기능을 포함하고 있습니다. 아래에 제시된 단계를 따라 실제로 코드를 실행하고 결과를 확인할 수 있습니다.

 

 

📌 암호화 서비스 및 컨트롤러 코드: 두 가지 케이스에 맞게 재구성

 

  1. 문자열을 받아서 문자열로 암호화하고, 암호화된 문자열을 문자열로 복호화
  2. 문자열을 받아서 바이트 배열로 변환하여 암호화하고, 바이트 배열로 복호화한 후 문자열로 변환하여 반환

 

 

1. 데이터베이스 설정

SQL Server에 EncryptedData 테이블을 생성합니다:

 

CREATE TABLE EncryptedData (
    Id INT PRIMARY KEY IDENTITY(1,1),
    EncryptedValue VARBINARY(MAX) NOT NULL
);

 

 

2. 모델 클래스 생성

EncryptedData 모델 클래스를 생성합니다:

 

public class EncryptedData
{
    public int Id { get; set; }
    public byte[] EncryptedValue { get; set; }
}

 

 

3. AES 암호화 서비스 클래스 생성

AesEncryptionService 클래스를 생성합니다:

 

256비트 키와 128비트 초기화 벡터를 사용하는 AES-256 암호화를 사용합니다. 이 구성은 다양한 암호화 요구 사항에 적합한 높은 수준의 보안을 보장합니다.

 

AES-256:

  • : 32바이트(256비트)
  • IV: 16바이트(128비트)

 

using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace AesEncryptionExample.Services
{
    public class AesEncryptionService
    {
        private readonly byte[] Key;
        private readonly byte[] IV;

        public AesEncryptionService(byte[] key, byte[] iv)
        {
            if (key == null || key.Length != 32)
                throw new ArgumentException("Key must be 32 bytes long.");

            if (iv == null || iv.Length != 16)
                throw new ArgumentException("IV must be 16 bytes long.");

            Key = key;
            IV = iv;
        }

        public byte[] EncryptStringToBytes(string plainText)
        {
            if (plainText == null)
                throw new ArgumentNullException(nameof(plainText));

            byte[] plainBytes = Encoding.UTF8.GetBytes(plainText);
            byte[] encrypted;

            using (Aes aesAlg = Aes.Create())
            {
                aesAlg.Key = Key;
                aesAlg.IV = IV;

                ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);

                using (MemoryStream msEncrypt = new MemoryStream())
                {
                    using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                    {
                        csEncrypt.Write(plainBytes, 0, plainBytes.Length);
                        csEncrypt.FlushFinalBlock();
                        encrypted = msEncrypt.ToArray();
                    }
                }
            }

            return encrypted;
        }

        public string DecryptBytesToString(byte[] cipherBytes)
        {
            if (cipherBytes == null || cipherBytes.Length <= 0)
                throw new ArgumentNullException(nameof(cipherBytes));

            byte[] plainBytes;
            string plaintext = null;

            using (Aes aesAlg = Aes.Create())
            {
                aesAlg.Key = Key;
                aesAlg.IV = IV;

                ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);

                using (MemoryStream msDecrypt = new MemoryStream(cipherBytes))
                {
                    using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                    {
                        using (MemoryStream msPlain = new MemoryStream())
                        {
                            csDecrypt.CopyTo(msPlain);
                            plainBytes = msPlain.ToArray();
                        }
                    }
                }
            }

            plaintext = Encoding.UTF8.GetString(plainBytes);
            return plaintext;
        }
    }
}

 

 

4. 컨트롤러 클래스 생성

EncryptionController 클래스를 생성합니다:

 

using Microsoft.AspNetCore.Mvc;
using AesEncryptionExample.Services;
using System.Data.SqlClient;
using System.Threading.Tasks;
using Dapper;

namespace AesEncryptionExample.Controllers
{
    public class EncryptionController : Controller
    {
        private readonly AesEncryptionService _aesEncryptionService;
        private readonly string _connectionString;

        public EncryptionController(AesEncryptionService aesEncryptionService)
        {
            _aesEncryptionService = aesEncryptionService;
            _connectionString = "YourConnectionString"; // 실제 연결 문자열로 대체
        }

        [HttpPost]
        public async Task<IActionResult> Encrypt([FromBody] string text)
        {
            if (string.IsNullOrEmpty(text))
            {
                return BadRequest("Text cannot be null or empty");
            }

            var encryptedBytes = _aesEncryptionService.EncryptStringToBytes(text);
            var encryptedData = new EncryptedData
            {
                EncryptedValue = encryptedBytes
            };

            using (var connection = new SqlConnection(_connectionString))
            {
                var sql = "INSERT INTO EncryptedData (EncryptedValue) VALUES (@EncryptedValue); SELECT CAST(SCOPE_IDENTITY() as int)";
                var id = await connection.QuerySingleAsync<int>(sql, new { EncryptedValue = encryptedData.EncryptedValue });
                encryptedData.Id = id;
            }

            return Ok(Convert.ToBase64String(encryptedBytes));
        }

        [HttpGet("{id}")]
        public async Task<IActionResult> Decrypt(int id)
        {
            EncryptedData encryptedData;

            using (var connection = new SqlConnection(_connectionString))
            {
                var sql = "SELECT * FROM EncryptedData WHERE Id = @Id";
                encryptedData = await connection.QuerySingleOrDefaultAsync<EncryptedData>(sql, new { Id = id });
            }

            if (encryptedData == null)
            {
                return NotFound();
            }

            var decryptedText = _aesEncryptionService.DecryptBytesToString(encryptedData.EncryptedValue);
            return Ok(decryptedText);
        }

        [HttpPost("EncryptBytes")]
        public IActionResult EncryptBytes([FromBody] string text)
        {
            if (string.IsNullOrEmpty(text))
            {
                return BadRequest("Text cannot be null or empty");
            }

            var encryptedBytes = _aesEncryptionService.EncryptStringToBytes(text);
            return Ok(encryptedBytes);
        }

        [HttpPost("DecryptBytes")]
        public IActionResult DecryptBytes([FromBody] byte[] encryptedBytes)
        {
            if (encryptedBytes == null || encryptedBytes.Length == 0)
            {
                return BadRequest("Encrypted bytes cannot be null or empty");
            }

            var decryptedText = _aesEncryptionService.DecryptBytesToString(encryptedBytes);
            return Ok(decryptedText);
        }
    }
}

 

 

5. Program.cs 설정

 

using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using AesEncryptionExample.Services;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddControllersWithViews();

// Register AesEncryptionService with appropriate key and IV
byte[] key = { 0x14, 0x22, 0x03, 0x05, 0x20, 0x89, 0x64, 0x1A, 0x29, 0x33,
               0xAA, 0x97, 0x23, 0x33, 0x35, 0x58, 0x28, 0x9E, 0x70, 0x53,
               0x3D, 0x02, 0x43, 0x3C, 0x1E, 0xC1, 0x82, 0xB5, 0x2C, 0x1F,
               0x1F, 0x5B };
byte[] iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
              0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

builder.Services.AddSingleton(new AesEncryptionService(key, iv));

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Home/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

app.Run();

 

 

테스트 실행

위의 코드를 설정한 후, Postman 또는 다른 HTTP 클라이언트를 사용하여 다음과 같은 요청을 보낼 수 있습니다:

 

 

암호화

  1. POST 요청: https://localhost:5001/Encryption/Encrypt
    • 요청 본문: { "text": "Nice to meet you." }
    • 응답 예시 (Base64로 인코딩된 암호화된 문자열): "QWJjMTIzIT8kKiYoKSctPUB+"

 

복호화

  1. GET 요청: https://localhost:5001/Encryption/Decrypt/{id}
    • URL에서 {id}를 암호화된 데이터의 ID로 대체 : "Nice to meet you."

 

 

요약

  • 데이터베이스 설정: EncryptedData 테이블을 생성합니다.
  • AES 암호화 서비스: 문자열을 암호화하고 복호화하는 서비스를 구현합니다.
  • Dapper를 사용한 컨트롤러: 암호화된 데이터를 저장하고 조회하여 복호화 합니다.