创建加密应用程序

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

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

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

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

    Note注意

    如果您的目的是保护计算机上的数据,而不是与其他人交换加密内容,可考虑使用 ProtectedData 或ProtectedMemory 类。

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

任务说明

创建 Windows 窗体应用程序

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

声明全局对象

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

创建不对称密钥

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

加密文件

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

解密文件

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

获取私钥

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

导出公钥

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

导入公钥

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

测试应用程序

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

此应用程序需要引用下面的命名空间:

  • System.IO

  • System.Security.Cryptography

创建 Windows 窗体应用程序

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

控件名称文本属性(根据需要)

Button

buttonEncryptFile

加密文件

Button

buttonDecryptFile

解密文件

Button

buttonCreateAsmKeys

创建密钥

Button

buttonExportPublicKey

导出公钥

Button

buttonImportPublicKey

导入公钥

Button

buttonGetPrivateKey

获取私钥

Label

label1

 

OpenFileDialog

openFileDialog1

 

OpenFileDialog

openFileDialog2

 

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

声明全局对象

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

C#
VB
// 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 密钥(用于加密内容)进行加密和解密的不对称密钥,并在标签控件上显示密钥容器名称。

将下列代码示例添加为“创建密钥”按钮的单击事件处理程序:buttonCreateAsmKeys_Click

C#
VB
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";elselabel1.Text = "Key: " + cspp.KeyContainerName + " - Full Key Pair";}
加密文件

此任务涉及两个方法:“加密文件”按钮的事件处理程序方法 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 的长度,可以确定加密包的所有部分的起始点和长度以便对文件进行加密。

将下列代码示例添加为“加密文件”按钮的单击事件处理程序:buttonEncryptFile_Click

C#
VB
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 方法。

C#
VB
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();}}
解密文件

此任务涉及两个方法:“解密文件”按钮的事件处理程序方法 buttonEncryptFile_Click 以及 DecryptFile 方法。第一个方法将显示一个对话框以便选择某个文件并将相应的文件名传递给第二个方法,后者将执行解密操作。

Decrypt 方法执行下列操作:

  1. 创建 RijndaelManaged 对称算法以对内容进行解密。

  2. 将加密包的 FileStream 的前 8 个字节读取到字节数组中,以获取加密密钥和 IV 的长度。

  3. 从加密包中将密钥和 IV 提取到字节数组中。

  4. 创建一个 RSACryptoServiceProvider 实例以对 RijndaelManaged 密钥进行解密。

  5. 使用 CryptoStream 以将 FileStream 加密包的密码文本部分读取到解密文件的 FileStream 中并进行解密(以字节块为单位)。完成此操作后,解密即告完成。

将下列代码示例添加为“解密文件”按钮的单击事件处理程序。

C#
VB
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 方法。

C#
VB
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();}}
导出公钥

此任务将“创建密钥”按钮创建的密钥保存到仅导出公共参数的文件中。

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

将下列代码示例添加为“创建密钥”按钮的单击事件处理程序:buttonExportPublicKey_Click

C#
VB
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();
}
导入公钥

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

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

将下列代码示例添加为“导入公钥”按钮的单击事件处理程序:buttonImportPublicKey_Click

C#
VB
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";elselabel1.Text = "Key: " + cspp.KeyContainerName + " - Full Key Pair";sr.Close();
}
获取私钥

此任务将密钥容器名称设置为使用“创建密钥”按钮创建的密钥的名称。密钥容器将包含带有私有参数的完全密钥对。

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

将下列代码示例添加为“获取私钥”按钮的单击事件处理程序:buttonGetPrivateKey_Click

C#
VB
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";elselabel1.Text = "Key: " + cspp.KeyContainerName + " - Full Key Pair";}
测试应用程序

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

创建密钥、加密和解密

  1. 单击“创建密钥”按钮。标签将显示密钥名称,并显示此密钥是一个完全密钥对。

  2. 单击“导出公钥”按钮。请注意,导出公钥参数不会更改当前密钥。

  3. 单击“加密文件”按钮并选择一个文件。

  4. 单击“解密文件”按钮并选择刚刚加密的文件。

  5. 检查刚刚解密的文件。

  6. 关闭并重新启动应用程序以在下一个方案中对检索保留的密钥容器进行测试。

使用公钥进行加密

  1. 单击“导入公钥”按钮。标签将显示密钥名称,并显示此密钥仅是公用的。

  2. 单击“加密文件”按钮并选择一个文件。

  3. 单击“解密文件”按钮并选择刚刚加密的文件。此操作将失败,因为您必须具有私钥才能进行解密。

此方案演示了仅使用公钥对发送给其他人的文件进行加密的情况。通常,此人将仅为您提供公钥,而保留用于解密的私钥。

使用私钥进行解密

  1. 单击“获取私钥”按钮。标签将显示密钥名称,并显示此密钥是否为一个完全密钥对。

  2. 单击“解密文件”按钮并选择刚刚加密的文件。此操作将成功,因为您具有用于解密的完全密钥对。

转载于:https://www.cnblogs.com/amylis_chen/p/4789923.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/491832.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

中科院詹剑锋:美国出口管控对中国开源软件及产业的影响。

来源:Bench Council摘要:开源软件受美国出口管控限制?对中国蓬勃发展的信息产业有着什么样的影响? 本周五(19年5月24日)上午9点组织中美科技和法律专家通过欣秀科教交流工具远程线上讨论, 6月27…

附全文 |《数字中国指数报告2019》重磅发布,下一个数字经济增长点将由产业驱动...

来源:腾讯研究院5月21日,2019腾讯全球数字生态大会在昆明盛大开幕。在主峰会上,腾讯研究院发布《数字中国指数报告(2019)》(以下简称“报告”),推出2019数字中国指数,全面…

将KEEL的数据集转换为CSV文件

使用MATLAB将KEEL的数据集(以glass1数据集为例)转换为CSV文件步骤如下: 预处理:首先将从KEEL下载的.dat文件用记事本方式打开,删除里面的非数据部分 点击MATLAB的"导入数据"按钮,选择要转换的.…

超维计算让AI有记忆和反应,还能解决自动驾驶难题

来源:雷锋网这可以打破我们与自动驾驶汽车和其他机器人之间的僵局,这也将促使更像人类AI模型的出现。马里兰大学的一个研究团队最近提出了超维计算理论(hyperdimensional computing theory),能够让机器人拥有记忆和反应…

数字图像处理-0.绪论

一、图像处理的概念 图像:是对客观物体的一种相似性的生动的写真或描述。 可见的图像:照片、图与画 、投影 /不可见光:不可见光成像(红外、紫外等)、数学模型的生成。 图像的类别:彩色和非彩色&#xff…

window下打开tensorboard

首先通过一个简单的 TensorFlow 程序,在这个程序中完成了TensorBoard 日志输出的功能。 import tensorflow as tfa tf.constant([1, 2, 3], nameinput1) b tf.constant([4, 5, 6], nameinput2) c tf.add_n([a, b], nameadd)with tf.Session() as sess:sess.run(…

数字图像处理-1.图像获取

一、图像数字化 原理:图像数字化是将一幅画面转化成计算机能处理的形式——数字图像的过程。 将一幅图像分割成如图的一个个小区域(像元或像素),并将各小区域灰度用整数表示,形成一幅点阵式的数字图像。 包括采样和量…

刘炽平:腾讯要以生态方式进行开放,不做“颠覆者”

“我们希望做生态的‘共建者’,成为大家的‘帮助者’,而不是传统互联网行业的颠覆者。”在2019腾讯全球数字生态大会上,腾讯公司总裁刘炽平这样说道。本次大会由云南省人民政府指导,云南省文化和旅游厅、昆明市人民政府、腾讯公司…

数字图像处理--2.图像变换

一、图像的傅里叶变换 目的与用途 图像变换的目的: 使得图像处理问题简化;有利于图像特征提取;(我们知道特征提取的目的是为了对影像进行分析,根据特征从影像中提取目标等有用信息,特征提取对影像中提取…

《腾讯数字生活报告2019》发布,互联网时代新马斯洛需求金字塔预示什么?

来源:腾讯研究院5月22日,腾讯研究院、腾讯应用宝、腾讯开放平台联合出品的《腾讯数字生活报告2019》在腾讯全球数字生态大会应用生态主题论坛上发布,报告从生存、关系、发展三个层级解读了大众数字生活版图中的新趋势及核心洞察。透过这份数字…

数字图像处理--3.图像增强

一、图像增强的点运算 图像增强:采用一系列技术,改善图像的视觉效果,或者将图像转换成一种更适合于人或者机器进行分析和处理的形式。 图像增强方法:1.空间域增强:直接对图像各像素进行处理;2.对图像进行…

腾讯姚星:两大科技矩阵助力两张网,立志攻克通用人工智能和多模态问题

来源:腾讯AI实验室5月21日,2019腾讯全球数字生态大会在昆明滇池国际会展中心开幕。本次大会由云南省人民政府指导,云南省文化和旅游厅、昆明市人民政府、腾讯公司共同主办,是腾讯战略升级后,整合互联网数字经济峰会、云…

图像处理-5

1.图像的数学变换 空间域:图像的代数运算和几何运算都是利用对输入图像进行加工而得到输出图像 转换空间:最典型的有离散傅里叶变换将原定义在图像空间的图像以某种形式转换到另外一些空间,并利用输入图像在这些空间的特有性质有效而快速地…

量子算法、DNA计算与后经典计算时代

来源:资本实验室二进制与伟大的计算机相结合,推动人类进入了信息化时代。在这个基于物质世界的,由0和1构成的新世界中,我们依靠算法和电子技术不断解决了大量曾经无法解决的问题。然而,好奇的人类总是善于提出新的、更…

使用Matplotlib创建散点图

假设data是m行两列的训练样本,labels是m行一列的类标签,类标签一共有3类,分别用1、2、3表示,现将data用散点图表示出来,且不同类的样本有不同的颜色: import matplotlib.pyplot as pltfig plt.figure() a…

数字图像-6空域滤波

空域处理 基本概念: 理论基础——线性系统响应:卷积理论 卷积的离散表达式,基本上可以理解为模板运算的数学表达式 由此,卷积的冲击响应函数h(x,y),称为空域卷积模板。 空域滤波及滤波器的定义 使用空域模板进行的…

特斯拉烧,特斯拉烧完蔚来烧

来源:36氪最关键的问题还是在电池。又一台蔚来汽车自燃了。5月16日,上海嘉定一个小区的地下车库,一台黑色的蔚来ES8突然冒出大量浓烟。消防人员及时赶到,扑灭烟雾并封锁了现场,才没有引起火灾。根据车主的描述&#xf…

超出内容用省略号替代

最近学习了一下怎么用省略号代替超出的文本。 虽然网上的资料很多&#xff0c;但俗话说得好&#xff0c;好记性不如烂笔头&#xff0c;还是记一下吧&#xff01; 有两种方法&#xff0c;第一是用CSS实现&#xff1b;第二是用js HTML <p id"text">9月10日&#…

数字图像处理-7频域滤波

傅里叶变化特性及其应用

福布斯发布2019全球品牌价值100强:华为上榜苹果夺冠

来源&#xff1a;世界科技创新论坛百强品牌中&#xff0c;有56个来自美国公司&#xff0c;前10名中有80%是美国公司的品牌。德国、法国和日本排在美国之后&#xff0c;分别有11个、7个、6个品牌上榜。上榜品牌共来自16个国家。5月23日&#xff0c;福布斯发布了一年一度的全球品…