반응형

C# - 문자열 양방향 암호화 ( RijndaelManaged )


환경 ; visual studio community 2017


참고 : https://docs.microsoft.com/ko-kr/dotnet/api/system.security.cryptography.rijndaelmanaged?view=netframework-4.6.1


** 참고에 나온 예제 함수를 그대로 사용함.


** 문자열을 RijndaelManaged 로 암호화 한후, 복호화 하기 **


** 문자열을 암호화 하면, byte[ ] 형태의 결과 값 나옴

   --> db 나 파일에 저장하기 편하게 하기위해, 16진수 string 으로 변환하여 저장함.

   --> 이후, 저장된 16진수 문자열을 읽어들여, byte[ ] 로 바꾸고,

   --> 이를 다시 문자열로 복호화 함.



** 암호화 하기 위해, 먼저 key 와 IV(initialization vector) 를 구하여, 저장해둔다.

   --> 이후, 암호화 , 복호화 시에 똑같은 key 와 iv 를 사용해야함.


            byte[] key = GetKey();  // 실행시마다, 바뀜
            byte[] iv = GetIV();  // 실행시마다, 바뀜

   --> 실행시마다, 바뀌므로,  key, iv 를 한번만 실행하여, 그 결과를 아래와 같이 하드코딩하여 계속 사용하자.



            key = new byte[] { 66178206246134160101782015911825492251451141771742062381861581535189182243214187200156210 };
            iv = new byte[] { 15115177176641171391502395333111547721976 };



** 암호화 하는 함수 **

            string encStr = GetEncryptedData(strDatakeyiv);



** 복호화 하는 함수 **

            string data = GetDecryptedData(encStrkeyiv);  // 복호화



<< 전체 소스 코드 >>


using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace 암호화
{
    class Program
    {

        public static void Main()
        {
            CryptRijndaelManaged.Test("abdc 암호화 @ 테스트 코드 !!");

            //Console.ReadLine();
        }

    }

    // 문자열 -- 양방향 암호화 
    public class CryptRijndaelManaged
    {
        // ** 참고 ; https://docs.microsoft.com/ko-kr/dotnet/api/system.security.cryptography.rijndaelmanaged?view=netframework-4.6.1

        // sample test 용..
        static public void Test(string strData = "Here is 한글 테스트!")
        {
            byte[] key = GetKey();  // 실행시마다, 바뀜
            byte[] iv = GetIV();  // 실행시마다, 바뀜

            PrintKey(key);  // 출력값을 프로그램 내에 하드코딩 하여 계속 사용하자!!!

            Console.WriteLine("-------------------");

            PrintIV(iv);  // 출력값을 프로그램 내에 하드코딩 하여 계속 사용하자!!!

            Console.WriteLine("============ key, iv 하드코딩후 사용 예 ========================");

            key = new byte[] { 66178206246134160101782015911825492251451141771742062381861581535189182243214187200156210 };
            iv = new byte[] { 15115177176641171391502395333111547721976 };

            Console.WriteLine($"원본 문자열 ; {strData}\n");

            string encStr = GetEncryptedData(strDatakeyiv);

            Console.WriteLine($"저장하기 편한 hex string 암호화 data (파일 저장용); \n{encStr}");

            string data = GetDecryptedData(encStrkeyiv);  // 복호화


            Console.WriteLine($"\n복구된 문자열 ; {data}");
            //Debug.WriteLine("-------------------");

            Console.ReadLine();
        }

        // 프로그램 내에 Key 값을 하드코딩 시에 사용!
        static string PrintKey(byte[] key = null)
        {
            string strKey = ToStringFromBytes(key);
            Console.WriteLine($"Key = {{ {strKey} }}");

            return strKey;
        }

        // 프로그램 내에 IV 값을 하드코딩 시에 사용!
        static string PrintIV(byte[] iv = null)
        {
            string strIV = ToStringFromBytes(iv);
            Console.WriteLine($"IV = {{ {strIV} }}");

            return strIV;
        }

        // 반환값 형식 ex) 58, 176, 190, 165, 246, 118, 253, 90, 147, 7, 
        static private string ToStringFromBytes(byte[] data = null)
        {
            if(data == null)
            {
                data = GetKey();
            }

            StringBuilder strb = new StringBuilder();

            for (int i=0i < data.Length - 1i++)
            {
                strb.Append($"{data[i]}, ");
            }

            strb.Append(data[data.Length - 1]);  // 마지막 data 에는 ', ' 를 넣지말자.

            return strb.ToString();
        }

        // **** byte[] 을 hex string 으로 변환하여 반환.****
        static private string ToHexStringFromBytes(byte[] data = null)
        {
            // **** 파일 or db 저장용. hex string 만들기 위함. ****
            // 반환값 형식 ex) 8B406FF18EE5AD0CD3AFFFD73F28B380B014D2420A0FC6C5BFCF40911CDB2E21

            if (data == null)
            {
                //data = GetKey();
                return null;
            }

            StringBuilder strb = new StringBuilder();

            for (int i = 0i < data.Lengthi++)
            {
                strb.Append($"{data[i]:X2}");  // 2자리 16진수로 변환.
            }

            return strb.ToString();
        }

        static private byte[] HexStringToBytes(string hexData)
        {
            if (hexData == null)
            {
                return null;
            }

            List<bytetempList = new List<byte>();

            // 2개씩 읽어들여서, 변환함.
            for (int i = 0i < hexData.Length/2i++)
            {
                string hexValue = hexData.Substring(i*22);  
                //Console.Write($"{hexValue}, ");
                tempList.Add(Convert.ToByte(hexValue16));  // 16진수 문자를, byte 로 변환.
            }

            return tempList.ToArray();
        }

        static public byte[] GetKey()
        {
            using (RijndaelManaged myRijndael = new RijndaelManaged())
            {
                myRijndael.GenerateKey();

                return myRijndael.Key;
            }
        }

        static public byte[] GetIV()
        {
            using (RijndaelManaged myRijndael = new RijndaelManaged())
            {
                myRijndael.GenerateIV();

                return myRijndael.IV;
            }
        }

        // 원본 string --> 암호화된 hex string
        static public string GetEncryptedData(string databyte[] Keybyte[] IV)
        {
            byte[] encData = EncryptStringToBytes(dataKeyIV); // **** 암호화된 data ****

            //===== encStr 을 파일이나, db 에 저장하여 사욯한다.  ===========
            // --- 저장하기 편하게 하기위해, 암호화된 byte[] 데이터 ==> hex string data로 변환.
            string encStr = ToHexStringFromBytes(encData);  // **** 파일 저장용. hex string ****

            return encStr;
        }

        // 암호화된 hex string --> 복호화된 원본 string
        static public string GetDecryptedData(string encStrbyte[] Keybyte[] IV)
        {
            byte[] encData2 = HexStringToBytes(encStr);  // 저장된 암호화 string data를, byte[] 로 변환함.

            string data = DecryptStringFromBytes(encData2KeyIV);  // 복호화

            return data;
        }

        static byte[] EncryptStringToBytes(string plainTextbyte[] Keybyte[] IV)
        {
            // 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 RijndaelManaged object
            // with the specified key and IV.
            using (RijndaelManaged rijAlg = new RijndaelManaged())
            {
                rijAlg.Key = Key;
                rijAlg.IV = IV;

                // Create an encryptor to perform the stream transform.
                ICryptoTransform encryptor = rijAlg.CreateEncryptor(rijAlg.KeyrijAlg.IV);

                // Create the streams used for encryption.
                using (MemoryStream msEncrypt = new MemoryStream())
                {
                    using (CryptoStream csEncrypt = new CryptoStream(msEncryptencryptorCryptoStreamMode.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;
        }

        static string DecryptStringFromBytes(byte[] cipherTextbyte[] Keybyte[] IV)
        {
            // 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 = null;

            // Create an RijndaelManaged object
            // with the specified key and IV.
            using (RijndaelManaged rijAlg = new RijndaelManaged())
            {
                rijAlg.Key = Key;
                rijAlg.IV = IV;

                // Create a decryptor to perform the stream transform.
                ICryptoTransform decryptor = rijAlg.CreateDecryptor(rijAlg.KeyrijAlg.IV);

                // Create the streams used for decryption.
                using (MemoryStream msDecrypt = new MemoryStream(cipherText))
                {
                    using (CryptoStream csDecrypt = new CryptoStream(msDecryptdecryptorCryptoStreamMode.Read))
                    {
                        using (StreamReader srDecrypt = new StreamReader(csDecrypt))
                        {
                            // Read the decrypted bytes from the decrypting stream
                            // and place them in a string.
                            plaintext = srDecrypt.ReadToEnd();
                        }
                    }
                }
            }

            return plaintext;
        }


    }
}





반응형
Posted by 자유프로그램
,