연습: 암호화 애플리케이션 만들기

참고

이 문서는 Windows에 적용됩니다.

ASP.NET Core 대한 자세한 내용은 ASP.NET Core Data Protection을 참조하세요.

이 연습에서는 파일의 내용을 암호화하고 암호 해독하는 방법을 보여 줍니다. 코드 예제는 Windows Forms 애플리케이션용으로 설계되었습니다. 이 애플리케이션은 스마트 카드 사용과 같은 실제 시나리오를 보여주지 않습니다. 대신, 암호화 및 암호 해독의 기초를 보여 줍니다.

이 연습에서는 암호화에 대한 다음 지침을 사용합니다.

  • 대칭 알고리즘인 Aes 클래스를 사용하여 자동으로 생성된 해당 KeyIV를 통해 데이터를 암호화 및 암호 해독합니다.

  • 비대칭 알고리즘을 RSA 사용하여 키를 암호화하고 에 의해 Aes암호화된 데이터에 대한 암호를 해독합니다. 비대칭 알고리즘은 키와 같은 적은 양의 데이터에 가장 적합합니다.

    참고

    암호화된 콘텐츠를 다른 사용자와 교환하는 대신 컴퓨터의 데이터를 보호하려면 클래스를 ProtectedData 사용하는 것이 좋습니다.

다음 표에는 이 항목의 암호화 작업이 요약되어 있습니다.

Task 설명
Windows Forms 애플리케이션 만들기 애플리케이션을 실행하는 데 필요한 컨트롤을 나열합니다.
전역 개체 선언 Form 클래스의 전역 컨텍스트를 사용하도록 문자열 경로 변수, CspParametersRSACryptoServiceProvider를 선언합니다.
비대칭 키 만들기 비대칭 퍼블릭 및 프라이빗 키-값 쌍을 만들고 키 컨테이너 이름을 할당합니다.
파일 암호화 암호화를 위해 파일을 선택할 수 있는 대화 상자를 표시하고 파일을 암호화합니다.
파일 암호 해독 암호 해독을 위해 암호화된 파일을 선택할 수 있는 대화 상자를 표시하고 파일을 암호 해독합니다.
프라이빗 키 가져오기 키 컨테이너 이름을 사용하여 전체 키 쌍을 가져옵니다.
공개 키 내보내기 public 매개 변수만 사용하여 키를 XML 파일에 저장합니다.
공개 키 가져오기 XML 파일의 키를 키 컨테이너에 로드합니다.
애플리케이션 테스트 이 애플리케이션을 테스트하기 위한 절차를 나열합니다.

필수 구성 요소

이 연습을 완료하려면 다음과 같은 구성 요소가 필요합니다.

Windows Forms 애플리케이션 만들기

이 연습의 대다수 코드 예제는 단추 컨트롤에 대한 이벤트 처리기로 설계되었습니다. 다음 표에서는 샘플 애플리케이션에 필요한 컨트롤 및 코드 예제와 일치하는 데 필요한 이름을 보여 줍니다.

제어 Name 텍스트 속성(필요에 따라)
Button buttonEncryptFile 파일 암호화
Button buttonDecryptFile 파일 암호 해독
Button buttonCreateAsmKeys 키 만들기
Button buttonExportPublicKey 공개 키 내보내기
Button buttonImportPublicKey 공개 키 가져오기
Button buttonGetPrivateKey 프라이빗 키 가져오기
Label label1 키가 설정되지 않음
OpenFileDialog _encryptOpenFileDialog
OpenFileDialog _decryptOpenFileDialog

Visual Studio 디자이너에서 단추를 두 번 클릭하여 이벤트 처리기를 만듭니다.

전역 개체 선언

다음 코드를 Form1 클래스 선언의 일부로 추가합니다. 사용자 환경 및 기본 설정에 맞게 문자열 변수를 편집합니다.

// Declare CspParameters and RsaCryptoServiceProvider
// objects with global scope of your Form class.
readonly CspParameters _cspp = new CspParameters();
RSACryptoServiceProvider _rsa;

// Path variables for source, encryption, and
// decryption folders. Must end with a backslash.
const string EncrFolder = @"c:\Encrypt\";
const string DecrFolder = @"c:\Decrypt\";
const string SrcFolder = @"c:\docs\";

// Public key file
const string PubKeyFile = @"c:\encrypt\rsaPublicKey.txt";

// Key container name for
// private/public key value pair.
const string KeyName = "Key01";
' Declare CspParameters and RsaCryptoServiceProvider
' objects with global scope of your Form class.
ReadOnly _cspp As New CspParameters
Dim _rsa As RSACryptoServiceProvider

' Path variables for source, encryption, and
' decryption folders. Must end with a backslash.
Const EncrFolder As String = "c:\Encrypt\"
Const DecrFolder As String = "c:\Decrypt\"
Const SrcFolder As String = "c:\docs\"

' Public key file
Const PubKeyFile As String = "c:\encrypt\rsaPublicKey.txt"

' Key container name for
' private/public key value pair.
Const KeyName As String = "Key01"

비대칭 키 만들기

이 작업은 Aes 키를 암호화 및 암호 해독하는 비대칭 키를 만듭니다. 이 키는 콘텐츠를 암호화하는 데 사용되었으며 레이블 컨트롤에 키 컨테이너 이름을 표시합니다.

Create Keys 단추(buttonCreateAsmKeys_Click)에 대한 Click 이벤트 처리기로 다음 코드를 추가합니다.

private void buttonCreateAsmKeys_Click(object sender, EventArgs e)
{
    // Stores a key pair in the key container.
    _cspp.KeyContainerName = KeyName;
    _rsa = new RSACryptoServiceProvider(_cspp)
    {
        PersistKeyInCsp = true
    };

    label1.Text = _rsa.PublicOnly
        ? $"Key: {_cspp.KeyContainerName} - Public Only"
        : $"Key: {_cspp.KeyContainerName} - Full Key Pair";
}
Private Sub buttonCreateAsmKeys_Click(ByVal sender As Object, ByVal e As EventArgs) Handles buttonCreateAsmKeys.Click
    ' Stores a key pair in the key container.
    _cspp.KeyContainerName = KeyName
    _rsa = New RSACryptoServiceProvider(_cspp) With {
        .PersistKeyInCsp = True
    }

    If _rsa.PublicOnly Then
        Label1.Text = $"Key: {_cspp.KeyContainerName} - Public Only"
    Else
        Label1.Text = $"Key: {_cspp.KeyContainerName} - Full Key Pair"
    End If

End Sub

파일 암호화

이 작업에는 단추(buttonEncryptFile_Click)에 대한 이벤트 처리기 메서드와 메서드의 Encrypt File 두 가지 메서드가 EncryptFile 포함됩니다. 첫 번째 메서드는 파일을 선택할 수 있는 대화 상자를 표시하고 암호화를 수행하는 두 번째 메서드에 파일 이름을 전달합니다.

암호화된 콘텐츠, 키 및 IV가 모두 하나의 FileStream에 저장되며, 이를 암호화 패키지라고 합니다.

EncryptFile 메서드는 다음 작업을 수행합니다.

  1. Aes 대칭 알고리즘을 만들어 콘텐츠를 암호화합니다.
  2. RSACryptoServiceProvider 개체를 만들어 Aes 키를 암호화합니다.
  3. CryptoStream 개체를 사용하여 소스 파일의 FileStream을 바이트 블록 단위로 암호화된 파일의 대상 FileStream 개체로 읽고 암호화합니다.
  4. 암호화된 키 및 IV의 길이를 확인하고 해당 길이 값의 바이트 배열을 만듭니다.
  5. 암호화된 패키지에 키, IV 및 해당 길이 값을 씁니다.

암호화 패키지는 다음 형식을 사용합니다.

  • 키 길이, 0-3바이트
  • IV 길이, 4-7바이트
  • 암호화된 키
  • IV
  • 암호화 텍스트

키 및 IV의 길이를 사용하여 파일을 암호 해독하는 데 사용할 수 있는 암호화 패키지의 모든 부분에 대한 시작 지점 및 길이를 확인할 수 있습니다.

Encrypt File 단추(buttonEncryptFile_Click)에 대한 Click 이벤트 처리기로 다음 코드를 추가합니다.

private void buttonEncryptFile_Click(object sender, EventArgs e)
{
    if (_rsa is null)
    {
        MessageBox.Show("Key not set.");
    }
    else
    {
        // Display a dialog box to select a file to encrypt.
        _encryptOpenFileDialog.InitialDirectory = SrcFolder;
        if (_encryptOpenFileDialog.ShowDialog() == DialogResult.OK)
        {
            string fName = _encryptOpenFileDialog.FileName;
            if (fName != null)
            {
                // Pass the file name without the path.
                EncryptFile(new FileInfo(fName));
            }
        }
    }
}
Private Sub buttonEncryptFile_Click(ByVal sender As Object, ByVal e As EventArgs) Handles buttonEncryptFile.Click
    If _rsa Is Nothing Then
        MsgBox("Key not set.")
    Else
        ' Display a dialog box to select a file to encrypt.
        _encryptOpenFileDialog.InitialDirectory = SrcFolder
        If _encryptOpenFileDialog.ShowDialog = Windows.Forms.DialogResult.OK Then
            Try
                Dim fName As String = _encryptOpenFileDialog.FileName
                If (Not (fName) Is Nothing) Then
                    Dim fInfo As New FileInfo(fName)
                    ' Use just the file name without path.
                    Dim name As String = fInfo.FullName
                    EncryptFile(name)
                End If
            Catch ex As Exception
                MsgBox(ex.Message)
            End Try
        End If
    End If
End Sub

다음 EncryptFile 메서드를 폼에 추가합니다.

private void EncryptFile(FileInfo file)
{
    // Create instance of Aes for
    // symmetric encryption of the data.
    Aes aes = Aes.Create();
    ICryptoTransform transform = aes.CreateEncryptor();

    // Use RSACryptoServiceProvider to
    // encrypt the AES key.
    // rsa is previously instantiated:
    //    rsa = new RSACryptoServiceProvider(cspp);
    byte[] keyEncrypted = _rsa.Encrypt(aes.Key, false);

    // Create byte arrays to contain
    // the length values of the key and IV.
    int lKey = keyEncrypted.Length;
    byte[] LenK = BitConverter.GetBytes(lKey);
    int lIV = aes.IV.Length;
    byte[] LenIV = BitConverter.GetBytes(lIV);

    // Write the following to the FileStream
    // for the encrypted file (outFs):
    // - length of the key
    // - length of the IV
    // - encrypted key
    // - the IV
    // - the encrypted cipher content

    // Change the file's extension to ".enc"
    string outFile =
        Path.Combine(EncrFolder, Path.ChangeExtension(file.Name, ".enc"));

    using (var outFs = new FileStream(outFile, FileMode.Create))
    {
        outFs.Write(LenK, 0, 4);
        outFs.Write(LenIV, 0, 4);
        outFs.Write(keyEncrypted, 0, lKey);
        outFs.Write(aes.IV, 0, lIV);

        // Now write the cipher text using
        // a CryptoStream for encrypting.
        using (var outStreamEncrypted =
            new CryptoStream(outFs, transform, CryptoStreamMode.Write))
        {
            // By encrypting a chunk at
            // a time, you can save memory
            // and accommodate large files.
            int count = 0;
            int offset = 0;

            // blockSizeBytes can be any arbitrary size.
            int blockSizeBytes = aes.BlockSize / 8;
            byte[] data = new byte[blockSizeBytes];
            int bytesRead = 0;

            using (var inFs = new FileStream(file.FullName, FileMode.Open))
            {
                do
                {
                    count = inFs.Read(data, 0, blockSizeBytes);
                    offset += count;
                    outStreamEncrypted.Write(data, 0, count);
                    bytesRead += blockSizeBytes;
                } while (count > 0);
            }
            outStreamEncrypted.FlushFinalBlock();
        }
    }
}
Private Sub EncryptFile(ByVal inFile As String)
    ' Create instance of Aes for
    ' symmetric encryption of the data.
    Dim aes As Aes = Aes.Create()
    Dim transform As ICryptoTransform = aes.CreateEncryptor

    ' Use RSACryptoServiceProvider to
    ' encrypt the AES key.
    Dim keyEncrypted() As Byte = _rsa.Encrypt(aes.Key, False)

    ' Create byte arrays to contain
    ' the length values of the key and IV.
    Dim LenK() As Byte = New Byte((4) - 1) {}
    Dim LenIV() As Byte = New Byte((4) - 1) {}
    Dim lKey As Integer = keyEncrypted.Length
    LenK = BitConverter.GetBytes(lKey)
    Dim lIV As Integer = aes.IV.Length
    LenIV = BitConverter.GetBytes(lIV)

    ' Write the following to the FileStream
    ' for the encrypted file (outFs):
    ' - length of the key
    ' - length of the IV
    ' - encrypted key
    ' - the IV
    ' - the encrypted cipher content
    ' Change the file's extension to ".enc"
    Dim startFileName As Integer = inFile.LastIndexOf("\") + 1
    Dim outFile As String = (EncrFolder _
                + (inFile.Substring(startFileName, inFile.LastIndexOf(".") - startFileName) + ".enc"))

    Using outFs As New FileStream(outFile, FileMode.Create)
        outFs.Write(LenK, 0, 4)
        outFs.Write(LenIV, 0, 4)
        outFs.Write(keyEncrypted, 0, lKey)
        outFs.Write(aes.IV, 0, lIV)

        ' Now write the cipher text using
        ' a CryptoStream for encrypting.
        Using outStreamEncrypted As New CryptoStream(outFs, transform, CryptoStreamMode.Write)
            ' By encrypting a chunk at
            ' a time, you can save memory
            ' and accommodate large files.
            Dim count As Integer = 0
            Dim offset As Integer = 0

            ' blockSizeBytes can be any arbitrary size.
            Dim blockSizeBytes As Integer = (aes.BlockSize / 8)
            Dim data() As Byte = New Byte((blockSizeBytes) - 1) {}
            Dim bytesRead As Integer = 0
            Using inFs As New FileStream(inFile, FileMode.Open)
                Do
                    count = inFs.Read(data, 0, blockSizeBytes)
                    offset = (offset + count)
                    outStreamEncrypted.Write(data, 0, count)
                    bytesRead = (bytesRead + blockSizeBytes)
                Loop Until (count = 0)

                outStreamEncrypted.FlushFinalBlock()
                inFs.Close()
            End Using
            outStreamEncrypted.Close()
        End Using
        outFs.Close()
    End Using
End Sub

파일 암호 해독

이 작업에는 Decrypt File 단추에 대한 이벤트 처리기 메서드(buttonDecryptFile_Click) 및 DecryptFile 메서드의 두 메서드가 필요합니다. 첫 번째 메서드는 파일을 선택할 수 있는 대화 상자를 표시하고 암호 해독을 수행하는 두 번째 메서드에 파일 이름을 전달합니다.

Decrypt 메서드는 다음 작업을 수행합니다.

  1. Aes 콘텐츠를 해독하는 대칭 알고리즘을 만듭니다.
  2. 암호화된 패키지 FileStream의 처음 8바이트를 바이트 배열로 읽어 암호화된 키 및 IV의 길이를 가져옵니다.
  3. 암호화 패키지에서 바이트 배열로 키 및 IV를 추출합니다.
  4. RSACryptoServiceProvider 개체를 만들어 Aes 키를 암호 해독합니다.
  5. CryptoStream 개체를 사용하여 FileStream 암호화 패키지의 암호화 텍스트 섹션을 바이트 블록 단위로 암호 해독된 파일의 FileStream 개체로 읽고 암호 해독합니다. 이 작업을 완료하면 암호 해독이 완료됩니다.

Decrypt File 단추에 대한 Click 이벤트 처리기로 다음 코드를 추가합니다.

private void buttonDecryptFile_Click(object sender, EventArgs e)
{
    if (_rsa is null)
    {
        MessageBox.Show("Key not set.");
    }
    else
    {
        // Display a dialog box to select the encrypted file.
        _decryptOpenFileDialog.InitialDirectory = EncrFolder;
        if (_decryptOpenFileDialog.ShowDialog() == DialogResult.OK)
        {
            string fName = _decryptOpenFileDialog.FileName;
            if (fName != null)
            {
                DecryptFile(new FileInfo(fName));
            }
        }
    }
}
Private Sub buttonDecryptFile_Click(ByVal sender As Object, ByVal e As EventArgs) Handles buttonDecryptFile.Click
    If _rsa Is Nothing Then
        MsgBox("Key not set.")
    Else
        ' Display a dialog box to select the encrypted file.
        _decryptOpenFileDialog.InitialDirectory = EncrFolder
        If (_decryptOpenFileDialog.ShowDialog = Windows.Forms.DialogResult.OK) Then
            Try
                Dim fName As String = _decryptOpenFileDialog.FileName
                If ((fName) IsNot Nothing) Then
                    Dim fi As New FileInfo(fName)
                    Dim name As String = fi.Name
                    DecryptFile(name)
                End If
            Catch ex As Exception
                MessageBox.Show(ex.Message)
            End Try
        End If
    End If
End Sub

다음 DecryptFile 메서드를 폼에 추가합니다.

private void DecryptFile(FileInfo file)
{
    // Create instance of Aes for
    // symmetric decryption of the data.
    Aes aes = Aes.Create();

    // Create byte arrays to get the length of
    // the encrypted key and IV.
    // These values were stored as 4 bytes each
    // at the beginning of the encrypted package.
    byte[] LenK = new byte[4];
    byte[] LenIV = new byte[4];

    // Construct the file name for the decrypted file.
    string outFile =
        Path.ChangeExtension(file.FullName.Replace("Encrypt", "Decrypt"), ".txt");

    // Use FileStream objects to read the encrypted
    // file (inFs) and save the decrypted file (outFs).
    using (var inFs = new FileStream(file.FullName, FileMode.Open))
    {
        inFs.Seek(0, SeekOrigin.Begin);
        inFs.Read(LenK, 0, 3);
        inFs.Seek(4, SeekOrigin.Begin);
        inFs.Read(LenIV, 0, 3);

        // Convert the lengths to integer values.
        int lenK = BitConverter.ToInt32(LenK, 0);
        int lenIV = BitConverter.ToInt32(LenIV, 0);

        // Determine the start position of
        // the cipher text (startC)
        // and its length(lenC).
        int startC = lenK + lenIV + 8;
        int lenC = (int)inFs.Length - startC;

        // Create the byte arrays for
        // the encrypted Aes key,
        // the IV, and the cipher text.
        byte[] KeyEncrypted = new byte[lenK];
        byte[] IV = new byte[lenIV];

        // Extract the key and IV
        // starting from index 8
        // after the length values.
        inFs.Seek(8, SeekOrigin.Begin);
        inFs.Read(KeyEncrypted, 0, lenK);
        inFs.Seek(8 + lenK, SeekOrigin.Begin);
        inFs.Read(IV, 0, lenIV);

        Directory.CreateDirectory(DecrFolder);
        // Use RSACryptoServiceProvider
        // to decrypt the AES key.
        byte[] KeyDecrypted = _rsa.Decrypt(KeyEncrypted, false);

        // Decrypt the key.
        ICryptoTransform transform = aes.CreateDecryptor(KeyDecrypted, IV);

        // Decrypt the cipher text from
        // from the FileSteam of the encrypted
        // file (inFs) into the FileStream
        // for the decrypted file (outFs).
        using (var outFs = new FileStream(outFile, FileMode.Create))
        {
            int count = 0;
            int offset = 0;

            // blockSizeBytes can be any arbitrary size.
            int blockSizeBytes = aes.BlockSize / 8;
            byte[] data = new byte[blockSizeBytes];

            // By decrypting a chunk a time,
            // you can save memory and
            // accommodate large files.

            // Start at the beginning
            // of the cipher text.
            inFs.Seek(startC, SeekOrigin.Begin);
            using (var outStreamDecrypted =
                new CryptoStream(outFs, transform, CryptoStreamMode.Write))
            {
                do
                {
                    count = inFs.Read(data, 0, blockSizeBytes);
                    offset += count;
                    outStreamDecrypted.Write(data, 0, count);
                } while (count > 0);

                outStreamDecrypted.FlushFinalBlock();
            }
        }
    }
}
Private Sub DecryptFile(ByVal inFile As String)
    ' Create instance of Aes for
    ' symmetric decryption of the data.
    Dim aes As Aes = Aes.Create()

    ' Create byte arrays to get the length of
    ' the encrypted key and IV.
    ' These values were stored as 4 bytes each
    ' at the beginning of the encrypted package.
    Dim LenK() As Byte = New Byte(4 - 1) {}
    Dim LenIV() As Byte = New Byte(4 - 1) {}

    ' Construct the file name for the decrypted file.
    Dim outFile As String = (DecrFolder _
                + (inFile.Substring(0, inFile.LastIndexOf(".")) + ".txt"))

    ' Use FileStream objects to read the encrypted
    ' file (inFs) and save the decrypted file (outFs).
    Using inFs As New FileStream((EncrFolder + inFile), FileMode.Open)

        inFs.Seek(0, SeekOrigin.Begin)
        inFs.Read(LenK, 0, 3)
        inFs.Seek(4, SeekOrigin.Begin)
        inFs.Read(LenIV, 0, 3)

        Dim lengthK As Integer = BitConverter.ToInt32(LenK, 0)
        Dim lengthIV As Integer = BitConverter.ToInt32(LenIV, 0)
        Dim startC As Integer = (lengthK + lengthIV + 8)
        Dim lenC As Integer = (CType(inFs.Length, Integer) - startC)
        Dim KeyEncrypted() As Byte = New Byte(lengthK - 1) {}
        Dim IV() As Byte = New Byte(lengthIV - 1) {}

        ' Extract the key and IV
        ' starting from index 8
        ' after the length values.
        inFs.Seek(8, SeekOrigin.Begin)
        inFs.Read(KeyEncrypted, 0, lengthK)
        inFs.Seek(8 + lengthK, SeekOrigin.Begin)
        inFs.Read(IV, 0, lengthIV)
        Directory.CreateDirectory(DecrFolder)
        ' User RSACryptoServiceProvider
        ' to decrypt the AES key
        Dim KeyDecrypted() As Byte = _rsa.Decrypt(KeyEncrypted, False)

        ' Decrypt the key.
        Dim transform As ICryptoTransform = aes.CreateDecryptor(KeyDecrypted, IV)
        ' Decrypt the cipher text from
        ' from the FileSteam of the encrypted
        ' file (inFs) into the FileStream
        ' for the decrypted file (outFs).
        Using outFs As New FileStream(outFile, FileMode.Create)
            Dim count As Integer = 0
            Dim offset As Integer = 0

            ' blockSizeBytes can be any arbitrary size.
            Dim blockSizeBytes As Integer = (aes.BlockSize / 8)
            Dim data() As Byte = New Byte(blockSizeBytes - 1) {}
            ' By decrypting a chunk a time,
            ' you can save memory and
            ' accommodate large files.
            ' Start at the beginning
            ' of the cipher text.
            inFs.Seek(startC, SeekOrigin.Begin)
            Using outStreamDecrypted As New CryptoStream(outFs, transform, CryptoStreamMode.Write)
                Do
                    count = inFs.Read(data, 0, blockSizeBytes)
                    offset += count
                    outStreamDecrypted.Write(data, 0, count)
                Loop Until (count = 0)

                outStreamDecrypted.FlushFinalBlock()
            End Using
        End Using
    End Using
End Sub

공개 키 내보내기

이 작업은 Create Keys 단추를 사용하여 만든 키를 파일에 저장합니다. public 매개 변수만 내보냅니다.

이 작업은 Bob이 파일을 암호화할 수 있도록 Alice가 Bob에게 공개 키를 제공하는 시나리오를 시뮬레이트합니다. Bob과 해당 공개 키를 가진 다른 사용자는 private 매개 변수가 있는 전체 키 쌍이 없기 때문에 파일을 암호 해독할 수 없습니다.

Export Public Key 단추(buttonExportPublicKey_Click)에 대한 Click 이벤트 처리기로 다음 코드를 추가합니다.

void buttonExportPublicKey_Click(object sender, EventArgs e)
{
    // Save the public key created by the RSA
    // to a file. Caution, persisting the
    // key to a file is a security risk.
    Directory.CreateDirectory(EncrFolder);
    using (var sw = new StreamWriter(PubKeyFile, false))
    {
        sw.Write(_rsa.ToXmlString(false));
    }
}
Private Sub buttonExportPublicKey_Click(ByVal sender As Object, ByVal e As EventArgs) Handles buttonExportPublicKey.Click
    ' Save the public key created by the RSA
    ' to a file. Caution, persisting the
    ' key to a file is a security risk.
    Directory.CreateDirectory(EncrFolder)
    Using sw As New StreamWriter(PubKeyFile)
        sw.Write(_rsa.ToXmlString(False))
    End Using
End Sub

공개 키 가져오기

이 작업은 Export Public Key 단추를 사용하여 만든 public 매개 변수만 있는 키를 로드하고 키 컨테이너 이름으로 설정합니다.

이 작업은 Bob이 파일을 암호화할 수 있도록 public 매개 변수만 있는 Alice의 키를 Bob이 로드하는 시나리오를 시뮬레이트합니다.

Import Public Key 단추(buttonImportPublicKey_Click)에 대한 Click 이벤트 처리기로 다음 코드를 추가합니다.

void buttonImportPublicKey_Click(object sender, EventArgs e)
{
    using (var sr = new StreamReader(PubKeyFile))
    {
        _cspp.KeyContainerName = KeyName;
        _rsa = new RSACryptoServiceProvider(_cspp);

        string keytxt = sr.ReadToEnd();
        _rsa.FromXmlString(keytxt);
        _rsa.PersistKeyInCsp = true;

        label1.Text = _rsa.PublicOnly
            ? $"Key: {_cspp.KeyContainerName} - Public Only"
            : $"Key: {_cspp.KeyContainerName} - Full Key Pair";
    }
}
Private Sub buttonImportPublicKey_Click(ByVal sender As Object, ByVal e As EventArgs) Handles buttonImportPublicKey.Click
    Using sr As New StreamReader(PubKeyFile)
        _cspp.KeyContainerName = KeyName
        _rsa = New RSACryptoServiceProvider(_cspp)
        Dim keytxt As String = sr.ReadToEnd
        _rsa.FromXmlString(keytxt)
        _rsa.PersistKeyInCsp = True

        If _rsa.PublicOnly Then
            Label1.Text = $"Key: {_cspp.KeyContainerName} - Public Only"
        Else
            Label1.Text = $"Key: {_cspp.KeyContainerName} - Full Key Pair"
        End If
    End Using
End Sub

프라이빗 키 가져오기

이 작업은 키 컨테이너 이름을 Create Keys 단추를 사용하여 만든 키의 이름으로 설정합니다. 키 컨테이너는 private 매개 변수가 있는 전체 키 쌍을 포함합니다.

이 작업은 Alice가 프라이빗 키를 사용하여 Bob이 암호화한 파일을 암호 해독하는 시나리오를 시뮬레이트합니다.

Get Private Key 단추(buttonGetPrivateKey_Click)에 대한 Click 이벤트 처리기로 다음 코드를 추가합니다.

private void buttonGetPrivateKey_Click(object sender, EventArgs e)
{
    _cspp.KeyContainerName = KeyName;
    _rsa = new RSACryptoServiceProvider(_cspp)
    {
        PersistKeyInCsp = true
    };

    label1.Text = _rsa.PublicOnly
        ? $"Key: {_cspp.KeyContainerName} - Public Only"
        : $"Key: {_cspp.KeyContainerName} - Full Key Pair";
}
Private Sub buttonGetPrivateKey_Click(ByVal sender As Object,
    ByVal e As EventArgs) Handles buttonGetPrivateKey.Click
    _cspp.KeyContainerName = KeyName
    _rsa = New RSACryptoServiceProvider(_cspp) With {
        .PersistKeyInCsp = True
    }
    If _rsa.PublicOnly Then
        Label1.Text = $"Key: {_cspp.KeyContainerName} - Public Only"
    Else
        Label1.Text = $"Key: {_cspp.KeyContainerName} - Full Key Pair"
    End If
End Sub

애플리케이션 테스트

애플리케이션을 빌드한 후 다음과 같은 테스트 시나리오를 수행합니다.

키를 만들고 암호화 및 암호 해독하려면

  1. Create Keys 단추를 클릭합니다. 레이블이 키 이름을 표시하고 전체 키 쌍임을 보여 줍니다.
  2. Export Public Key 단추를 클릭합니다. 공개 키 매개 변수를 내보내는 경우 현재 키가 변경되지 않습니다.
  3. Encrypt File 단추를 클릭하고 파일을 선택합니다.
  4. Decrypt File 단추를 클릭하고 방금 암호화한 파일을 선택합니다.
  5. 방금 암호 해독한 파일을 검사합니다.
  6. 애플리케이션을 닫고 다음 시나리오에서 지속형 키 컨테이너 검색을 테스트하기 위해 다시 시작합니다.

공개 키를 사용하여 암호화하려면

  1. Import Public Key 단추를 클릭합니다. 레이블이 키 이름을 표시하고 public 전용임을 보여 줍니다.
  2. Encrypt File 단추를 클릭하고 파일을 선택합니다.
  3. Decrypt File 단추를 클릭하고 방금 암호화한 파일을 선택합니다. 암호 해독하려면 프라이빗 키가 있어야 하므로 이 작업은 실패합니다.

이 시나리오에서는 다른 사용자를 위해 파일을 암호화할 공개 키만 있는 경우를 보여 줍니다. 일반적으로 해당 사용자는 퍼블릭 키만 제공하고 암호 해독을 위한 프라이빗 키는 보유합니다.

프라이빗 키를 사용하여 암호 해독하려면

  1. Get Private Key 단추를 클릭합니다. 레이블이 키 이름을 표시하고 전체 키 쌍인지 여부를 보여 줍니다.
  2. Decrypt File 단추를 클릭하고 방금 암호화한 파일을 선택합니다. 암호 해독을 위한 전체 키 쌍이 있으므로 이 작업은 성공합니다.

추가 정보