Skip to content

Commit 3d7ff8a

Browse files
committed
升级1.1版本代码,结构更合理,支持更广泛
1 parent 027e97a commit 3d7ff8a

File tree

7 files changed

+579
-231
lines changed

7 files changed

+579
-231
lines changed

Program.cs

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
using System;
2-
using System.Collections.Generic;
3-
using System.Linq;
4-
using System.Text;
5-
using System.Threading.Tasks;
62

7-
namespace RSA {
3+
namespace com.github.xiangyuecn.rsacsharp {
4+
/// <summary>
5+
/// RSA、RSA_PEM测试控制台主程序
6+
/// GitHub: https://github.com/xiangyuecn/RSA-csharp
7+
/// </summary>
88
class Program {
99
static void RSATest() {
1010
var rsa = new RSA(512);
11-
Console.WriteLine("【512私钥(XML)】:");
11+
Console.WriteLine("【" + rsa.KeySize + "私钥(XML)】:");
1212
Console.WriteLine(rsa.ToXML());
1313
Console.WriteLine();
14-
Console.WriteLine("【512私钥(PEM)】:");
14+
Console.WriteLine("【" + rsa.KeySize + "私钥(PEM)】:");
1515
Console.WriteLine(rsa.ToPEM_PKCS1());
1616
Console.WriteLine();
17-
Console.WriteLine("【512公钥(PEM)】:");
17+
Console.WriteLine("【" + rsa.KeySize + "公钥(PEM)】:");
1818
Console.WriteLine(rsa.ToPEM_PKCS1(true));
1919
Console.WriteLine();
2020

@@ -41,6 +41,22 @@ static void RSATest() {
4141
Console.WriteLine("XML:" + (rsa3.ToXML() == rsa.ToXML()));
4242
Console.WriteLine("PKCS1:" + (rsa3.ToPEM_PKCS1() == rsa.ToPEM_PKCS1()));
4343
Console.WriteLine("PKCS8:" + (rsa3.ToPEM_PKCS8() == rsa.ToPEM_PKCS8()));
44+
45+
//--------RSA_PEM验证---------
46+
RSA_PEM pem = rsa.ToPEM();
47+
Console.WriteLine("【RSA_PEM是否和原始RSA一致】:");
48+
Console.WriteLine(pem.KeySize + "位");
49+
Console.WriteLine("XML:" + (pem.ToXML(false) == rsa.ToXML()));
50+
Console.WriteLine("PKCS1:" + (pem.ToPEM(false, false) == rsa.ToPEM_PKCS1()));
51+
Console.WriteLine("PKCS8:" + (pem.ToPEM(false, true) == rsa.ToPEM_PKCS8()));
52+
Console.WriteLine("仅公钥:");
53+
Console.WriteLine("XML:" + (pem.ToXML(true) == rsa.ToXML(true)));
54+
Console.WriteLine("PKCS1:" + (pem.ToPEM(true, false) == rsa.ToPEM_PKCS1(true)));
55+
Console.WriteLine("PKCS8:" + (pem.ToPEM(true, true) == rsa.ToPEM_PKCS8(true)));
56+
57+
var rsa4 = new RSA(new RSA_PEM(pem.Key_Modulus, pem.Key_Exponent, pem.Key_D));
58+
Console.WriteLine("【用n、e、d构造解密】");
59+
Console.WriteLine(rsa4.DecodeOrNull(en));
4460
}
4561

4662

Properties/AssemblyInfo.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,14 @@
1010
[assembly: AssemblyConfiguration("")]
1111
[assembly: AssemblyCompany("")]
1212
[assembly: AssemblyProduct("RSA-csharp")]
13-
[assembly: AssemblyCopyright("Copyright © 2018")]
13+
[assembly: AssemblyCopyright("Copyright © xiangyuecn")]
1414
[assembly: AssemblyTrademark("")]
1515
[assembly: AssemblyCulture("")]
1616

1717
// 将 ComVisible 设置为 false 使此程序集中的类型
1818
// 对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型,
1919
// 则将该类型上的 ComVisible 特性设置为 true。
20-
[assembly: ComVisible(false)]
20+
[assembly: ComVisible(true)]
2121

2222
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
2323
[assembly: Guid("7661a9da-7f07-403a-8e49-5224ae79a009")]
@@ -29,5 +29,5 @@
2929
// 生成号
3030
// 修订号
3131
//
32-
[assembly: AssemblyVersion("1.0.0.0")]
33-
[assembly: AssemblyFileVersion("1.0.0.0")]
32+
[assembly: AssemblyVersion("1.1.0.0")]
33+
[assembly: AssemblyFileVersion("1.1.0.0")]

README.md

Lines changed: 119 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
1-
# RSA-csharp的帮助文档
1+
# :open_book:RSA-csharp的帮助文档
22

3+
本项目核心功能为:支持`.Net`环境下`PEM``PKCS#1``PKCS#8`)格式RSA密钥对导入、导出。
34

4-
## 跑起来
5+
附带实现了一个RSA封装操作类,和一个测试控制台程序。
6+
7+
支持`.NET Core``.NET Framework`;已移植到Java版:[RSA-java](https://github.com/xiangyuecn/RSA-java/blob/master/RSA_PEM.java);你可以只copy `RSA_PEM.cs` 文件到你的项目中使用,只需这一个文件你就拥有了通过PEM格式密钥创建`RSACryptoServiceProvider`的能力。
58

69
clone下来用vs应该能够直接打开,经目测看起来没什么卵用的文件都svn:ignore掉了(svn滑稽。
710

811

9-
## 主要支持
12+
## 提供支持
1013

1114
- 通过`XML格式`密钥对创建RSA
1215
- 通过`PEM格式`密钥对创建RSA
@@ -17,13 +20,123 @@ clone下来用vs应该能够直接打开,经目测看起来没什么卵用的
1720
- `PEM格式`秘钥对和`XML格式`秘钥对互转
1821

1922

20-
## 已知问题
2123

22-
代码在.NET Framework 4.5测试过,如果要用在.NET Core下,除了RSA_PEM.cs可以copy过去用用外,其他几个文件不建议拿到.NET Core下使用;因为RSA_PEM里面除了RSACryptoServiceProvider、RSAParameters之外的代码是容易用别的语言来实现,而这两个玩意在这个文件里面几乎算是可有可无的东西。问题在于我用的RSACryptoServiceProvider在.NET Core下面就是个残废,参考[/issues/1](https://github.com/xiangyuecn/RSA-csharp/issues/1),手动额外实现一下FromXmlString、ToXmlString(关键是会去用这两个函数完全是被.NET Framework的RSACryptoServiceProvider逼的啊,要是他直接支持PEM秘钥,这个仓库都省了,不可能因为RSACryptoServiceProvider的XML格式而去支持XML格式~)。
24+
25+
# :open_book:文档
26+
27+
## 【RSA_PEM.cs】
28+
此文件不依赖任何文件,可以直接copy这个文件到你项目中用;通过`FromPEM``ToPEM``FromXML``ToXML`这两对方法,可以实现PEM`PKCS#1``PKCS#8`相互转换,PEM、XML的相互转换。
29+
30+
项目里面需要引入程序集`System.Numerics`用来支持`BigInteger`,vs默认创建的项目是不会自动引入此程序集的,要手动引入。
31+
32+
注:openssl `RSAPublicKey_out`导出的公钥,字节码内并不带[OID](http://www.oid-info.com/get/1.2.840.113549.1.1.1)(目测是因为不带OID所以openssl自己都不支持用这个公钥来加密数据),RSA_PEM支持此格式公钥的导入,但不提供此种格式公钥的导出。
33+
34+
### 实例属性
35+
36+
`byte[]``Key_Modulus`(模数n,公钥、私钥都有)、`Key_Exponent`(公钥指数e,公钥、私钥都有)、`Key_D`(私钥指数d,只有私钥的时候才有);有这3个足够用来加密解密。
37+
38+
`byte[]``Val_P`(prime1)、`Val_Q`(prime2)、`Val_DP`(exponent1)、`Val_DQ`(exponent2)、`Val_InverseQ`(coefficient); (PEM中的私钥才有的更多的数值;可通过n、e、d反推出这些值(只是反推出有效值,和原始的值大概率不同))。
39+
40+
`int``KeySize`(密钥位数)
41+
42+
`bool``HasPrivate`(是否包含私钥)
43+
44+
### 构造方法
45+
46+
`RSA_PEM(RSACryptoServiceProvider rsa, bool convertToPublic = false)`:通过RSA中的公钥和私钥构造一个PEM,如果convertToPublic含私钥的RSA将只读取公钥,仅含公钥的RSA不受影响。
47+
48+
`RSA_PEM(byte[] modulus, byte[] exponent, byte[] d, byte[] p, byte[] q, byte[] dp, byte[] dq, byte[] inverseQ)`:通过全量的PEM字段数据构造一个PEM,除了模数modulus和公钥指数exponent必须提供外,其他私钥指数信息要么全部提供,要么全部不提供(导出的PEM就只包含公钥)注意:所有参数首字节如果是0,必须先去掉。
49+
50+
`RSA_PEM(byte[] modulus, byte[] exponent, byte[] dOrNull)`:通过公钥指数和私钥指数构造一个PEM,会反推计算出P、Q但和原始生成密钥的P、Q极小可能相同。注意:所有参数首字节如果是0,必须先去掉。出错将会抛出异常。私钥指数可以不提供,导出的PEM就只包含公钥。
51+
52+
53+
### 实例方法
54+
55+
`RSACryptoServiceProvider GetRSA()`:将PEM中的公钥私钥转成RSA对象,如果未提供私钥,RSA中就只包含公钥。
56+
57+
`string ToPEM(bool convertToPublic, bool usePKCS8)`:将RSA中的密钥对转换成PEM格式,usePKCS8=false时返回PKCS#1格式,否则返回PKCS#8格式,如果convertToPublic含私钥的RSA将只返回公钥,仅含公钥的RSA不受影响。
58+
59+
`string ToXML(bool convertToPublic)`:将RSA中的密钥对转换成XML格式,如果convertToPublic含私钥的RSA将只返回公钥,仅含公钥的RSA不受影响。
60+
61+
62+
### 静态方法
63+
64+
`static RSA_PEM FromPEM(string pem)`:用PEM格式密钥对创建RSA,支持PKCS#1、PKCS#8格式的PEM,出错将会抛出异常。pem格式如:`-----BEGIN XXX KEY-----....-----END XXX KEY-----`
65+
66+
`static RSA_PEM FromXML(string xml)`:将XML格式密钥转成PEM,支持公钥xml、私钥xml,出错将会抛出异常。
67+
68+
69+
70+
71+
## 【RSA.cs】
72+
此文件依赖`RSA_PEM.cs`,封装了加密、解密、签名、验证、秘钥导入导出操作。
73+
74+
### 构造方法
75+
76+
`RSA(int keySize)`:用指定密钥大小创建一个新的RSA,会生成新密钥,出错抛异常。
77+
78+
`RSA(string xml)`:通过XML格式密钥,创建一个RSA,xml内可以只包含一个公钥或私钥,或都包含,出错抛异常。,`XML格式`如:`<RSAKeyValue><Modulus>...</RSAKeyValue>`
79+
80+
`RSA(string pem, bool noop)`:通过`PEM格式`密钥对创建RSA(noop参数随意填),PEM可以是公钥或私钥,支持`PKCS#1``PKCS#8`格式,pem格式如:`-----BEGIN XXX KEY-----....-----END XXX KEY-----`
81+
82+
`RSA(RSA_PEM pem)`:通过一个pem对象创建RSA,pem为公钥或私钥,出错抛异常。
83+
84+
85+
### 实例属性
86+
87+
`RSACryptoServiceProvider``RSAObject`(最底层的RSACryptoServiceProvider对象)
88+
89+
`int``KeySize`(密钥位数)
90+
91+
`bool``HasPrivate`(是否包含私钥)
92+
93+
94+
### 实例方法
95+
96+
`string ToXML(bool convertToPublic = false)`:导出`XML格式`秘钥对。如果RSA包含私钥,默认会导出私钥,设置仅仅导出公钥时只会导出公钥;不包含私钥只会导出公钥。
97+
98+
`string ToPEM_PKCS1(bool convertToPublic = false)`:导出`PEM PKCS#1格式`秘钥对。如果RSA包含私钥,默认会导出私钥,设置仅仅导出公钥时只会导出公钥;不包含私钥只会导出公钥。
99+
100+
`string ToPEM_PKCS8(bool convertToPublic = false)`:导出`PEM PKCS#8格式`秘钥对。如果RSA包含私钥,默认会导出私钥,设置仅仅导出公钥时只会导出公钥;不包含私钥只会导出公钥。
101+
102+
`RSA_PEM ToPEM(bool convertToPublic = false)`:导出RSA_PEM对象,如果convertToPublic含私钥的RSA将只返回公钥,仅含公钥的RSA不受影响。
103+
104+
`string Encode(string str)`:加密操作,支持任意长度数据。
105+
106+
`byte[] Encode(byte[] data)`:加密数据,支持任意长度数据,出错抛异常。
107+
108+
`string DecodeOrNull(string str)`:解密字符串(utf-8),解密异常返回null。
109+
110+
`byte[] DecodeOrNull(byte[] data)`:解密数据,解密异常返回null。
111+
112+
`string Sign(string hash, string str)`:对str进行签名,并指定hash算法(如:SHA256)。
113+
114+
`byte[] Sign(string hash, byte[] data)`:对data进行签名,并指定hash算法(如:SHA256)。
115+
116+
`bool Verify(string hash, string sgin, string str)`:验证字符串str的签名是否是sgin,并指定hash算法(如:SHA256)。
117+
118+
`bool Verify(string hash, byte[] sgin, byte[] data)`:验证data的签名是否是sgin,并指定hash算法(如:SHA256)。
119+
120+
121+
23122

24123

25124

26-
## 前言、自述、还有啥
125+
# :open_book:图例
126+
127+
控制台运行:
128+
129+
![控制台运行](images/1.png)
130+
131+
RSA工具(非开源):
132+
133+
![RSA工具](images/2.png)
134+
135+
136+
137+
138+
139+
# :open_book:知识库
27140

28141
在写一个小转换工具时加入了RSA加密解密支持(见图RSA工具),秘钥输入框支持填写XML和PEM格式,操作类型里面支持XML->PEM、PEM->XML的转换。
29142

@@ -266,83 +379,3 @@ yZKNX3VxmLEHXQ==
266379
```
267380

268381

269-
270-
271-
272-
# C# RSA操作类
273-
274-
275-
## 主要文件
276-
277-
### RSA.cs
278-
此文件依赖`RSA_PEM.cs`,用于进行加密、解密、签名、验证、秘钥导入导出操作。
279-
280-
#### [构造函数] new RSA(`1024`)
281-
通过指定密钥长度来创建RSA,会生成新密钥。
282-
283-
#### [构造函数] new RSA(`"<xml>"`)
284-
通过`XML格式`密钥对创建RSA,xml可以是公钥或私钥,`XML格式`如:
285-
```
286-
<RSAKeyValue><Modulus>mMPfjN/kRMw7WKsAa7P2rPzsvBkROTpp6jldBH5BIgiI4nM21RBZ2d6kYy2wwE35gcTUOnOhYGvJ19vIJRB/2i/0RtinaSPCjFKigLMzcnbB0nofTEinHec4EuDbhNLvnkewgfJDloqYiw0JmN/JKTN+qUVnTUJaSGkw6OSISSc=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>
287-
```
288-
289-
#### [构造函数] new RSA(`"PEM"`, `any`)
290-
通过`PEM格式`密钥对创建RSA,PEM可以是公钥或私钥,支持`PKCS#1``PKCS#8`格式,`PEM格式`如:
291-
```
292-
-----BEGIN PUBLIC KEY-----
293-
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCYw9+M3+REzDtYqwBrs/as/Oy8
294-
GRE5OmnqOV0EfkEiCIjiczbVEFnZ3qRjLbDATfmBxNQ6c6Fga8nX28glEH/aL/RG
295-
2KdpI8KMUqKAszNydsHSeh9MSKcd5zgS4NuE0u+eR7CB8kOWipiLDQmY38kpM36p
296-
RWdNQlpIaTDo5IhJJwIDAQAB
297-
-----END PUBLIC KEY-----
298-
```
299-
300-
#### [方法] .ToXML(`[false]是否仅仅导出公钥`)
301-
导出`XML格式`秘钥对。如果RSA包含私钥,默认会导出私钥,设置仅仅导出公钥时只会导出公钥;不包含私钥只会导出公钥。
302-
303-
#### [方法] .ToPEM_PKCS1|.ToPEM_PKCS8(`[false]是否仅仅导出公钥`)
304-
导出`PEM格式`秘钥对,两个方法分别导出`PKCS#1``PKCS#8`格式。如果RSA包含私钥,默认会导出私钥,设置仅仅导出公钥时只会导出公钥;不包含私钥只会导出公钥。
305-
306-
#### [方法] .Encode(`"字符串"|bytes`)
307-
加密操作,支持任意长度数据。
308-
309-
#### [方法] .DecodeOrNull(`"Base64字符串"|bytes`)
310-
解密操作,解密失败返回null,支持任意长度数据。
311-
312-
#### [方法] .Sign(`"hash"`, `"字符串"|bytes`)
313-
通过hash算法(MD5、SHA1等)来对数据进行签名。
314-
315-
#### [方法] .Verify(`"hash"`, `"sign"`, `"字符串"`)
316-
通过hash算法(MD5、SHA1等)来验证字符串是否和sign签名一致。
317-
318-
319-
### RSA_PEM.cs
320-
此文件不依赖任何文件,可以单独copy来用(`RSA_Unit`里面的方法可以忽略)
321-
322-
#### [静态方法] .FromPEM(`"PEM"`)
323-
通过`PEM格式`秘钥对来创建`RSACryptoServiceProvider`,PEM可以是公钥或私钥。
324-
325-
#### [静态方法] .ToPEM(`RSACryptoServiceProvider`, `exportPublicOnly`, `usePKCS8`)
326-
将RSA中的密钥对导出成`PEM格式``usePKCS8=false`时返回`PKCS#1格式`,否则返回`PKCS#8格式`。如果RSA包含私钥,默认会导出私钥,设置仅仅导出公钥时只会导出公钥;不包含私钥只会导出公钥。
327-
328-
329-
330-
## 次要文件
331-
332-
## RSA_Unit.cs
333-
封装的一些通用方法,如:base64。没有此文件也可以,引用的地方用别的代码实现。
334-
335-
## Program.cs
336-
控制台入口文件,用来测试的,里面包含了主要的使用用例。
337-
338-
339-
340-
## 图例
341-
342-
控制台运行:
343-
344-
![控制台运行](images/1.png)
345-
346-
RSA工具:
347-
348-
![RSA工具](images/2.png)

0 commit comments

Comments
 (0)