演练:创建加密应用程序

本演练演示如何对内容进行加密和解密。 这些代码示例是专为 Windows 窗体应用程序设计的。 此应用程序并不演示实际方案(例如使用智能卡), 而只演示加密和解密的基础。

此演练使用下列加密准则:

  • 使用 RijndaelManaged 类(一种对称算法)并利用它自动生成的 KeyIV 对数据进行加密和解密。

  • 使用 RSACryptoServiceProvider(一种不对称算法)对 RijndaelManaged 加密的数据的密钥进行加密和解密。 不对称算法最适用于少量数据,如密钥。

    注意注意

    如果要保护计算机上的数据,而不是与他人交换加密的内容,请考虑使用 ProtectedDataProtectedMemory 类。

下表对本主题中的加密任务进行了总结。

任务

说明

创建 Windows 窗体应用程序

列出运行应用程序所需的控件。

声明全局对象

声明字符串路径变量、CspParametersRSACryptoServiceProvider,以获得 Form 类的全局上下文。

创建非对称密钥

创建一个不对称的公钥/私钥值对,并为其指定一个密钥容器名称。

加密文件

显示一个对话框以选择要加密的文件并对该文件进行加密。

解密文件

显示一个对话框以选择要解密的已加密文件并对该文件进行解密。

获取私钥

获取使用密钥容器名的完全密钥对。

导出公钥

将只带有公共参数的密钥保存到一个 XML 文件中。

导入公钥

将密钥从一个 XML 文件加载到密钥容器中。

测试应用程序

列出用于测试此应用程序的过程。

系统必备

您需要以下组件来完成本演练:

创建 Windows 窗体应用程序

本演练中的大多数代码示例都被设计为按钮控件的事件处理程序。 下表列出了示例应用程序所需的控件以及这些控件为与代码示例匹配所需的名称。

控件

名称

文本属性(根据需要)

Button

buttonEncryptFile

加密文件

Button

buttonDecryptFile

解密文件

Button

buttonCreateAsmKeys

创建密钥

Button

buttonExportPublicKey

导出公钥

Button

buttonImportPublicKey

导入公钥

Button

buttonGetPrivateKey

获取私钥

Label

label1

OpenFileDialog

openFileDialog1

OpenFileDialog

openFileDialog2

双击 Visual Studio 设计器中的按钮以创建其事件处理程序。

声明全局对象

将下列代码添加到窗体的构造函数中。 编辑表示您的环境和首选项的字符串变量。

' 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 按钮的 Click 事件处理程序 (buttonCreateAsmKeys_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 对象将源文件的 FileStream 读取到加密文件的目标 FileStream 对象中并进行加密(以字节块为单位)。

  4. 确定加密密钥和 IV 的长度并创建其长度值的字节数组。

  5. 将密钥、IV 及其长度值写入到加密包中。

加密包使用以下格式:

  • 密钥长度,字节 0 - 3

  • IV 长度,字节 4 - 7

  • 加密密钥

  • IV

  • 密码文本

可以使用密钥和 IV 的长度确定加密包的所有部分的起始点和长度,从而用于对文件进行解密。

将下列代码添加为 Encrypt File 按钮的 Click 事件处理程序 (buttonEncryptFile_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.FullName
                    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.FullName;
                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 startFileName As Integer = inFile.LastIndexOf("\") + 1
    Dim outFile As String = (EncrFolder _
                + (inFile.Substring(startFileName, inFile.LastIndexOf(".") - startFileName) + ".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.
    // rsa is previously instantiated: 
    //    rsa = new RSACryptoServiceProvider(cspp);
    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

    int startFileName = inFile.LastIndexOf("\\") + 1;
   // Change the file's extension to ".enc"
    string outFile = EncrFolder + inFile.Substring(startFileName, inFile.LastIndexOf(".")- startFileName) + ".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 的前 8 个字节读取到字节数组中,以获取加密密钥和 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)
        Directory.CreateDirectory(DecrFolder)
        ' User RSACryptoServiceProvider
        ' to decryt the Rijndael key
        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;

    // 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);
        Directory.CreateDirectory(DecrFolder);
        // 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 按钮创建的密钥保存到文件中。 它只导出公共参数。

此任务模拟了这样一种情况:小红将她的公钥提供给小明,以便小明能够对发送给她的文件进行加密。 小明和其他具有该公钥的人员将不能对这些文件进行解密,因为他们不具备带有私有参数的整个密钥对。

将下列代码添加为 Export Public Key 按钮的 Click 事件处理程序 (buttonExportPublicKey_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.
    Directory.CreateDirectory(EncrFolder)
    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.
    Directory.CreateDirectory(EncrFolder);
    StreamWriter sw = new StreamWriter(PubKeyFile, false);
    sw.Write(rsa.ToXmlString(false));
    sw.Close();
}

导入公钥

此任务将加载 Export Public Key 按钮创建的密钥(仅带有公共参数)并将其设置为密钥容器名称。

此任务模拟这样一种情况:小明将加载小红提供的仅带有公共参数的密钥,以便他能够对发送给小红的文件进行加密。

将下列代码添加为 Import Public Key 按钮的 Click 事件处理程序 (buttonImportPublicKey_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 按钮创建的密钥的名称。 密钥容器将包含带有私有参数的整个密钥对。

此任务模拟这样一种情况:小红使用自己的私钥对小明加密的文件进行解密。

将下列代码添加为 Get Private Key 按钮的 Click 事件处理程序 (buttonGetPrivateKey_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";

}

测试应用程序

生成应用程序之后,执行下列测试方案。

创建密钥、加密和解密

  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 按钮并选择刚刚加密的文件。 此操作将成功,因为您具有用于解密的完全密钥对。

请参见

概念

加密服务

其他资源

加密任务