예전부터 한번 해봐야지 하고 생각만 하다가 안했던 암호화처리
요즘은 나름 보안에 관심을 가져야 겠다 라는 생각에 데이터 네트워크로 송수신할때 암호화는 적용해야 하지 않을까 라는 생각에 간단한 예제 해봄.
암호화에 대한 기초 지식은 https://www.slideshare.net/ssuser800974/ss-76664853 를 참고함
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; using System.Security.Cryptography; using System.Text; using System.Threading.Tasks; namespace AESTest2 { class AESEncrypt { private SHA256Managed sha256Managed = new SHA256Managed(); private RijndaelManaged aes = new RijndaelManaged(); public AESEncrypt() { aes.KeySize = 256; aes.BlockSize = 128; aes.Mode = CipherMode.CBC; aes.Padding = PaddingMode.PKCS7; } //AES_256 암호화 public byte[] AESEncrypt256(byte[] encryptData, String password) { // Salt는 비밀번호의 길이를 SHA256 해쉬값으로 한다. var salt = sha256Managed.ComputeHash(Encoding.UTF8.GetBytes(password.Length.ToString())); Console.WriteLine("Salt(Base64) : " + Convert.ToBase64String(salt)); //PBKDF2(Password-Based Key Derivation Function) //반복은 65535번 var PBKDF2Key = new Rfc2898DeriveBytes(password, salt, 65535, HashAlgorithmName.SHA256); var secretKey = PBKDF2Key.GetBytes(aes.KeySize / 8); var iv = PBKDF2Key.GetBytes(aes.BlockSize / 8); Console.WriteLine("SecretKey(Base64) : " + Convert.ToBase64String(secretKey)); Console.WriteLine("IV(Base64) : " + Convert.ToBase64String(iv)); byte[] xBuff = null; using (var ms = new MemoryStream()) { using (var cs = new CryptoStream(ms, aes.CreateEncryptor(secretKey, iv), CryptoStreamMode.Write)) { cs.Write(encryptData, 0, encryptData.Length); } xBuff = ms.ToArray(); } return xBuff; } //AES_256 복호화 public byte[] AESDecrypt256(byte[] decryptData, String password) { // Salt는 비밀번호의 길이를 SHA256 해쉬값으로 한다. var salt = sha256Managed.ComputeHash(Encoding.UTF8.GetBytes(password.Length.ToString())); //PBKDF2(Password-Based Key Derivation Function) //반복은 65535번 var PBKDF2Key = new Rfc2898DeriveBytes(password, salt, 65535, HashAlgorithmName.SHA256); var secretKey = PBKDF2Key.GetBytes(aes.KeySize / 8); var iv = PBKDF2Key.GetBytes(aes.BlockSize / 8); byte[] xBuff = null; using (var ms = new MemoryStream()) { using (var cs = new CryptoStream(ms, aes.CreateDecryptor(secretKey, iv), CryptoStreamMode.Write)) { cs.Write(decryptData, 0, decryptData.Length); } xBuff = ms.ToArray(); } return xBuff; } } class Program { static void Main(string[] args) { AESEncrypt aes = new AESEncrypt(); var planeText = "https://linsoo.co.kr"; var password = "비밀번호"; Console.WriteLine("오리지널 문장 : "+planeText); Console.WriteLine("대칭키로 쓰일 키 : " + password); Console.WriteLine(""); //스트링을 byte배열로 변환 var byteArray = Encoding.UTF8.GetBytes(planeText); //AES256으로 인크립트 byte[] encryptedArray = aes.AESEncrypt256(byteArray, password); Console.WriteLine(""); Console.WriteLine("인크립트 된 문자열 : " + Encoding.UTF8.GetString(encryptedArray)); //디크립트(AES256) byte[] decryptedArray = aes.AESDecrypt256(encryptedArray, password); var decryptedString = Encoding.UTF8.GetString(decryptedArray); Console.WriteLine("디크립트 된 문자열 : " + decryptedString); Console.WriteLine(""); } } }
다른 예제들 보면 대부분 IV 값을 0으로 넣는데 0이면 큰 의미는 없을거 같아서 검색해보니 패스워드 키값을 가지고 이래저래 섞어서 쓰길래 나도 적용함.
반복은 많이 할수록 느려지지만 그만큼 풀기가 힘들어진다고 함.
암튼 그래서 위와 같은 방식으로 작업 완료.
C#에서는 기본적으로 제공되는 함수가 많아서 편리하고 간단하게 작업되서 좋았음.
전문가들 추천으로는 암호화는 절대로 독자적인 방법으로 만들지 말고 남들이 많이 쓰는 안전하다고 입증된 알고리즘을 입증된 라이브러리 써서 적용하라고 함.
답글 남기기