데이터 암호화

업데이트: 2007년 11월

대칭 암호화와 비대칭 암호화는 서로 다른 프로세스를 사용하여 수행됩니다. 대칭 암호화는 스트림에서 수행되므로 많은 양의 데이터를 암호화하는 데 유용합니다. 비대칭 암호화는 적은 수의 바이트에 대해 수행되므로 데이터 양이 적은 경우에만 유용합니다.

대칭 암호화

관리되는 대칭 암호화 클래스는 스트림에서 읽은 데이터를 암호화하는 CryptoStream이라는 특별한 스트림 클래스와 함께 사용됩니다. CryptoStream 클래스는 관리되는 스트림 클래스를 사용하여 초기화됩니다. 관리되는 스트림 클래스는 암호화 알고리즘을 구현하는 클래스에서 만들어진 ICryptoTransform 인터페이스와 CryptoStream에 허용되는 액세스 유형을 설명하는 CryptoStreamMode 열거형을 구현합니다. CryptoStream 클래스는 FileStream, MemoryStreamNetworkStream을 비롯한 Stream 클래스에서 파생된 클래스를 사용하여 초기화할 수 있습니다. 이러한 클래스를 사용하면 다양한 스트림 개체에 대해 대칭 암호화를 수행할 수 있습니다.

다음 예제에서는 Rijndael 암호화 알고리즘을 구현하는 RijndaelManaged 클래스의 새 인스턴스를 만들고 이 인스턴스를 사용하여 CryptoStream 클래스에 대한 암호화를 수행하는 방법을 보여 줍니다. 이 예제에서 CryptoStream은 관리되는 스트림 형식이 될 수 있는 MyStream이라는 스트림 개체를 사용하여 초기화됩니다. RijndaelManaged 클래스의 CreateEncryptor 메서드에는 암호화에 사용되는 키와 IV가 전달됩니다. 이 경우에는 RMCrypto에서 생성된 IV와 기본 키가 사용됩니다. 마지막으로, CryptoStreamMode.Write가 전달되어 스트림에 대한 쓰기 권한을 지정합니다.

Dim RMCrypto As New RijndaelManaged()
Dim CryptStream As New CryptoStream(MyStream, RMCrypto.CreateEncryptor(RMCrypto.Key, RMCrypto.IV), CryptoStreamMode.Write)
RijndaelManaged RMCrypto = new RijndaelManaged();
CryptoStream CryptStream = new CryptoStream(MyStream, RMCrypto.CreateEncryptor(), CryptoStreamMode.Write);

이 코드가 실행되면 CryptoStream 개체에 쓰여진 데이터는 Rijndael 알고리즘을 사용하여 암호화됩니다.

다음 예제에서는 스트림을 만들고 스트림을 암호화하고 스트림에 데이터를 쓴 다음 스트림을 닫는 전체 프로세스를 보여 줍니다. 이 예제에서는 CryptoStream 클래스와 RijndaelManaged 클래스를 사용하여 암호화되는 네트워크 스트림을 만듭니다. 메시지는 StreamWriter 클래스를 사용하여 암호화된 스트림에 쓰여집니다.

Imports System
Imports System.IO
Imports System.Security.Cryptography
Imports System.Net.Sockets

Module Module1
Sub Main()
   Try
      'Create a TCP connection to a listening TCP process.
      'Use "localhost" to specify the current computer or
      'replace "localhost" with the IP address of the 
      'listening process. 
      Dim TCP As New TcpClient("localhost", 11000)

      'Create a network stream from the TCP connection. 
      Dim NetStream As NetworkStream = TCP.GetStream()

      'Create a new instance of the RijndaelManaged class
      'and encrypt the stream.
      Dim RMCrypto As New RijndaelManaged()

            Dim Key As Byte() = {&H1, &H2, &H3, &H4, &H5, &H6, &H7, &H8, &H9, &H10, &H11, &H12, &H13, &H14, &H15, &H16}
            Dim IV As Byte() = {&H1, &H2, &H3, &H4, &H5, &H6, &H7, &H8, &H9, &H10, &H11, &H12, &H13, &H14, &H15, &H16}

      'Create a CryptoStream, pass it the NetworkStream, and encrypt 
      'it with the Rijndael class.
      Dim CryptStream As New CryptoStream(NetStream, RMCrypto.CreateEncryptor(Key, IV), CryptoStreamMode.Write)

      'Create a StreamWriter for easy writing to the 
      'network stream.
      Dim SWriter As New StreamWriter(CryptStream)

      'Write to the stream.
      SWriter.WriteLine("Hello World!")

      'Inform the user that the message was written
      'to the stream.
      Console.WriteLine("The message was sent.")

      'Close all the connections.
      SWriter.Close()
      CryptStream.Close()
      NetStream.Close()
      TCP.Close()
   Catch
      'Inform the user that an exception was raised.
      Console.WriteLine("The connection failed.")
   End Try
End Sub
End Module
using System;
using System.IO;
using System.Security.Cryptography;
using System.Net.Sockets;
 
public class main
{
   public static void Main(string[] args)
   {
      try
      {
         //Create a TCP connection to a listening TCP process.
         //Use "localhost" to specify the current computer or
         //replace "localhost" with the IP address of the 
         //listening process.  
         TcpClient TCP = new TcpClient("localhost",11000);
   
         //Create a network stream from the TCP connection. 
         NetworkStream NetStream = TCP.GetStream();

         //Create a new instance of the RijndaelManaged class
         // and encrypt the stream.
         RijndaelManaged RMCrypto = new RijndaelManaged();

         byte[] Key = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16};
         byte[] IV = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16};

         //Create a CryptoStream, pass it the NetworkStream, and encrypt 
         //it with the Rijndael class.
         CryptoStream CryptStream = new CryptoStream(NetStream, 
         RMCrypto.CreateEncryptor(Key, IV),   
         CryptoStreamMode.Write);

         //Create a StreamWriter for easy writing to the 
         //network stream.
         StreamWriter SWriter = new StreamWriter(CryptStream);

         //Write to the stream.
         SWriter.WriteLine("Hello World!");

         //Inform the user that the message was written
         //to the stream.
         Console.WriteLine("The message was sent.");

         //Close all the connections.
         SWriter.Close();
         CryptStream.Close();
         NetStream.Close();
         TCP.Close();
      }
      catch
      {
         //Inform the user that an exception was raised.
         Console.WriteLine("The connection failed.");
      }
   }
}

앞의 예제가 올바르게 실행되려면 TCPClient 클래스에 지정된 IP 주소 및 포트 번호를 수신하는 프로세스가 있어야 합니다. 수신 프로세스가 있으면 이 코드에서는 해당 수신 프로세스에 연결하고 Rijndael 대칭 알고리즘을 사용하여 스트림을 암호화한 다음 해당 스트림에 "Hello World!"라는 텍스트를 씁니다. 이 코드가 올바르게 완료되면 콘솔에 다음 텍스트가 표시됩니다.

The message was sent.

그러나 수신 프로세스가 없거나 예외가 발생되는 경우에는 콘솔에 다음 텍스트가 표시됩니다.

The connection failed.

비대칭 암호화

비대칭 알고리즘은 일반적으로 대칭 키 및 IV를 암호화할 때처럼 적은 양의 데이터를 암호화하는 데 사용됩니다. 일반적으로 비대칭 암호화를 수행하는 사용자는 다른 사용자가 생성한 공개 키를 사용합니다. RSACryptoServiceProvider 클래스는 .NET Framework에서 이 목적으로 제공하는 클래스입니다.

다음 예제에서는 공개 키 정보를 사용하여 대칭 키 및 IV를 암호화합니다. 이때 제3자의 공개 키를 나타내는 두 개의 바이트 배열이 초기화됩니다. RSAParameters 개체는 이 값으로 초기화됩니다. 다음에는 RSACryptoServiceProvider.ImportParameters 메서드를 사용하여 RSAParameters 개체와 이 개체가 나타내는 공개 키를 RSACryptoServiceProvider로 가져옵니다. 마지막으로, RijndaelManaged 클래스에서 만든 개인 키와 IV가 암호화됩니다. 이 예제를 실행하려면 시스템에 128비트 암호화 기능이 설치되어 있어야 합니다.

Imports System
Imports System.Security.Cryptography

Module Module1

    Sub Main()
        'Initialize the byte arrays to the public key information.
      Dim PublicKey As Byte() =  {214, 46, 220, 83, 160, 73, 40, 39, 201, 155, 19,202, 3, 11, 191, 178, 56, 74, 90, 36, 248, 103, 18, 144, 170, 163, 145, 87, 54, 61, 34, 220, 222, 207, 137, 149, 173, 14, 92, 120, 206, 222, 158, 28, 40, 24, 30, 16, 175, 108, 128, 35, 230, 118, 40, 121, 113, 125, 216, 130, 11, 24, 90, 48, 194, 240, 105, 44, 76, 34, 57, 249, 228, 125, 80, 38, 9, 136, 29, 117, 207, 139, 168, 181, 85, 137, 126, 10, 126, 242, 120, 247, 121, 8, 100, 12, 201, 171, 38, 226, 193, 180, 190, 117, 177, 87, 143, 242, 213, 11, 44, 180, 113, 93, 106, 99, 179, 68, 175, 211, 164, 116, 64, 148, 226, 254, 172, 147}

        Dim Exponent As Byte() = {1, 0, 1}

        'Create values to store encrypted symmetric keys.
        Dim EncryptedSymmetricKey() As Byte
        Dim EncryptedSymmetricIV() As Byte

        'Create a new instance of the RSACryptoServiceProvider class.
        Dim RSA As New RSACryptoServiceProvider()

        'Create a new instance of the RSAParameters structure.
        Dim RSAKeyInfo As New RSAParameters()

        'Set RSAKeyInfo to the public key values. 
        RSAKeyInfo.Modulus = PublicKey
        RSAKeyInfo.Exponent = Exponent

        'Import key parameters into RSA.
        RSA.ImportParameters(RSAKeyInfo)

        'Create a new instance of the RijndaelManaged class.
        Dim RM As New RijndaelManaged()

        'Encrypt the symmetric key and IV.
        EncryptedSymmetricKey = RSA.Encrypt(RM.Key, False)
        EncryptedSymmetricIV = RSA.Encrypt(RM.IV, False)
    End Sub

End Module
using System;
using System.Security.Cryptography;

class Class1
{
   static void Main()
   {
      //Initialize the byte arrays to the public key information.
      byte[] PublicKey = {214,46,220,83,160,73,40,39,201,155,19,202,3,11,191,178,56,
            74,90,36,248,103,18,144,170,163,145,87,54,61,34,220,222,
            207,137,149,173,14,92,120,206,222,158,28,40,24,30,16,175,
            108,128,35,230,118,40,121,113,125,216,130,11,24,90,48,194,
            240,105,44,76,34,57,249,228,125,80,38,9,136,29,117,207,139,
            168,181,85,137,126,10,126,242,120,247,121,8,100,12,201,171,
            38,226,193,180,190,117,177,87,143,242,213,11,44,180,113,93,
            106,99,179,68,175,211,164,116,64,148,226,254,172,147};

      byte[] Exponent = {1,0,1};
      
      //Create values to store encrypted symmetric keys.
      byte[] EncryptedSymmetricKey;
      byte[] EncryptedSymmetricIV;

      //Create a new instance of the RSACryptoServiceProvider class.
      RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();

      //Create a new instance of the RSAParameters structure.
      RSAParameters RSAKeyInfo = new RSAParameters();

      //Set RSAKeyInfo to the public key values. 
      RSAKeyInfo.Modulus = PublicKey;
      RSAKeyInfo.Exponent = Exponent;

      //Import key parameters into RSA.
      RSA.ImportParameters(RSAKeyInfo);

      //Create a new instance of the RijndaelManaged class.
      RijndaelManaged RM = new RijndaelManaged();

      //Encrypt the symmetric key and IV.
      EncryptedSymmetricKey = RSA.Encrypt(RM.Key, false);
      EncryptedSymmetricIV = RSA.Encrypt(RM.IV, false);
   }
}

참고 항목

개념

암호화 및 해독용 키 생성

데이터 해독

기타 리소스

암호화 작업

암호화 서비스