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

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

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

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

二、数字签名的基本概念

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

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

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

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

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

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

二、.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.rsa
8 {
9 /// <summary>
10 /// https://cloud.tencent.com/developer/article/1054441
11 /// </summary>
12 public class RsaAlgorithm
13 {
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 .ctor
21
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 #endregion
32
33 #region 创建RSA
34
35 /// <summary>
36 /// 创建加密RSA
37 /// </summary>
38 /// <param name="publicKey">公钥</param>
39 /// <returns></returns>
40 public RSACryptoServiceProvider CreateEncryptRSA(string publicKey)
41 {
42 try
43 {
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 /// 根据字符串创建解密RSA
58 /// </summary>
59 /// <param name="privateKey">私钥</param>
60 /// <returns></returns>
61 public RSACryptoServiceProvider CreateDecryptRSA(string privateKey)
62 {
63 try
64 {
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 /// 根据安全证书创建加密RSA
79 /// </summary>
80 /// <param name="certfile">公钥文件</param>
81 /// <returns></returns>
82 public RSACryptoServiceProvider X509CertCreateEncryptRSA(string certfile)
83 {
84 try
85 {
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 }

代码示例:https://github.com/Dwayne112401/encryption

计算机网络安全 —— 非对称加密算法 RSA 和数字签名(二)的更多相关文章

  1. 非对称加密算法-RSA算法

    一.概述 1.RSA是基于大数因子分解难题.目前各种主流计算机语言都支持RSA算法的实现 2.java6支持RSA算法 3.RSA算法可以用于数据加密和数字签名 4.RSA算法相对于DES/AES等对 ...

  2. 非对称加密算法RSA使用注意事项

    原文:非对称加密算法RSA使用注意事项 第一个问题,也是最重要的一个——RSA无法对超过117字节的数据进行加密!切记!其实也勿需要求对更大数据的加密,虽然网上已经有相关解决方案,比如BigInteg ...

  3. Java进阶(七)Java加密技术之非对称加密算法RSA

    Java加密技术(四)--非对称加密算法RSA 非对称加密算法--RSA 基本概念 非对称加密算法是一种密钥的保密方法. 非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥(priv ...

  4. JAVA 非对称加密算法RSA

    非对称加密算法 RSA过程 : 以甲乙双方为例 1.初始化密钥 构建密钥对,生成公钥.私钥保存到keymap中 KeyPairGenerator ---> KeyPair --> RSAP ...

  5. Java加密技术(四)非对称加密算法RSA

    RSA      这样的算法1978年就出现了.它是第一个既能用于数据加密也能用于数字签名的算法.它易于理解和操作.也非常流行.算法的名字以发明者的名字命名:Ron Rivest, AdiShamir ...

  6. 非对称加密算法RSA 学习

    非对称加密算法RSA 学习 RSA加密算法是一种非对称加密算法.RSA是1977年由罗纳德·李维斯特(Ron Rivest).阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Ad ...

  7. 第十二章 非对称加密算法-RSA

    注意:本节内容主要参考自<Java加密与解密的艺术(第2版)>第8章“高等加密算法--非对称加密算法” 12.1.RSA(最经典的非对称加密算法) 特点: 使用一套密钥即可完成加解密(与D ...

  8. openssl 非对称加密算法RSA命令详解

    1.非对称加密算法概述 非对称加密算法也称公开密钥算法,其解决了对称加密算法密钥分配的问题,非对称加密算法基本特点如下: 1.加密密钥和解密密钥不同 2.密钥对中的一个密钥可以公开 3.根据公开密钥很 ...

  9. java-信息安全(五)-非对称加密算法RSA

    概述 信息安全基本概念: RSA算法(Ron Rivest.Adi Shamir.Leonard Adleman,人名组合) RSA RSA公钥加密算法是1977年由罗纳德·李维斯特(Ron Rive ...

随机推荐

  1. Mysql技术内幕之InnoDB锁探究

    自7月份换工作以来,期间一直在学习MySQL的相关知识,听了一些视频课,但是一直好奇那些讲师的知识是从哪里学习的.于是想着从书籍中找答案.毕竟一直 看视频也不是办法,不能形成自己的知识.于是想着看书汲 ...

  2. 基础才是重中之重~BouncyCastle实现的DES3加密~java通用

    对于BouncyCastle类库(包)来说,他提供了很多加密算法,在与.net和java进行相互加解密过程中,得到了不错的应用,本文以DES3为例,来说一下DES3加解密的过程. 加密过程 明文字符转 ...

  3. Fresco 二三事:图片处理之旋转、缩放、裁剪切割图片

    关于Fresco加载图片的处理,例如旋转.裁剪切割图片,在官方文档也都有提到,只是感觉写的不太详细,正好最近项目里有类似需求,所以分享一些使用小tip,后面的朋友就不用再走弯路浪费时间了.(测试图片分 ...

  4. 使用maven创建java项目是,jdk的版本默认为1.5,如何修改为1.8

    <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> ...

  5. 指令重排序 as-if-serial

    笔者认为看完一本书或刚要了解完一个知识点  最好自己先运行一些DEMO 自己尝试着去了解下各种意思  这样知识点最终一定是你的.靠死记硬背的讨论或简单的粗暴的看下资料 脑子里肯定还是一团浆糊. p.p ...

  6. Spark学习进度-RDD

    RDD RDD 是什么 定义 RDD, 全称为 Resilient Distributed Datasets, 是一个容错的, 并行的数据结构, 可以让用户显式地将数据存储到磁盘和内存中, 并能控制数 ...

  7. 腾讯IOT安卓开发初探

    目录 腾讯IOT 安卓开发初探 Tecent IOT 开发平台的使用 新建项目 创建产品 添加自定义功能 设备开发 微信小程序配置 面板配置 新建设备 使用设备 安卓开发 前置配置 data.json ...

  8. pxe过程和原理

    pxe过程和原理 概要 远程安装和启动操作系统 网卡固件支持pxe的接口,一般是有基本的ip/udp协议栈,支持dhcp, tftp协议:bios中可以设置通过pxe启动操作系统 启动过程,大致如下: ...

  9. Harbor镜像删除回收?只看这篇

    最近,公司的技术平台,运维的破事儿颇多.Jira无法访问,ES堆内存不足,Jenkins频繁不工作..等等等,让我这个刚入门的小兵抓心脑肝,夜不能寐,关键时刻方恨经验薄弱呀!!一波未平,一波又起,这不 ...

  10. Vue.nextTick()的使用

    什么是Vue.nextTick()?? 定义:在下次 DOM 更新循环结束之后执行延迟回调.在修改数据之后立即使用这个方法,获取更新后的 DOM. 所以就衍生出了这个获取更新后的DOM的Vue方法.所 ...