如何通过 Windows 窗体访问和加密您的文件






4.80/5 (8投票s)
演示如何加密目录文件的文章。
引言
本文的目的是演示如何构建一个 Windows Forms 应用程序,该应用程序通过使用 RijndaelManaged
类来加密文件。RijndaelManaged
是一个对称算法,它利用自动生成的密钥和初始化向量 (IV) 来加密和解密数据。加密涉及创建一个密码(一种算法),该算法以数据和生成的密钥作为输入。算法的行为将取决于密钥的长度。对称算法是指使用相同的密钥来解密和加密数据文件的算法。在本例中,我们将使用 RSACryptoServiceProvider
,这是一种非对称算法,用于加密和解密由 RijndaelManaged
加密的密钥。非对称算法最适合用于少量数据,例如密钥,因为非对称算法比对称算法具有更多的开销。对称算法在生成时开销较小。顾名思义,RijndaelManaged
类由 .NET Framework 用于托管代码;作为一种政府加密标准,该算法也称为高级加密标准 (AES)。RijndaelManaged
算法使用的密钥长度范围为 128 到 256 位,以 32 位为增量。IV 代表初始化向量 (Initialization Vector):这是对称加密算法用于进一步混淆要加密的第一块数据的数据,从而使未经授权的解密更加困难。然后,IV 获取或设置对称算法的初始化向量。与 Key 属性一样,加密器和解密器都必须指定相同的值。Key 获取或设置对称算法的密钥对。加密后,必须存储此值并将其传输给解密器。解密期间,必须指定用于加密的相同密钥。下载的解决方案文件使用 Visual Studio 2010 构建,但后面部分提供的代码作为单个文件为命令行构建。
此过程的第一步是创建三个文件夹:c:\docs、c:\Encrypt 和 c:\Decrypt。写出一些文本文件并将它们放入 C:\docs 目录中。Forms 应用程序需要在窗体表面上拖放六个按钮、两个标签和两个 OpenFileDialog
控件。第一个标签(位于窗体顶部)的 AutoSize
属性应设置为 false
。这将为您提供空间来放大字体和更改颜色。这是我们单击“Create Keys”按钮时出现文本输出的地方。因此,将第一个标签的文本属性留空。第二个标签的文本应显示:“Secure Your Files”。该标签的 AutoSize
属性也设置为 false
。
单个文件中的源代码
注意 private
方法 Encrypt
和 Decrypt
,以及按钮控件的事件处理程序。Encrypt
按钮处理程序调用该模块的 private
方法,Decrypt
方法也一样。请注意,此应用程序中没有用户输入字段。我们使用 OpenFileDialog
控件来访问要加密的文件。
using System;
using System.IO;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Security.Cryptography;
using System.Text;
using System.Windows.Forms;
namespace Security
{
public partial class Form1 : Form
{
private System.Windows.Forms.Button buttonEncryptFile;
private System.Windows.Forms.Button buttonDecryptFile;
private System.Windows.Forms.Button buttonCreateAsmKeys;
private System.Windows.Forms.Button buttonExportPublicKey;
private System.Windows.Forms.Button buttonImportPublicKey;
private System.Windows.Forms.Button buttonGetPrivateKey;
private System.Windows.Forms.OpenFileDialog openFileDialog1;
private System.Windows.Forms.OpenFileDialog openFileDialog2;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.PictureBox pictureBox1;
private System.Windows.Forms.Label label2;
public Form1()
{
InitializeComponent();
}
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";
private void InitializeComponent()
{
this.buttonEncryptFile = new System.Windows.Forms.Button();
this.buttonDecryptFile = new System.Windows.Forms.Button();
this.buttonCreateAsmKeys = new System.Windows.Forms.Button();
this.buttonExportPublicKey = new System.Windows.Forms.Button();
this.buttonImportPublicKey = new System.Windows.Forms.Button();
this.buttonGetPrivateKey = new System.Windows.Forms.Button();
this.openFileDialog1 = new System.Windows.Forms.OpenFileDialog();
this.openFileDialog2 = new System.Windows.Forms.OpenFileDialog();
this.label1 = new System.Windows.Forms.Label();
this.pictureBox1 = new System.Windows.Forms.PictureBox();
this.label2 = new System.Windows.Forms.Label();
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
this.SuspendLayout();
//
// buttonEncryptFile
//
this.buttonEncryptFile.Location = new System.Drawing.Point(484, 44);
this.buttonEncryptFile.Name = "buttonEncryptFile";
this.buttonEncryptFile.Size = new System.Drawing.Size(125, 23);
this.buttonEncryptFile.TabIndex = 0;
this.buttonEncryptFile.Text = "Encrypt File";
this.buttonEncryptFile.UseVisualStyleBackColor = true;
this.buttonEncryptFile.Click +=
new System.EventHandler(this.buttonEncryptFile_Click);
//
// buttonDecryptFile
//
this.buttonDecryptFile.Location = new System.Drawing.Point(484, 95);
this.buttonDecryptFile.Name = "buttonDecryptFile";
this.buttonDecryptFile.Size = new System.Drawing.Size(125, 23);
this.buttonDecryptFile.TabIndex = 1;
this.buttonDecryptFile.Text = "Decrypt File";
this.buttonDecryptFile.UseVisualStyleBackColor = true;
this.buttonDecryptFile.Click +=
new System.EventHandler(this.buttonDecryptFile_Click);
//
// buttonCreateAsmKeys
//
this.buttonCreateAsmKeys.Location = new System.Drawing.Point(484, 145);
this.buttonCreateAsmKeys.Name = "buttonCreateAsmKeys";
this.buttonCreateAsmKeys.Size = new System.Drawing.Size(125, 23);
this.buttonCreateAsmKeys.TabIndex = 2;
this.buttonCreateAsmKeys.Text = "Create Keys";
this.buttonCreateAsmKeys.UseVisualStyleBackColor = true;
this.buttonCreateAsmKeys.Click +=
new System.EventHandler(this.buttonCreateAsmKeys_Click);
//
// buttonExportPublicKey
//
this.buttonExportPublicKey.Location = new System.Drawing.Point(484, 207);
this.buttonExportPublicKey.Name = "buttonExportPublicKey";
this.buttonExportPublicKey.Size = new System.Drawing.Size(125, 23);
this.buttonExportPublicKey.TabIndex = 3;
this.buttonExportPublicKey.Text = "Export Public Key";
this.buttonExportPublicKey.UseVisualStyleBackColor = true;
this.buttonExportPublicKey.Click +=
new System.EventHandler(this.buttonExportPublicKey_Click);
//
// buttonImportPublicKey
//
this.buttonImportPublicKey.Location = new System.Drawing.Point(484, 271);
this.buttonImportPublicKey.Name = "buttonImportPublicKey";
this.buttonImportPublicKey.Size = new System.Drawing.Size(125, 23);
this.buttonImportPublicKey.TabIndex = 4;
this.buttonImportPublicKey.Text = "Import Public Key";
this.buttonImportPublicKey.UseVisualStyleBackColor = true;
this.buttonImportPublicKey.Click +=
new System.EventHandler(this.buttonImportPublicKey_Click);
//
// buttonGetPrivateKey
//
this.buttonGetPrivateKey.Location = new System.Drawing.Point(484, 330);
this.buttonGetPrivateKey.Name = "buttonGetPrivateKey";
this.buttonGetPrivateKey.Size = new System.Drawing.Size(125, 23);
this.buttonGetPrivateKey.TabIndex = 5;
this.buttonGetPrivateKey.Text = "Get Private Key";
this.buttonGetPrivateKey.UseVisualStyleBackColor = true;
this.buttonGetPrivateKey.Click +=
new System.EventHandler(this.buttonGetPrivateKey_Click);
this.openFileDialog1.FileName = "openFileDialog1";
this.openFileDialog2.FileName = "openFileDialog2";
this.label1.BackColor = System.Drawing.Color.Red;
this.label1.Font = new System.Drawing.Font
("Times New Roman", 21.75F, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.label1.Location = new System.Drawing.Point(46, 23);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(262, 44);
this.label1.TabIndex = 6;
this.pictureBox1.Location = new System.Drawing.Point(101, 135);
this.pictureBox1.Name = "pictureBox1";
this.pictureBox1.Size = new System.Drawing.Size(165, 205);
this.pictureBox1.TabIndex = 7;
this.pictureBox1.TabStop = false;
this.label2.Font = new System.Drawing.Font
("Times New Roman", 18F, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.label2.Location = new System.Drawing.Point(52, 95);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(214, 37);
this.label2.TabIndex = 8;
this.label2.Text = "Secure Your Files";
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.Color.Cyan;
this.ClientSize = new System.Drawing.Size(631, 395);
this.Controls.Add(this.label2);
this.Controls.Add(this.pictureBox1);
this.Controls.Add(this.label1);
this.Controls.Add(this.buttonGetPrivateKey);
this.Controls.Add(this.buttonImportPublicKey);
this.Controls.Add(this.buttonExportPublicKey);
this.Controls.Add(this.buttonCreateAsmKeys);
this.Controls.Add(this.buttonDecryptFile);
this.Controls.Add(this.buttonEncryptFile);
this.Name = "Form1";
this.Text = "Form1";
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
this.ResumeLayout(false);
}
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
private void buttonCreateAsmKeys_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";
}
private void buttonEncryptFile_Click(object sender, 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);
}
}
}
}
private void EncryptFile(string inFile)
{
// Create instance of Rijndael for
// symmetric 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
// encrypt 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
// - encrypted 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();
}
}
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);
}
}
}
}
private void DecryptFile(string inFile)
{
// Create instance of Rijndael for
// symmetric 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];
// Construct 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 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 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)
using (FileStream outFs = new FileStream(outFile, FileMode.Create))
{
int count = 0;
int offset = 0;
int blockSizeBytes = rjndl.BlockSize / 8;
byte[] data = new byte[blockSizeBytes];
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();
}
}
private void buttonExportPublicKey_Click(object sender, EventArgs e)
{
Directory.CreateDirectory(EncrFolder);
StreamWriter sw = new StreamWriter(PubKeyFile, false);
sw.Write(rsa.ToXmlString(false));
sw.Close();
}
private void buttonImportPublicKey_Click(object sender, 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();
}
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";
}
}
}
构建窗体应用程序、检查对象浏览器并设置类的属性(在此情况下为控件)始终是一种良好的实践。但是,此文件是在 .NET Framework 的命令行提示符下构建的。以下是它在使用前的样子。

创建密钥、加密和解密
- 单击“Create Keys”按钮。标签显示密钥名称,并表明它是一个完整的密钥对。
- 单击“Export Public Key”按钮。请注意,导出公钥参数不会更改当前密钥。
- 单击“Encrypt File”按钮并选择一个文件。
- 单击“Decrypt File”按钮并选择刚刚加密的文件。
- 检查刚刚解密的文件。
- 关闭应用程序并重新启动它,以便在下一个场景中测试检索持久化的密钥容器。
使用公钥进行加密
- 单击“Import Public Key”按钮。标签显示密钥名称,并表明它仅为公共密钥。
- 单击“Encrypt File”按钮并选择一个文件。
- 单击“Decrypt File”按钮并选择刚刚加密的文件。这将失败,因为您必须拥有私钥才能解密。
此场景演示了仅拥有公钥来为另一个人加密文件。通常,那个人只会将公钥提供给您,而保留私钥用于解密。
使用私钥进行解密
- 单击“Get Private Key”按钮。标签显示密钥名称,并表明它是完整的密钥对。
- 单击“Decrypt File”按钮并选择刚刚加密的文件。这将成功,因为您拥有完整的密钥对来进行解密。
参考文献
- MSDN 库
历史
- 2010 年 4 月 23 日:首次发布