计算机网络安全 —— 非对称加密算法 RSA 和数字签名

 一、非对称加密算法基本概念

​ 在对称密钥系统中,两个参与者要共享同一个秘密密钥。但怎样才能做到这一点呢?一种是事先约定,另一种是用信使来传送。在高度自动化的大型计算机网络中,用信使来传送密钥显然是不合适的。如果事先约定密钥,就会给密钥的管理和更换都带来了极大的不便。当然我们可以使用复杂的密钥分发中心(KeyDistributionCenter,KDC)来解决该问题,但采用公钥密码体制可以比较容易地解决这个问题。公钥密码体制的概念是由Stanford大学的研究人员Diffie与Hellman于1976年提出的。公钥密码体制使用不同的加密密钥与解密密钥

​ 由于加密密钥不能用来解密,并且从加密密钥不能推导出解密密钥,因此加密密钥可以公开。例如,参与者A可以在报纸上公布自己的加 密密钥(即公钥),而解密密钥(即私钥)自己秘密保存。任何参与都可以获得该公钥,并用来加密发送给参与者A的信息,而该信息只 能由A解密。可见采用公钥密码体制更易解决密钥分发的问题。

​ 公钥密码体制有许多很好的特性,使得它不仅可以用于加密,还可以很方便地用于鉴别和数字签名。但不幸的是,目前的公钥密码算法比对称密码算法要慢好几个数量级。因此,对称密码被用于绝大部分加密,而公钥密码则通常用于会话密钥的建立。例如,参与者A要发送 大量秘密信息给B。A首先选择一个用于加密数据本身(如采用DES算法)的密钥,由于该密钥仅用于该次会话,被称为会话密钥。因为对称密钥由双方共享,A必须将该会话密钥通过秘密渠道告知B。为此,A用B的RSA公钥加密该会话密钥后发送给B。B收到加密的会话密 钥后用自己的私钥解密后得到会话密钥。此后,A和B之间就可以用该会话密钥加密通信的数据。具体流程如下图:

img

二、数字签名的基本概念

​ 在日常生活中,可以根据亲笔签名或印章来证明书信或文件的真实来源。但在计算机网络中传送的文电又如何盖章呢?这就是数字签名(digitalsignature)所要解决的问题。

​ 数字签名必须保证以下三点:

  1. *接收方能够核实发送方对报文的数字签名;*
  2. *发送方事后不能抵赖对报文的数字签名;*
  3. *任何人包括接收方都不能伪造对报文的签名。*

​ 现在已有多种实现数字签名的方法。但采用公钥算法要比采用对称密钥算法更容易实现。具体流程如下:

img

我们知道公钥密码算法的计算代价非常大,对整个报文进行数字签名是一件非常耗时的事情。更有效的方法是仅对报文摘要进行数字签名。

上述过程仅对报文进行了签名,对报文X本身却未保密。因为截获DSKA(X)并知道发送方身份的任何人,通过查阅手册即可获得发送方的公钥PKA,因而能得知电文内容。若采用下图所示的方法,则可同时实现秘密通信和数字签名。图中SKA和SKB分别为A和B的私钥,而PKA 和PKB分别为A和B的公钥。具体流程如下:

img

二、.NET使用 RSA 算法

​ RSA 的私钥或者公钥可以由算法自动生成,也可以读取证书生成,同时我们可以使用 RSA 算法完成数字签名,具体代码如下:

  1 using System;2 using System.IO;3 using System.Security.Cryptography;4 using System.Security.Cryptography.X509Certificates;5 using System.Text;6 7 namespace encryption.rsa8 {9     /// <summary>10     /// https://cloud.tencent.com/developer/article/105444111     /// </summary>12     public class RsaAlgorithm13     {14         public Encoding Encoding { get; set; }15         public string PrivateKey { get;private set; }16         public string PublicKey { get;private set; }17 18         private  RSACryptoServiceProvider _rsa;19         private int _keySize;20         #region .ctor21 22         public RsaAlgorithm(int keySize=512)23         {24             _keySize = keySize;25             _rsa = new RSACryptoServiceProvider() { KeySize = _keySize };26             Encoding = Encoding.UTF8;27             PrivateKey = _rsa.ToXmlString(true);28             PublicKey = _rsa.ToXmlString(false);29         }30 31         #endregion32 33         #region 创建RSA34 35         /// <summary>36         /// 创建加密RSA37         /// </summary>38         /// <param name="publicKey">公钥</param>39         /// <returns></returns>40         public  RSACryptoServiceProvider CreateEncryptRSA(string publicKey)41         {42             try43             {44                 _rsa = new RSACryptoServiceProvider() { KeySize = _keySize };45                 _rsa.FromXmlString(publicKey);46                 PublicKey = publicKey;47                 PrivateKey = null;48                 return _rsa;49             }50             catch (CryptographicException ex)51             {52                 throw ex;53             }54         }55 56         /// <summary>57         /// 根据字符串创建解密RSA58         /// </summary>59         /// <param name="privateKey">私钥</param>60         /// <returns></returns>61         public RSACryptoServiceProvider CreateDecryptRSA(string privateKey)62         {63             try64             {65                 _rsa = new RSACryptoServiceProvider() { KeySize = _keySize };66                 _rsa.FromXmlString(privateKey);67                 PublicKey = null;68                 PrivateKey = privateKey;69                 return _rsa;70             }71             catch (CryptographicException ex)72             {73                 throw ex;74             }75         }76 77         /// <summary>78         /// 根据安全证书创建加密RSA79         /// </summary>80         /// <param name="certfile">公钥文件</param>81         /// <returns></returns>82         public RSACryptoServiceProvider X509CertCreateEncryptRSA(string certfile)83         {84             try85             {86                 if (File.Exists(certfile)==false)87                 {88                     throw new ArgumentNullException(certfile, "加密证书未找到");89                 }90                 X509Certificate2 x509Cert = new X509Certificate2(certfile);91                 _rsa = (RSACryptoServiceProvider)x509Cert.PublicKey.Key;92                 return _rsa;93             }94             catch (CryptographicException ex)95             {96                 throw ex;97             }98         }99 
100         /// <summary>
101         /// 根据私钥文件创建解密RSA
102         /// </summary>
103         /// <param name="keyfile">私钥文件</param>
104         /// <param name="password">访问含私钥文件的密码</param>
105         /// <returns></returns>
106         public RSACryptoServiceProvider X509CertCreateDecryptRSA(string keyfile, string password)
107         {
108             try
109             {
110                 if (File.Exists(keyfile)==false)
111                 {
112                     throw new ArgumentNullException(keyfile, "解密证书未找到");
113                 }
114                 X509Certificate2 x509Cert = new X509Certificate2(keyfile, password);
115                 _rsa = (RSACryptoServiceProvider)x509Cert.PrivateKey;
116                 return _rsa;
117             }
118             catch (CryptographicException ex)
119             {
120                 throw ex;
121             }
122         }
123 
124         #endregion
125 
126 
127         #region 加密
128 
129         /// <summary>
130         /// RSA 加密
131         /// </summary>
132         /// <param name="dataToEncrypt">待加密数据</param>
133         /// <returns></returns>
134         public string Encrypt(string dataToEncrypt)
135         {
136             byte[] bufferBytes = Encoding.GetBytes(dataToEncrypt);
137             return Convert.ToBase64String(this.Encrypt(bufferBytes));
138         }
139 
140         /// <summary>
141         /// RSA 加密
142         /// </summary>
143         /// <param name="dataToEncrypt">待加密数据</param>
144         /// <returns></returns>
145         public byte[] Encrypt(byte[] dataToEncrypt)
146         {
147             byte[] data = null;
148             int blockLen = _rsa.KeySize / 8 - 11;
149             if (dataToEncrypt.Length <= blockLen)
150             {
151                 return _rsa.Encrypt(dataToEncrypt, false);
152             }
153 
154             using (var dataStream = new MemoryStream(dataToEncrypt))
155             using (var enStream = new MemoryStream())
156             {
157                 Byte[] buffer = new Byte[blockLen];
158                 int len = dataStream.Read(buffer, 0, blockLen);
159 
160                 while (len > 0)
161                 {
162                     Byte[] block = new Byte[len];
163                     Array.Copy(buffer, 0, block, 0, len);
164 
165                     Byte[] enBlock = _rsa.Encrypt(block, false);
166                     enStream.Write(enBlock, 0, enBlock.Length);
167 
168                     len = dataStream.Read(buffer, 0, blockLen);
169                 }
170 
171                 data = enStream.ToArray();
172             }
173 
174             return data;
175         }
176 
177         #endregion
178 
179 
180         #region 解密
181 
182         /// <summary>
183         /// RSA 解密
184         /// </summary>
185         /// <param name="encryptedData">待解密数据<see cref="string"/></param>
186         /// <returns></returns>
187         public string Decrypt(string encryptedData)
188         {
189             string str = null;
190             byte[] buffer = Convert.FromBase64String(encryptedData);
191             return Encoding.GetString(this.Decrypt(buffer));
192         }
193 
194         /// <summary>
195         /// RSA 解密
196         /// </summary>
197         /// <param name="encryptedData">待解密数据(byte数组)<see cref="byte"/></param>
198         /// <returns></returns>
199         public byte[] Decrypt(byte[] encryptedData)
200         {
201             byte[] data = null;
202             int blockLen = _rsa.KeySize / 8;
203             if (encryptedData.Length <= blockLen)
204             {
205                 return _rsa.Decrypt(encryptedData, false);
206             }
207 
208             using (var dataStream = new MemoryStream(encryptedData))
209             using (var deStream = new MemoryStream())
210             {
211                 Byte[] buffer = new Byte[blockLen];
212                 int len = dataStream.Read(buffer, 0, blockLen);
213 
214                 while (len > 0)
215                 {
216                     Byte[] block = new Byte[len];
217                     Array.Copy(buffer, 0, block, 0, len);
218 
219                     Byte[] deBlock = _rsa.Decrypt(block, false);
220                     deStream.Write(deBlock, 0, deBlock.Length);
221 
222                     len = dataStream.Read(buffer, 0, blockLen);
223                 }
224 
225                 data = deStream.ToArray();
226             }
227 
228             return data;
229         }
230 
231         #endregion
232 
233         #region 签名与验签
234         /// <summary>
235         ///  RSA 签名
236         /// https://docs.microsoft.com/zh-tw/dotnet/api/system.security.cryptography.rsacryptoserviceprovider.signdata?view=net-5.0
237         /// </summary>
238         /// <param name="hash">报文摘要算法</param>
239         /// <param name="str">报文数据</param>
240         /// <returns></returns>
241         public string Sign(string hash, string str)
242         {
243             byte[] data = Encoding.GetBytes(str);
244             byte[] sign = _rsa.SignData(data, hash);
245             return Convert.ToBase64String(sign);
246         }
247 
248         /// <summary>
249         /// 签名
250         /// </summary>
251         /// <param name="hash">报文摘要算法</param>
252         /// <param name="data">报文数据</param>
253         /// <returns></returns>
254         public string Sign(string hash, byte[] data)
255         {
256             byte[] sign = _rsa.SignData(data, hash);
257             return Convert.ToBase64String(sign);
258         }
259 
260         /// <summary>
261         /// 验签
262         /// </summary>
263         /// <param name="data">报文数据</param>
264         /// <param name="hash">报文摘要算法</param>
265         /// <param name="sign">签名</param>
266         /// <returns></returns>
267         public bool VerifySign(byte[] data, string hash,string sign)
268         {
269             byte[] signBytes = Convert.FromBase64String(sign);
270             return _rsa.VerifyData(data, hash, signBytes);
271         }
272 
273         /// <summary>
274         /// 验签
275         /// </summary>
276         /// <param name="data">报文数据</param>
277         /// <param name="hash">报文摘要算法</param>
278         /// <param name="sign">签名</param>
279         /// <returns></returns>
280         public bool VerifySign(string data, string hash, string sign)
281         {
282             return VerifySign(Encoding.GetBytes(data),hash,sign);
283         }
284         #endregion
285     }
286 }

四、测试代码与效果

​ 测试代码如下:

 1   static void Main(string[] args)2         {3             {4                 Console.WriteLine("-----------------------------------------------------RSA 字符串加密与解密以及签名与验签--------------------------------------------------");5                 var input = "公钥密码体制中,目前最著名的是由美国三位科学家Rivest, Shamir 和 Adleman 于1976年提出,并在1978年正式发表的RSA 算法。";6                 Console.Write($"加密内容:{input}\r\n");7                 var rsa = new RsaAlgorithm();8 9                 Console.WriteLine($"RSA私钥:\r\n{rsa.PrivateKey}\r\n");
10                 var encrypt = rsa.Encrypt(input);
11                 Console.WriteLine($"RSA加密后内容:\r\n{encrypt}\r\n");
12                 var sign = rsa.Sign("SHA1", input);
13                 Console.WriteLine($"RSA生成数字签名[SHAI]:\r\n{sign}\r\n");
14 
15                 Console.WriteLine($"RSA公钥:\r\n{rsa.PublicKey}\r\n");
16                 var decrypt = rsa.Decrypt(encrypt);
17                 Console.WriteLine($"RSA解密后内容:\r\n{decrypt}\r\n");
18                 string signResult = rsa.VerifySign(decrypt, "SHA1", sign) ? "验签通过" : "验签未通过";
19                 Console.WriteLine($"RSA进行鉴别数字签名:{signResult}");
20             }
21 
22             {
23                 Console.WriteLine("-----------------------------------------------------RSA 文件加密与解密--------------------------------------------------");
24                 var input = System.IO.File.ReadAllBytes(@"C:\Users\97460\Desktop\1.rar");
25                 Console.Write($"加密内容:{Convert.ToBase64String(input)}\r\n");
26                 var rsa = new RsaAlgorithm(1024);
27 
28                 Console.WriteLine($"RSA私钥:\r\n{rsa.PrivateKey}\r\n");
29                 var encrypt = rsa.Encrypt(input);
30                 Console.WriteLine($"RSA加密后内容:\r\n{Convert.ToBase64String(encrypt)}\r\n");
31 
32                 Console.WriteLine($"RSA公钥:\r\n{rsa.PublicKey}\r\n");
33                 var decrypt = rsa.Decrypt(encrypt);
34                 Console.WriteLine($"RSA解密后内容:\r\n{Convert.ToBase64String(decrypt)}\r\n");
35                 System.IO.File.WriteAllBytes("1.rar", decrypt);
36             }
37 
38             {
39                 Console.WriteLine("-----------------------------------------------------RSA 使用证书加密与解密字符串--------------------------------------------------");
40                 var input = "公钥密码体制中,目前最著名的是由美国三位科学家Rivest, Shamir 和 Adleman 于1976年提出,并在1978年正式发表的RSA 算法。";
41                 Console.Write($"加密内容:{input}\r\n");
42 
43                 // 证书加密
44                 var rsaEncrypt = new RsaAlgorithm();
45                 rsaEncrypt.X509CertCreateEncryptRSA(@"RSAKey.cer");
46                 Console.WriteLine($"RSA私钥:\r\n{rsaEncrypt.PrivateKey}\r\n");
47                 var encrypt = rsaEncrypt.Encrypt(input);
48                 Console.WriteLine($"RSA加密后内容:\r\n{encrypt}\r\n");
49 
50                 // 证书解密
51                 var rsaDecrypt = new RsaAlgorithm(1024);
52                 rsaDecrypt.X509CertCreateDecryptRSA(@"RSAKey.pfx", "888888");
53                 Console.WriteLine($"RSA公钥:\r\n{rsaEncrypt.PublicKey}\r\n");
54                 var decrypt = rsaDecrypt.Decrypt(encrypt);
55                 Console.WriteLine($"RSA解密后内容:\r\n{decrypt}\r\n");
56             }
57             Console.ReadKey();
58         }

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

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

相关文章

【动态规划】【卡特兰数】Leetcode 96. 不同的二叉搜索树

【动态规划】【卡特兰数】Leetcode 96. 不同的二叉搜索树 动态规划卡特兰数 ---------------&#x1f388;&#x1f388;96. 不同的二叉搜索树 题目链接&#x1f388;&#x1f388;------------------- 动态规划 &#x1f612;: 我的代码实现> 动规五部曲 ✒️确定dp数组…

Palindromes(回文、镜像字符串)

描述 A regular palindrome is a string of numbers or letters that is the same forward as backward. For example, the string "ABCDEDCBA" is a palindrome because it is the same when the string is read from left to right as when the string is read fr…

linux命令在线查询工具

您提供的链接是一个名为“Linux 命令在线查询工具 - 轻松查找命令信息”的在线工具页面。这个工具旨在帮助用户快速查找和了解Linux命令的详细信息&#xff0c;从而提高工作效率。 工具概述 Linux命令在线查询工具是一个便捷的资源&#xff0c;它允许用户通过简单的搜索功能来…

SpringMvc之映射器HandlerMapping

简介 在springmvc的处理流程中&#xff0c;第一步就是查询请求对应的映射器&#xff0c;然后组装成处理器链处理请求&#xff0c;本文意在梳理该过程 重要实现 HandlerMapping是一个接口&#xff0c;该接口用于通过HttpServletRequest寻找对应的处理器&#xff0c;接口介绍如下…

攻防世界逆向刷题

阅读须知&#xff1a; 探索者安全团队技术文章仅供参考,未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵操作,由于传播、利用本公众号所提供的技术和信息而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者 本人负责&#xff0c;作者不为此承担任何责任,如…

使用`scipy.stats.wasserstein_distance`来计算两个一维分布之间的Earth Mover‘s Distance (EMD)距离

在Python中&#xff0c;计算Earth Mover’s Distance (EMD)通常使用scipy库中的scipy.stats.wasserstein_distance函数&#xff0c;该函数计算的是Wasserstein距离&#xff0c;它与EMD非常相似&#xff0c;都是用来衡量两个分布之间的距离。 以下是一个简单的Python程序例子&a…

超好用的快捷回复软件

随着直播经济和短视频平台的兴起&#xff0c;品牌营销阵地不再局限于传统的电商巨头——淘宝、天猫、京东和拼多多&#xff0c;越来越多的品牌正积极布局快手、抖音等新晋电商平台&#xff0c;同步打造社群矩阵以拓宽产品推广渠道。这种多维度的市场渗透策略有力地提升了品牌的…

C语言看完我这篇编译与链接就够啦!!!

1. 前言 Hello&#xff01;大家好我是小陈&#xff0c;今天来给大家介绍最详细的C语言编译与链接。 2. 编译和链接 我们通常用的编译器&#xff0c;比如Visual Sudio,这样的IDE(集成开发环境&#xff09;一般将编译和链接的过程一步完成&#xff0c;通常将这这种编译和链接合…

算法(6)KMP+trie

KMP&#xff1a; 最浅显易懂的 KMP 算法讲解_哔哩哔哩_bilibili 该视频使用python书写代码&#xff0c;不会python的小伙伴也可以看看了解kmp的大致思路。 问题描述&#xff1a; kmp&#xff1a;字符串匹配算法&#xff0c;用来找一个长字符串中出现了几次小字符串&#xf…

【机器学习300问】54、如何找到有效的组合特征?

一、为什么需要去寻找有效的组合特征&#xff1f; 因为并不是所有的特征组合都会意义&#xff0c;都能带来价值。 例如在房价预测场景中&#xff0c;卧室数量和浴室数量的比值有意义&#xff0c;但房屋面积与建造年份相组合作为新的组合特征&#xff0c;可能就没有实际含义&…

【ORB-SLAM3】在 Ubuntu20.04 上编译 ORM-SLAM3 并使用 D435i、EuRoC 和 TUM-VI 运行测试

【ORB-SLAM3】在 Ubuntu20.04 上编译 ORM-SLAM3 并使用 D435i、EuRoC 和 TUM-VI 运行测试 1 Prerequisites1.1 C11 or C0x Compiler1.2 Pangolin1.3 OpenCV1.4 Eigen3 2 安装 Intel RealSense™ SDK 2.02.1 测试设备2.2 编译源码安装 (Recommend)2.3 预编译包安装 3 编译 ORB-S…

PTA L2-037 包装机

一种自动包装机的结构如图 1 所示。首先机器中有 N 条轨道&#xff0c;放置了一些物品。轨道下面有一个筐。当某条轨道的按钮被按下时&#xff0c;活塞向左推动&#xff0c;将轨道尽头的一件物品推落筐中。当 0 号按钮被按下时&#xff0c;机械手将抓取筐顶部的一件物品&#x…

07、Lua 流程控制

Lua 流程控制 Lua 流程控制控制结构语句 Lua 流程控制 Lua编程语言流程控制语句通过程序设定一个或多个条件语句来设定。在条件为 true 时执行指定程序代码&#xff0c;在条件为 false 时执行其他指定代码。 以下是典型的流程控制流程图&#xff1a; 控制结构的条件表达式结…

vscode c++环境配置

1.基础软件安装 安装Visual Studio Code. 安装C拓展。点击在vscode界面最左侧的Extensions图标&#xff08;打开快捷键&#xff1a;ctrlshiftX&#xff09;&#xff0c;搜索“C/C”&#xff0c;点击进行安装。 确保已安装gcc. 一般ubuntu系统会预装gcc.在终端窗口中输入如下…

查立得源码如何去除版权

最近发现很多人百度&#xff1a;查立得源码如何去除版权。 每个源代码/软件都是有版权的&#xff0c;无法去除&#xff0c;我们也得尊重知识产权/劳动成果。 可以去除/修改的是&#xff1a;页面显示的版权信息,查立得底部信息均可自定义(一般conn.php可修改)。 另&#xff1…

Linux-2 Linux的权限

目录 1.什么是权限&#xff1f; 2.权限的本质 3.Linux中的用户 普通用户与root用户相互转换 普通用户不变root&#xff0c;以root身份执行一个命令 LInux中的角色 4.Linux文件的权限 5.快速掌握修改权限的做法 修改权限 6.对比权限有无表现 对于普通用户&#xf…

五分钟,零基础也能入门 Python 图像文字识别

一. 前言 最近在研究 Python 的一些功能 &#xff0c; 也尝试了一些有趣实现&#xff0c; 这一篇就从实践的角度来研究一下 Python 如何实现图片识别。 众所周知 &#xff0c; Python 的库真的老多了&#xff0c;其中在图像识别上比较突出的就是 OpenCV. 那么基于这个库我们…

基于RAG的大模型知识库搭建

什么是RAG RAG(Retrieval Augmented Generation)&#xff0c;即检索增强生成技术。 RAG优势 部分解决了幻觉问题。由于我们可以控制检索内容的可靠性&#xff0c;也算是部分解决了幻觉问题。可以更实时。同理&#xff0c;可以控制输入给大模型上下文内容的时效性&#xff0c…

Day50:WEB攻防-PHP应用文件包含LFIRFI伪协议编码算法无文件利用黑白盒

目录 文件包含-原理&分类&利用&修复 文件读取 文件写入 代码执行 远程利用思路 黑盒利用-VULWEB 白盒利用-CTFSHOW-伪协议玩法 78-php&http协议 79-data&http协议 80-81-日志包含 87-php://filter/write&加密编码 88-data&base64协议 …

17、GateWay和Sentinel继承实现服务限流

注&#xff1a;本篇文章主要参考周阳老师讲解的cloud进行整理的&#xff01; 1、需求说明 cloudalibaba-sentinel-gateway9528 保护 cloudalibaba-provider-payment9001 2、启动nacos服务器8848 startup.cmd -m standalone 3、启动sentinel服务器8080 java -jar sentinel-dash…