Common Tip/보안(Security)2009. 8. 13. 10:06

민범규님의 글(Devpia 펌)
RSACryptoServiceProvider

 CSP(암호화 서비스 공급자) 제공한 RSA 알고리즘의 구현을 사용하여 비대칭 암호화와 해독을 수행합니다.

클래스는 상속될 없습니다

이것은 RSA 기본 구현입니다.

Microsoft Enhanced Cryptographic Provider 설치되어 있는 경우 RSACryptoServiceProvider에서는 길이가 384 - 16384비트(8비트 단위로 증가) 키를 지원하고 Microsoft Base Cryptographic Provider 설치되어 있는 경우에는 길이가 384 - 512비트(8비트 단위로 증가) 키를 지원합니다.

Microsoft CAPI(Cryptographic API)와의 상호 운용

비관리 CAPI RSA 구현과 달리 RSACryptoServiceProvider 클래스는 암호화 후와 암호 해독 전에 바이트의 암호화된 배열에 대한 순서를 반대로 바꿉니다. 기본적으로 RSACryptoServiceProvider 클래스로 암호화된 데이터는 CAPI CryptDecrypt 함수로 암호 해독할 없으며 CAPI CryptEncrypt 메서드로 암호화된 데이터는 RSACryptoServiceProvider 클래스로 암호 해독할 없습니다.

API 상호 운용 역순서 지정에 대한 보완 작업을 수행하지 않으면 RSACryptoServiceProvider 클래스가 CryptographicException throw합니다.

CAPI 상호 운용하려면 암호화된 데이터가 다른 API 상호 운용되기 전에 암호화된 바이트의 순서를 직접 반대로 바꿔야 합니다. Array..::.Reverse 메서드를 호출하여 관리되는 바이트 배열의 순서를 쉽게 반대로 바꿀 있습니다.

 인터넷에서 찿아본 설명들

RSA공개키 암호시스템의 하나로, 암호화 뿐만 아니라 전자서명이 가능한 최초의 알고리즘으로 알려져 있다. RSA가 갖는 전자서명 기능은 인증을 요구하는전자 상거래 등에 RSA의 광범위한 활용을 가능하게 하였다.

1977로널드 라이베스트(Ron Rivest), 아디 샤미르(Adi Shamir), 레오널드 애들먼(Leonard Adleman)의 연구에 의해 체계화되었으며, RSA라는 이름은 이들 3명의 이름 앞글자를 딴 것이다. 이 세 발명자는 이 공로로 2002튜링상을 수상했다.

RSA 암호체계의 안정성은 큰 숫자를 소인수분해하는 것이 어렵다는 것에 기반을 두고 있다. 그러므로 큰 수의 소인수분해를 획기적으로 빠르게 할 수 있는 알고리즘이 발견된다면 이 암호 체계는 가치가 떨어질 것이다. 1993 피터 쇼어쇼어 알고리즘을 발표하여, 양자 컴퓨터를 이용하여 임의의 정수를 다항 시간 안에 소인수분해하는 방법을 발표하였다. 따라서 양자 컴퓨터가 본격적으로 실용화되면 RSA 알고리즘은 무용지물이 될 것이다. 그러나 양자 컴퓨터가 이 정도 수준으로 실용화되려면 아직 여러 해가 더 필요할 것으로 보인다.

RSA 암호화 알고리즘은 1983에 발명자들이 소속되어 있던 매사추세츠 과대학교(MIT)에 의해 미국특허로 등록되었고, 2000 9월 21에 그 특허가 만료되었다

RSA는 두 개의 를 사용한다. 여기서 키란 메시지를 열고 잠그는 상수(constant)를 의미한다. 이 중 공개키(public key)는 모두에게 알려져 있으며, 메시지를 암호화(encrypt)하는데 쓰인다. 이렇게 암호화된 메시지는 개인(private key)를 가진 자만이 복호화(decrypt)하여 열어볼 수 있다. 다시 말하면, 누구나 어떤 메시지를 암호화할 수 있지만, 그것을 해독하여 열람할 수 있는 사람은 개인키를 지닌 단 한 사람 뿐인 것이다. RSA는 소인수분해의 난해함에 기반하여, 공개키만을 가지고는 개인키를 쉽게 짐작할 수 없도록 디자인되어 있다.

보다 이해하기 쉬운 예를 들자면, A라는 사람에게 B라는 사람이 메시지를 전하고자 할 때 B A의 열린 자물쇠를 들고 와 그의 메시지를 봉인하고, 그런 다음 A에게 전해 주면, 자물쇠의 열쇠를 가지고 있는 A가 그 메시지를 열어보는 식이 된다. 중간에 그 메시지를 가로채는 사람은 그 열쇠를 가지고 있지 않으므로 메시지를 열람할 수 없다. 그리고 RSA의 디자인 상, 그 열쇠는 자물쇠의 형태만 보고서는 쉽게 제작할 수가 없게 되어 있다.

 XML문서 서명 예제

//XML 서명

        private void btn전자서명_Click(object sender, EventArgs e)

        {

            CspParameters cspParams = new CspParameters();

            cspParams.KeyContainerName = "XML_DSIG_RSA_KEY";

 

            RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider(cspParams);

 

            XmlDocument xmlDoc = new XmlDocument();

            xmlDoc.PreserveWhitespace = true;

            xmlDoc.Load(strSource);     //서명 전 XML 읽기

            textBox1.Text = xmlDoc.OuterXml; //서명전 파일 보기

 

            SignedXml signedXml = new SignedXml(xmlDoc);

            signedXml.SigningKey = rsaKey;

 

            Reference reference = new Reference();

            reference.Uri = "";

 

            XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform();

            reference.AddTransform(env);

            signedXml.AddReference(reference);

            signedXml.ComputeSignature();

            XmlElement xmlDigitalSignature = signedXml.GetXml();

            XmlElement root = xmlDoc.DocumentElement;

            root.InsertAfter(xmlDoc.ImportNode(xmlDigitalSignature, true), root.FirstChild);

           

            xmlDoc.Save(strOutput);             //서명한 XML생성

            textBox2.Text = xmlDoc.OuterXml;

        }

 

        //XML 서명

        private void btn서명확인_Click(object sender, EventArgs e)

        {

            CspParameters cspParams = new CspParameters();

            cspParams.KeyContainerName = "XML_DSIG_RSA_KEY";

            RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider(cspParams);

 

            XmlDocument xmlDoc = new XmlDocument();

 

            xmlDoc.PreserveWhitespace = true;

            xmlDoc.Load(strOutput);

 

            //

            SignedXml signedXml = new SignedXml(xmlDoc);

            XmlNodeList nodeList = xmlDoc.GetElementsByTagName("Signature");

 

            if (nodeList.Count <= 0)

                throw new CryptographicException("XML파일에 Signature Element는 하나만 존재하여야 합니다.");

 

            signedXml.LoadXml((XmlElement)nodeList[0]);

            bool result= signedXml.CheckSignature(rsaKey);

     

            if (result)

                textBox3.Text = "서명과 일치 합니다";

            else

                textBox3.Text = "서명과 불칠칭 합니다.";

        }




Posted by penguindori
Common Tip/보안(Security)2009. 8. 13. 09:56

민범규님의 글(Devpia 펌)
RijndaelManaged을 사용하여 암호화 복호화 하는 예제을

MSDN의 내용을 최대한 간단히 만들어 본것입니다.

다음에는 XML서명에 관하여 간단한 예제를 올릴려고 합니다.

대칭형 암호화

1.     ACE

2.     DES

3.     DSE

4.     RC2

5.     Rijndael

6.     TripleDES


RijndaelManaged

현재 표준임.


테스트 예제

1 미리보기


private
void RijndaelManagedDemo_Load(object sender, EventArgs e)

        {

            textBox1.Text = "가나다라마바사아자차카타파하";

            textBox1.Text += "\r\n1234567890";

            textBox1.Text += "\r\nABCDEFGHIJKLMNOPQRSTUVWXYZ";

            textBox1.Text += "\r\nabcdefghijklmnopqrstuvwxyz";

            txtKey.Text = "12345678901234567890123456789012";//16,24,32 1

            txtIV.Text = "1234567890123456";// 16자리

    

        }

 

        private void btn암호화_Click(object sender, EventArgs e)

        {           

            MemoryStream msEncrypt = null;

            CryptoStream csEncrypt = null;

            StreamWriter swEncrypt = null;

            RijndaelManaged aesAlg = null;

 

            aesAlg = new RijndaelManaged();

            aesAlg.Key = Encoding.Default.GetBytes(txtKey.Text);

            aesAlg.IV = Encoding.Default.GetBytes(txtIV.Text);

 

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

 

            msEncrypt = new MemoryStream();

            csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write);

            swEncrypt = new StreamWriter(csEncrypt);

 

            swEncrypt.Write(textBox1.Text);

 

            if (swEncrypt != null) swEncrypt.Close();

            if (csEncrypt != null) csEncrypt.Close();

            if (msEncrypt != null) msEncrypt.Close();

            if (aesAlg != null) aesAlg.Clear();

 

            textBox2.Text = Convert.ToBase64String(msEncrypt.ToArray());

        }

 

        private void btn복호화_Click(object sender, EventArgs e)

        {

            MemoryStream msDecrypt = null;

            CryptoStream csDecrypt = null;

            StreamReader srDecrypt = null;

            RijndaelManaged aesAlg = null;

            string plaintext = null;

 

            aesAlg = new RijndaelManaged();

            aesAlg.Key = Encoding.Default.GetBytes(txtKey.Text);

            aesAlg.IV = Encoding.Default.GetBytes(txtIV.Text);

 

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

 

            byte[] cipherText = Convert.FromBase64String(textBox2.Text);

            msDecrypt = new MemoryStream(cipherText);

            csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read);

            srDecrypt = new StreamReader(csDecrypt);

 

            plaintext = srDecrypt.ReadToEnd();

 

            if (srDecrypt != null)  srDecrypt.Close();

            if (csDecrypt != null)  csDecrypt.Close();

            if (msDecrypt != null)  msDecrypt.Close();

            if (aesAlg != null)    aesAlg.Clear();

 

            textBox3.Text = plaintext;

       }


Posted by penguindori