Share via


逐步解說:建立密碼編譯應用程式

更新:2007 年 11 月

本逐步解說示範如何加密和解密內容。這些程式碼範例是為 Windows Form 應用程式所設計。這個應用程式不會示範使用智慧卡之類的實際生活案例,而是會示範加密和解密的基本工作。

本逐步解說使用下列方針進行加密:

  • 使用對稱演算法 RijndaelManaged 類別 (Class),利用其自動產生的 KeyIV 來加密和解密資料。

  • 使用非對稱演算法 RSACryptoServiceProvider,將金鑰 (Key) 加密和解密成 RijndaelManaged 所加密的資料。非對稱演算法最適用於例如金鑰的小量資料。

    注意事項:

    如果您是要保護電腦上的資料,而非與他人交換加密的內容,請考慮使用 ProtectedDataProtectedMemory 類別。

下表摘要本主題中的密碼編譯工作。

工作

描述

建立 Windows Form 應用程式

列出執行應用程式時的必要控制項。

宣告全域物件

宣告字串路徑變數,即 CspParametersRSACryptoServiceProvider,以指定 Form 類別的全域內容。

建立非對稱金鑰

建立非對稱的公開 (Public) 和私密金鑰值組,並對其指派金鑰容器 (Container) 名稱。

加密檔案

顯示可選取要加密和解密之檔案的對話方塊。

解密檔案

顯示可選取要解密之已加密檔案的對話方塊,然後解密該檔案。

取得私密金鑰

使用金鑰容器名稱取得完整的金鑰組 (Key Pair)。

匯出公開金鑰

將金鑰儲存至僅包含公用參數的 XML 檔。

匯入公開金鑰

從 XML 檔將金鑰載入至金鑰容器。

測試應用程式

列出測試此應用程式的程序。

必要條件

您需要下列元件才能完成此逐步解說:

建立 Windows Form 應用程式

本逐步解說中的大多數程式碼範例都是設計成按鈕控制項的事件處理常式。下表列出範例應用程式所需要的控制項,以及要與程式碼範例相符的必要名稱。

控制項

名稱

文字屬性 (視需要而定)

Button

buttonEncryptFile

加密檔案

Button

buttonDecryptFile

解密檔案

Button

buttonCreateAsmKeys

建立金鑰

Button

buttonExportPublicKey

匯出公開金鑰

Button

buttonImportPublicKey

匯入公開金鑰

Button

buttonGetPrivateKey

取得私密金鑰

Label

label1

OpenFileDialog

openFileDialog1

OpenFileDialog

openFileDialog2

按兩下 Visual Studio 設計工具中的按鈕,即可建立其事件處理常式。

宣告全域物件

將下列程式碼範例加入 Form 的建構函式 (Constructor)。編輯環境和偏好設定的字串變數。

' Declare CspParmeters and RsaCryptoServiceProvider 
' objects with global scope of your Form class.
Dim cspp As CspParameters = New System.Security.Cryptography.CspParameters
Dim rsa As RSACryptoServiceProvider

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

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

' Key container name for
' private/public key value pair.
Dim keyName As String = "Key01"
// Declare CspParmeters and RsaCryptoServiceProvider
// objects with global scope of your Form class.
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";

建立非對稱金鑰

這項工作會建立加密和解密 RijndaelManaged 金鑰的非對稱金鑰。此金鑰先前用來加密內容,會在標籤控制項上顯示金鑰容器名稱。

將下列程式碼加入至 Create Keys 按鈕 (buttonCreateAsmKeys_Click) 的 Click 事件處理常式。

Private Sub buttonCreateAsmKeys_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles buttonCreateAsmKeys.Click
    ' Stores a key pair in the key container.
    cspp.KeyContainerName = keyName
    rsa = New RSACryptoServiceProvider(cspp)
    rsa.PersistKeyInCsp = True

    If rsa.PublicOnly = True Then
        Label1.Text = "Key: " + cspp.KeyContainerName + " - Public Only"
    Else
        Label1.Text = "Key: " + cspp.KeyContainerName + " - Full Key Pair"
    End If

End Sub
private void buttonCreateAsmKeys_Click(object sender, System.EventArgs e)
{
    // Stores a key pair in the key container.
    cspp.KeyContainerName = keyName;
    rsa = new RSACryptoServiceProvider(cspp);
    rsa.PersistKeyInCsp = true;
    if (rsa.PublicOnly == true)
       label1.Text = "Key: " + cspp.KeyContainerName + " - Public Only";
    else
       label1.Text = "Key: " + cspp.KeyContainerName + " - Full Key Pair";

}

加密檔案

這項工作牽涉到兩個方法:Encrypt File 按鈕 (buttonEncryptFile_Click) 的事件處理常式方法,以及 EncryptFile 方法。第一個方法會顯示用來選取檔案的對話方塊,接著會將該檔案名稱傳遞給負責執行加密的第二個方法。

所加密的內容、金鑰和 IV 都會儲存到稱為加密套件的 FileStream

EncryptFile 方法會執行下列事項:

  1. 建立 RijndaelManaged 對稱演算法以加密內容。

  2. 建立 RSACryptoServiceProvider 物件以加密 RijndaelManaged 金鑰。

  3. 使用 CryptoStream 物件讀取原始程式檔 (Source File) 的 FileStream (以位元組區塊為單位),並將其加密至已加密檔案的目的 FileStream 物件。

  4. 判斷加密金鑰和 IV 的長度,並建立其長度值的位元組陣列。

  5. 將金鑰、IV 及其長度值寫入該加密套件。

加密套件會使用下列格式:

  • 金鑰長度,位元組 0 - 3

  • IV 長度,位元組 4 - 7

  • 加密金鑰

  • IV

  • 加密文字

您可以使用金鑰和 IV 的長度判斷加密套件之所有部分的起點和長度,接著便可用於解密檔案。

將下列程式碼加入至 Encrypt File 按鈕 (buttonEncryptFile_Click) 的 Click 事件處理常式。

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

        // Display a dialog box to select a file to encrypt.
        openFileDialog1.InitialDirectory = SrcFolder;
        if (openFileDialog1.ShowDialog() == DialogResult.OK)
        {
            string fName = openFileDialog1.FileName;
            if (fName != null)
            {
                FileInfo fInfo = new FileInfo(fName);
                // Pass the file name without the path.
                string name = fInfo.Name;
                EncryptFile(name);
            }
        }
    }
}

將下列 EncryptFile 方法加入至表單。

Private Sub EncryptFile(ByVal inFile As String)

    ' Create instance of Rijndael for
    ' symetric encryption of the data.
    Dim rjndl As RijndaelManaged = New RijndaelManaged
    rjndl.KeySize = 256
    rjndl.BlockSize = 256
    rjndl.Mode = CipherMode.CBC
    Dim transform As ICryptoTransform = rjndl.CreateEncryptor

    ' Use RSACryptoServiceProvider to 
    ' enrypt the Rijndael key.
    Dim keyEncrypted() As Byte = rsa.Encrypt(rjndl.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 = rjndl.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
    ' - ecrypted key
    ' - the IV
    ' - the encrypted cipher content
    ' Change the file's extension to ".enc"

    Dim outFile As String = (EncrFolder _
                + (inFile.Substring(0, inFile.LastIndexOf(".")) + ".enc"))

    Using outFs As FileStream = New FileStream(outFile, FileMode.Create)

        outFs.Write(LenK, 0, 4)
        outFs.Write(LenIV, 0, 4)
        outFs.Write(keyEncrypted, 0, lKey)
        outFs.Write(rjndl.IV, 0, lIV)

        ' Now write the cipher text using
        ' a CryptoStream for encrypting.
        Using outStreamEncrypted As CryptoStream = 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 = (rjndl.BlockSize / 8)
            Dim data() As Byte = New Byte((blockSizeBytes) - 1) {}
            Dim bytesRead As Integer = 0
            Using inFs As FileStream = 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
private void EncryptFile(string inFile)
{

    // Create instance of Rijndael for
    // symetric encryption of the data.
    RijndaelManaged rjndl = new RijndaelManaged();
    rjndl.KeySize = 256;
    rjndl.BlockSize = 256;
    rjndl.Mode = CipherMode.CBC;
    ICryptoTransform transform = rjndl.CreateEncryptor();

    // Use RSACryptoServiceProvider to
    // enrypt the Rijndael key.
    byte[] keyEncrypted = rsa.Encrypt(rjndl.Key, false);

    // Create byte arrays to contain
    // the length values of the key and IV.
    byte[] LenK = new byte[4];
    byte[] LenIV = new byte[4];

    int lKey = keyEncrypted.Length;
    LenK = BitConverter.GetBytes(lKey);
    int lIV = rjndl.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
    // - ecrypted key
    // - the IV
    // - the encrypted cipher content

   // Change the file's extension to ".enc"
    string outFile = EncrFolder + inFile.Substring(0, inFile.LastIndexOf(".")) + ".enc";

    using (FileStream outFs = new FileStream(outFile, FileMode.Create))
    {

            outFs.Write(LenK, 0, 4);
            outFs.Write(LenIV, 0, 4);
            outFs.Write(keyEncrypted, 0, lKey);
            outFs.Write(rjndl.IV, 0, lIV);

            // Now write the cipher text using
            // a CryptoStream for encrypting.
            using (CryptoStream 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 = rjndl.BlockSize / 8;
                byte[] data = new byte[blockSizeBytes];
                int bytesRead = 0;

                using (FileStream inFs = new FileStream(inFile, FileMode.Open))
                {
                    do
                    {
                        count = inFs.Read(data, 0, blockSizeBytes);
                        offset += count;
                        outStreamEncrypted.Write(data, 0, count);
                        bytesRead += blockSizeBytes;
                    }
                    while (count > 0);
                inFs.Close();
                }
                outStreamEncrypted.FlushFinalBlock();
                outStreamEncrypted.Close();
            }
            outFs.Close();
    }

}

解密檔案

這項工作牽涉到兩個方法:Decrypt File 按鈕 (buttonEncryptFile_Click) 的事件處理常式方法,以及 DecryptFile 方法。第一個方法會顯示用來選取檔案的對話方塊,接著會將該檔案名稱傳遞給負責執行解密的第二個方法。

Decrypt 方法會執行下列事項:

  1. 建立 RijndaelManaged 對稱演算法以解密內容。

  2. 將加密套件之 FileStream 的前八個位元組讀取到位元組陣列中,以取得加密金鑰和 IV 的長度。

  3. 從加密套件將金鑰和 IV 擷取到位元組陣列中。

  4. 建立 RSACryptoServiceProvider 物件以解密 RijndaelManaged 金鑰。

  5. 使用 CryptoStream 物件讀取 FileStream 加密套件的加密文字區段 (以位元組區塊為單位),並將其解密到已解密檔案的 FileStream 物件。完成這個作業時,表示解密已完成。

將下列程式碼加入至 Decrypt File 按鈕的 Click 事件處理常式。

Private Sub buttonDecryptFile_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles buttonDecryptFile.Click
    If rsa Is Nothing Then
        MsgBox("Key not set.")
    Else
        ' Display a dialog box to select the encrypted file.
        OpenFileDialog2.InitialDirectory = EncrFolder
        If (OpenFileDialog2.ShowDialog = Windows.Forms.DialogResult.OK) Then
            Try
                Dim fName As String = OpenFileDialog2.FileName
                If (Not (fName) Is Nothing) Then
                    Dim fi As FileInfo = 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
private void buttonDecryptFile_Click(object sender, EventArgs e)
{
    if (rsa == null)
        MessageBox.Show("Key not set.");
    else
    {
        // Display a dialog box to select the encrypted file.
        openFileDialog2.InitialDirectory = EncrFolder;
        if (openFileDialog2.ShowDialog() == DialogResult.OK)
        {
            string fName = openFileDialog2.FileName;
            if (fName != null)
            {
                FileInfo fi = new FileInfo(fName);
                string name = fi.Name;
                DecryptFile(name);
            }
        }
    }
}

將下列 DecryptFile 方法加入至表單。

Private Sub DecryptFile(ByVal inFile As String)
    ' Create instance of Rijndael for
    ' symetric decryption of the data.
    Dim rjndl As RijndaelManaged = New RijndaelManaged
    rjndl.KeySize = 256
    rjndl.BlockSize = 256
    rjndl.Mode = CipherMode.CBC

    ' 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 FileStream = 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)
        Dim KeyDecrypted() As Byte = rsa.Decrypt(KeyEncrypted, False)

        ' Decrypt the key.
        Dim transform As ICryptoTransform = rjndl.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 FileStream = 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 = (rjndl.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 CryptoStream = New CryptoStream(outFs, transform, CryptoStreamMode.Write)
                Do
                    count = inFs.Read(data, 0, blockSizeBytes)
                    offset = (offset + count)
                    outStreamDecrypted.Write(data, 0, count)
                Loop Until (count = 0)

                outStreamDecrypted.FlushFinalBlock()
                outStreamDecrypted.Close()
            End Using
            outFs.Close()
        End Using
        inFs.Close()
    End Using
End Sub
private void DecryptFile(string inFile)
{

    // Create instance of Rijndael for
    // symetric decryption of the data.
    RijndaelManaged rjndl = new RijndaelManaged();
    rjndl.KeySize = 256;
    rjndl.BlockSize = 256;
    rjndl.Mode = CipherMode.CBC;
    rjndl.Padding = PaddingMode.None;

    // 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];

    // Consruct the file name for the decrypted file.
    string outFile = DecrFolder + inFile.Substring(0, inFile.LastIndexOf(".")) + ".txt";

    // Use FileStream objects to read the encrypted
    // file (inFs) and save the decrypted file (outFs).
    using (FileStream inFs = new FileStream(EncrFolder + inFile, FileMode.Open))
    {

        inFs.Seek(0, SeekOrigin.Begin);
        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 postition of
        // the ciphter text (startC)
        // and its length(lenC).
        int startC = lenK + lenIV + 8;
        int lenC = (int)inFs.Length - startC;

        // Create the byte arrays for
        // the encrypted Rijndael 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);

        // Use RSACryptoServiceProvider
        // to decrypt the Rijndael key.
        byte[] KeyDecrypted = rsa.Decrypt(KeyEncrypted, false);

        // Decrypt the key.
        ICryptoTransform transform = rjndl.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 (FileStream outFs = new FileStream(outFile, FileMode.Create))
        {

            int count = 0;
            int offset = 0;

            // blockSizeBytes can be any arbitrary size.
            int blockSizeBytes = rjndl.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 (CryptoStream 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();
                outStreamDecrypted.Close();
            }
            outFs.Close();
        }
        inFs.Close();
    }

}

匯出公開金鑰

這項工作會將 Create Keys 按鈕所建立的金鑰儲存到檔案。它只會匯出公用參數。

這項工作會模擬 Alice 將她的公開金鑰提供給 Bob,使其能夠為她加密檔案的案例。由於 Bob 和擁有該公開金鑰的其他人都沒有完整金鑰組和私用參數,因此他們都無法解密這些檔案。

將下列程式碼加入至 Export Public Key 按鈕 (buttonExportPublicKey_Click) 的 Click 事件處理常式。

Private Sub buttonExportPublicKey_Click(ByVal sender As System.Object, ByVal e As System.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.
    Dim sw As StreamWriter = New StreamWriter(PubKeyFile)
    sw.Write(rsa.ToXmlString(False))
    sw.Close()
End Sub
void buttonExportPublicKey_Click(object sender, System.EventArgs e)
{
    // Save the public key created by the RSA
    // to a file. Caution, persisting the
    // key to a file is a security risk.
    StreamWriter sw = new StreamWriter(PubKeyFile);
    sw.Write(rsa.ToXmlString(false));
    sw.Close();
}

匯入公開金鑰

這項工作會載入僅包含公用參數的金鑰 (即由 Export Public Key 按鈕所建立者),並將其設定為金鑰容器名稱。

這項工作會模擬 Bob 載入屬於 Alice 之僅含公用參數的金鑰,以便為她加密檔案的案例。

將下列程式碼加入至 Import Public Key 按鈕 (buttonImportPublicKey_Click) 的 Click 事件處理常式。

Private Sub buttonImportPublicKey_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles buttonImportPublicKey.Click
    Dim sr As StreamReader = 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 = True Then
        Label1.Text = "Key: " + cspp.KeyContainerName + " - Public Only"
    Else
        Label1.Text = "Key: " + cspp.KeyContainerName + " - Full Key Pair"
    End If
    sr.Close()
End Sub
void buttonImportPublicKey_Click(object sender, System.EventArgs e)
{
    StreamReader sr = new StreamReader(PubKeyFile);
    cspp.KeyContainerName = keyName;
    rsa = new RSACryptoServiceProvider(cspp);
    string keytxt = sr.ReadToEnd();
    rsa.FromXmlString(keytxt);
    rsa.PersistKeyInCsp = true;
    if (rsa.PublicOnly == true)
        label1.Text = "Key: " + cspp.KeyContainerName + " - Public Only";
    else
        label1.Text = "Key: " + cspp.KeyContainerName + " - Full Key Pair";
    sr.Close();
}

取得私密金鑰

這項工作會將金鑰容器名稱設定為使用 Create Keys 按鈕所建立金鑰的名稱。金鑰容器中將包含具有私密參數的完整金鑰組。

這項工作會模擬 Alice 使用其私密金鑰來解密由 Bob 加密之檔案的案例。

將下列程式碼加入至 Get Private Key 按鈕 (buttonGetPrivateKey_Click) 的 Click 事件處理常式。

Private Sub buttonGetPrivateKey_Click(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles buttonGetPrivateKey.Click
    cspp.KeyContainerName = keyName
    rsa = New RSACryptoServiceProvider(cspp)
    rsa.PersistKeyInCsp = True
    If rsa.PublicOnly = True Then
        Label1.Text = "Key: " + cspp.KeyContainerName + " - Public Only"
    Else
        Label1.Text = "Key: " + cspp.KeyContainerName + " - Full Key Pair"
    End If
End Sub
private void buttonGetPrivateKey_Click(object sender, EventArgs e)
{
    cspp.KeyContainerName = keyName;

    rsa = new RSACryptoServiceProvider(cspp);
    rsa.PersistKeyInCsp = true;

    if (rsa.PublicOnly == true)
        label1.Text = "Key: " + cspp.KeyContainerName + " - Public Only";
    else
        label1.Text = "Key: " + cspp.KeyContainerName + " - Full Key Pair";

}

測試應用程式

在建置 (Build) 應用程式之後,執行下列測試案例。

若要建立金鑰、加密和解密

  1. 按一下 [Create Keys] 按鈕。標籤便會顯示金鑰名稱,並顯示它是完整金鑰組。

  2. 按一下 [Export Public Key] 按鈕。請注意匯出公開金鑰參數並不會變更目前的金鑰。

  3. 按一下 [Encrypt File] 按鈕並選取檔案。

  4. 按一下 [Decrypt File] 按鈕,然後選取剛才加密的檔案。

  5. 檢查剛才解密的檔案。

  6. 關閉應用程式並重新啟動,以便在下一個案例中測試所保存的金鑰容器。

若要使用公開金鑰加密

  1. 按一下 [Import Public Key] 按鈕。標籤便會顯示金鑰名稱,並顯示它僅屬於公開金鑰。

  2. 按一下 [Encrypt File] 按鈕並選取檔案。

  3. 按一下 [Decrypt File] 按鈕,然後選取剛才加密的檔案。由於您必須擁有私密金鑰才能解密,因此這時將會失敗。

這個案例示範僅使用公開金鑰來為他人加密檔案。通常該人員只會提供您公開金鑰,而保留用於解密的私密金鑰。

若要使用私密金鑰解密

  1. 按一下 [Get Private Key] 按鈕。標籤便會顯示金鑰名稱,並顯示它是否為完整金鑰組。

  2. 按一下 [Decrypt File] 按鈕,然後選取剛才加密的檔案。由於您擁有可用來解密的完整金鑰組,因此這時將會成功。

請參閱

其他資源

密碼編譯工作

密碼編譯服務