2023. 9. 25. 00:00ㆍEntityFramewok Core (EF Core)
요즘 같은 경우는 개인정보 보호로 인해 사용자 정보를 db 에 저장할 경우
해당 data 를 encryption 해야 하는 경우가 많다.
이번시간에는 ef core 에서 특정 column 을 encryption , decryption 하는 방법을 알아보자
기존에 사용했던 API Server 를 이용하겠다.
https://yogingang.tistory.com/404
Rest API Template 만들기 - EP 01 (Create , Swagger, Logging)
Create visual studio 2022 를 실행하고 Create a new project 를 선택한다. asp.net core web api 선택 Project name 정하기 Additional Information 설정 Create 하면 Project 가 생성된다. F5 를 누르면 실행 된다. 위와 같이 swagger
yogingang.tistory.com
해당 강좌의 마지막까지 따라가면 api template 가 하나 만들어 질거고 그것을 이용할 것이다.
조금씩 다를 수 있지만 크게 다르지 않다.
강좌에서 사용하는 api server 는 ep 10 이후 encryption decryption 까지 적용된 버전이다.
이버전에서 특정 db 의 column 을 암호화 할 것이다.
BaseDbContext.cs
...
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Encryption>()
.HasData(new Encryption
{
Id = "AesInfo",
Key = "이게 32bytes 가 될때까지 이것 $%^&* 저것 넣어라 넘어도 된다. 알아서 자를거니까"u8.ToArray(),
IV = "이건 16bytes가 되어야 할꺼라고 南李事Encryption"u8.ToArray(),
});
modelBuilder.Entity<User>()
.Property(e => e.Name)
.HasConversion(
encryptedValue => AesHelper.EncryptString(encryptedValue),
decryptedValue => AesHelper.DecryptString(decryptedValue)
);
base.OnModelCreating(modelBuilder);
}
...
AESHelper.cs
public class AesHelper
{
public static byte[] Key { get; set; }
public static byte[] IV { get; set; }
public static string EncryptString(string plainText)
{
// Check arguments.
if (plainText == null || plainText.Length <= 0)
throw new ArgumentNullException("plainText");
if (Key == null || Key.Length <= 0)
throw new ArgumentNullException("Key");
if (IV == null || IV.Length <= 0)
throw new ArgumentNullException("IV");
byte[] encrypted;
// Create an Aes object
// with the specified key and IV.
using (Aes aesAlg = Aes.Create())
{
var pdb = new Rfc2898DeriveBytes(Key, IV, 1000, HashAlgorithmName.SHA512);
aesAlg.Key = pdb.GetBytes(32);
aesAlg.IV = pdb.GetBytes(16);
// Create an encryptor to perform the stream transform.
ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
// Create the streams used for encryption.
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
//Write all data to the stream.
swEncrypt.Write(plainText);
}
encrypted = msEncrypt.ToArray();
}
}
}
// Return the encrypted bytes from the memory stream.
//return encrypted;
return Convert.ToBase64String(encrypted);
}
public static string DecryptString(string cipherText)
{
// Check arguments.
if (cipherText == null || cipherText.Length <= 0)
throw new ArgumentNullException("cipherText");
if (Key == null || Key.Length <= 0)
throw new ArgumentNullException("Key");
if (IV == null || IV.Length <= 0)
throw new ArgumentNullException("IV");
// Declare the string used to hold
// the decrypted text.
string plaintext;
// Create an Aes object
// with the specified key and IV.
using var aesAlg = Aes.Create();
var pdb = new Rfc2898DeriveBytes(Key, IV, 1000, HashAlgorithmName.SHA512);
aesAlg.Key = pdb.GetBytes(32);
aesAlg.IV = pdb.GetBytes(16);
// Create a decryptor to perform the stream transform.
ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
// Create the streams used for decryption.
using (var msDecrypt = new MemoryStream(Convert.FromBase64String(cipherText)))
{
using (var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (var srDecrypt = new StreamReader(csDecrypt))
{
// Read the decrypted bytes from the decrypting stream
// and place them in a string.
plaintext = srDecrypt.ReadToEnd();
}
}
}
return plaintext;
}
}
AbstractBaseHandler.cs
public abstract class AbstractBaseHandler
{
protected readonly BaseDbContext _context;
protected readonly IConfiguration _configuration;
protected readonly IApiLogger _apiLogger;
public AbstractBaseHandler(BaseDbContext context, IConfiguration configuration, IApiLogger apiLogger)
{
_context = context;
_configuration = configuration;
_apiLogger = apiLogger;
if (AesHelper.Key != null && AesHelper.IV != null) return;
var encryption = _context.Encryptions.SingleOrDefault(e => e.Id == "AesInfo");
if (encryption != null)
{
AesHelper.Key = encryption.Key;
AesHelper.IV = encryption.IV;
}
}
...
}
AesHelper.Key 와 IV 를 설정한다. (초기화)
이제 migration and update 이 후 User.Name 이 암호화 되어 Db 에 저장되어 진걸 확인할 수 있다.
관련영상
'EntityFramewok Core (EF Core)' 카테고리의 다른 글
대용량 데이터 처리시 발생 하는 동시성 충돌 처리 (0) | 2024.03.18 |
---|---|
EF Core - With Generic Host (Pagination) (0) | 2023.08.21 |
EntityFramework Core Tip & Trick (0) | 2022.01.05 |