2014년 12월 10일 수요일

C# 공개키 암호화 (RSA 암호화) 적용.

프로그램작업을 하다 보면 암호화를 어쩔수 없이 적용해야 하는경우가 있는데, 여러가지 많은 암호화 로직이 있지만, 암호 저장 같은 특수한 몇몇 경우를 제외하고는 "복호화" 문제 때문에 결국 공개키 암호화(RSA) 를 적용하게 된다.

일단 기본적으로 C#은 RAS 암호화를 지원하기 때문에 그다지 어렵지 않게 적용 할수 있다.

일단 웹단에는


<form id="form1" runat="server">
    <div>

        <asp:TextBox ID="TextBox1" runat="server" TextMode="MultiLine"></asp:TextBox><p></p>
        <asp:Button ID="Button1" runat="server" Text="암호화" OnClick="Button1_Click" /><p></p>

        IN TXT : <asp:Label ID="Label1" runat="server" Text=""></asp:Label><p></p>
        De TXT: <asp:Label ID="Label2" runat="server" Text=""></asp:Label><p></p>

        <asp:TextBox ID="TextBox2" runat="server" TextMode="MultiLine"></asp:TextBox>
            
    </div>
    </form>


이정도로 간단한 인터페이스를 만들어 두고...


cs 단에는 ...

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Security;
using System.Security.Cryptography;
using System.Text;
using System.IO;

namespace WebApplication1
{
    public partial class WebForm1 : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
        }

        protected void Button1_Click(object sender, System.EventArgs e)
        {
            // 암호화 개체 생성
            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();

            // 개인키 생성
            RSAParameters privateKey = RSA.Create().ExportParameters(true);
            rsa.ImportParameters(privateKey);
            string privateKeyText = rsa.ToXmlString(true);

            // 공개키 생성
            RSAParameters publicKey = new RSAParameters();
            publicKey.Modulus = privateKey.Modulus;
            publicKey.Exponent = privateKey.Exponent;
            rsa.ImportParameters(publicKey);
            string publicKeyText = rsa.ToXmlString(false);

            Label1.Text = RSAEncrypt(TextBox1.Text, publicKeyText);
            Label2.Text = RSADecrypt(Label1.Text, privateKeyText);

            TextBox2.Text = Label2.Text;
        }

        // RSA 암호화
        public string RSAEncrypt(string getValue, string pubKey)
        {
            System.Security.Cryptography.RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); //암호화
            rsa.FromXmlString(pubKey);

            //암호화할 문자열을 UFT8인코딩
            byte[] inbuf = (new UTF8Encoding()).GetBytes(getValue);

            //암호화
            byte[] encbuf = rsa.Encrypt(inbuf, false);

            //암호화된 문자열 Base64인코딩
            return Convert.ToBase64String(encbuf);
        }

        // RSA 복호화
        public static string RSADecrypt(string getValue, string priKey)
        {
            //RSA객체생성
            System.Security.Cryptography.RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); //복호화
            rsa.FromXmlString(priKey);

            //sValue문자열을 바이트배열로 변환
            byte[] srcbuf = Convert.FromBase64String(getValue);

            //바이트배열 복호화
            byte[] decbuf = rsa.Decrypt(srcbuf, false);

            //복호화 바이트배열을 문자열로 변환
            string sDec = (new UTF8Encoding()).GetString(decbuf, 0, decbuf.Length);
            return sDec;
        }
    }
}

이정도로 해두면 된다.



그럼 이렇게 암호화 및 복호화를 할 수 있다.

현재 예제는 RSAParameters privateKey = RSA.Create().ExportParameters(true); 를 통해서 실행시 마다 개인 키를 생성해서 쓰는 방식이지만...



각 키를 디버그 모드를 쓰던 어떻게든 알아내서...



using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

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


namespace WebApplication1
{
    public partial class WebForm1 : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }

        protected void Button1_Click(object sender, System.EventArgs e)
        {
            string privateKeyText, publicKeyText;
            privateKeyText = "<RSAKeyValue><Modulus>xb2pB0WkbgL0/3UxAYLs5B4ekUYaKBiYmKAlTNylzcefzeJPiJlPkob4aPjlU6fZBU/9NiCsthO4DPtazSXk+wB4Q1JtLf2rKLqboxNLZxvV286Gfl24XEB9RswVmhgPDk60VQ1QAI495qoc9paEhmSjcShdCZL7D/r17M6YEkM=</Modulus><Exponent>AQAB</Exponent><P>5kO8JY9g2bBgNZ0eCaLJGknrGDMk2cmm13RUbRv6auas0sjRxZQP0vg6OAPy43l4JKIJte375kl8LFwpU93lYw==</P><Q>29ddmOPFm8JfRLN6mCxTt3w9bizweniMiXpwzXVgq/yrKMoEsT1zj+35jSZ32E6u0u9ZBmo+Ur7dQb10j6aloQ==</Q><DP>jChAlpAuQHL2LMwk43KdfA3wNnuy+4mdr1lUplE4XOdp3Kd14BCejSigr0XgCwv90DZ9OKrSADtMhOfYE/9lxw==</DP><DQ>F13+7t9XA8VXRwAkycP8agZkqS9RqFLj7UD8eHo/ekhzEPTYJta3T9clrWEnX/CNGJKkTdBBK55p+jDfEN3PwQ==</DQ><InverseQ>M/IbkooBDo4QSon30995lG6/A+O8WYtYPohNGmb/sHDoIJ/Kry94uBwHSMi4K08H5jrCDlNOtrn3zaKzlrz+yA==</InverseQ><D>ujJoClfyiECykCW62pB9HiSaZfMbyCu47ObHmMOgQM+7U3PJrnembPQ4zyenUYmYmh8C8Mf9uYmB4n+AtfH71RJ7SR507ki/zaPjxVatUYrBk/DZckidgclYd/sdCvLARXOr83Ykbxqz/tkE5to2TKj4uqnOMa2iFXE4Nfu3LME=</D></RSAKeyValue>";
            publicKeyText = "<RSAKeyValue><Modulus>xb2pB0WkbgL0/3UxAYLs5B4ekUYaKBiYmKAlTNylzcefzeJPiJlPkob4aPjlU6fZBU/9NiCsthO4DPtazSXk+wB4Q1JtLf2rKLqboxNLZxvV286Gfl24XEB9RswVmhgPDk60VQ1QAI495qoc9paEhmSjcShdCZL7D/r17M6YEkM=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";

            Label1.Text = RSAEncrypt(TextBox1.Text, publicKeyText);
            Label2.Text = RSADecrypt(Label1.Text, privateKeyText);

            TextBox2.Text = Label2.Text;

        }

        // RSA 암호화
        public string RSAEncrypt(string getValue, string pubKey)
        {
            System.Security.Cryptography.RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); //암호화
            rsa.FromXmlString(pubKey);

            //암호화할 문자열을 UFT8인코딩
            byte[] inbuf = (new UTF8Encoding()).GetBytes(getValue);

            //암호화
            byte[] encbuf = rsa.Encrypt(inbuf, false);

            //암호화된 문자열 Base64인코딩
            return Convert.ToBase64String(encbuf);
        }

        // RSA 복호화
        public static string RSADecrypt(string getValue, string priKey)
        {
            //RSA객체생성
            System.Security.Cryptography.RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); //복호화
            rsa.FromXmlString(priKey);

            //sValue문자열을 바이트배열로 변환
            byte[] srcbuf = Convert.FromBase64String(getValue);

            //바이트배열 복호화
            byte[] decbuf = rsa.Decrypt(srcbuf, false);

            //복호화 바이트배열을 문자열로 변환
            string sDec = (new UTF8Encoding()).GetString(decbuf, 0, decbuf.Length);
            return sDec;
        }
    }
}


이렇게 미리 키를 지정해 놓고 써도된다.