forked from xiangyuecn/RSA-csharp
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathRSA.cs
223 lines (201 loc) · 6.72 KB
/
RSA.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
namespace com.github.xiangyuecn.rsacsharp {
/// <summary>
/// RSA操作类
/// GitHub: https://github.com/xiangyuecn/RSA-csharp
/// </summary>
public class RSA {
/// <summary>
/// 导出XML格式密钥对,如果convertToPublic含私钥的RSA将只返回公钥,仅含公钥的RSA不受影响
/// </summary>
public string ToXML(bool convertToPublic = false) {
return rsa.ToXmlString(!rsa.PublicOnly && !convertToPublic);
}
/// <summary>
/// 将密钥对导出成PEM对象,如果convertToPublic含私钥的RSA将只返回公钥,仅含公钥的RSA不受影响
/// </summary>
public RSA_PEM ToPEM(bool convertToPublic = false) {
return new RSA_PEM(rsa, convertToPublic);
}
/// <summary>
/// 加密字符串(utf-8),出错抛异常
/// </summary>
public string Encode(string str) {
return Convert.ToBase64String(Encode(Encoding.UTF8.GetBytes(str)));
}
/// <summary>
/// 加密数据,出错抛异常
/// </summary>
public byte[] Encode(byte[] data) {
int blockLen = rsa.KeySize / 8 - 11;
if (data.Length <= blockLen) {
return rsa.Encrypt(data, false);
}
using (var dataStream = new MemoryStream(data))
using (var enStream = new MemoryStream()) {
Byte[] buffer = new Byte[blockLen];
int len = dataStream.Read(buffer, 0, blockLen);
while (len > 0) {
Byte[] block = new Byte[len];
Array.Copy(buffer, 0, block, 0, len);
Byte[] enBlock = rsa.Encrypt(block, false);
enStream.Write(enBlock, 0, enBlock.Length);
len = dataStream.Read(buffer, 0, blockLen);
}
return enStream.ToArray();
}
}
/// <summary>
/// 解密字符串(utf-8),解密异常返回null
/// </summary>
public string DecodeOrNull(string str) {
if (String.IsNullOrEmpty(str)) {
return null;
}
byte[] byts = null;
try { byts = Convert.FromBase64String(str); } catch { }
if (byts == null) {
return null;
}
var val = DecodeOrNull(byts);
if (val == null) {
return null;
}
return Encoding.UTF8.GetString(val);
}
/// <summary>
/// 解密数据,解密异常返回null
/// </summary>
public byte[] DecodeOrNull(byte[] data) {
try {
int blockLen = rsa.KeySize / 8;
if (data.Length <= blockLen) {
return rsa.Decrypt(data, false);
}
using (var dataStream = new MemoryStream(data))
using (var deStream = new MemoryStream()) {
Byte[] buffer = new Byte[blockLen];
int len = dataStream.Read(buffer, 0, blockLen);
while (len > 0) {
Byte[] block = new Byte[len];
Array.Copy(buffer, 0, block, 0, len);
Byte[] deBlock = rsa.Decrypt(block, false);
deStream.Write(deBlock, 0, deBlock.Length);
len = dataStream.Read(buffer, 0, blockLen);
}
return deStream.ToArray();
}
} catch {
return null;
}
}
/// <summary>
/// 对str进行签名,并指定hash算法(如:SHA256)
/// </summary>
public string Sign(string hash, string str) {
return Convert.ToBase64String(Sign(hash, Encoding.UTF8.GetBytes(str)));
}
/// <summary>
/// 对data进行签名,并指定hash算法(如:SHA256)
/// </summary>
public byte[] Sign(string hash, byte[] data) {
return rsa.SignData(data, hash);
}
/// <summary>
/// 验证字符串str的签名是否是sgin,并指定hash算法(如:SHA256)
/// </summary>
public bool Verify(string hash, string sgin, string str) {
byte[] byts = null;
try { byts = Convert.FromBase64String(sgin); } catch { }
if (byts == null) {
return false;
}
return Verify(hash, byts, Encoding.UTF8.GetBytes(str));
}
/// <summary>
/// 验证data的签名是否是sgin,并指定hash算法(如:SHA256)
/// </summary>
public bool Verify(string hash, byte[] sgin, byte[] data) {
try {
return rsa.VerifyData(data, hash, sgin);
} catch {
return false;
}
}
private RSACryptoServiceProvider rsa;
/// <summary>
/// 最底层的RSACryptoServiceProvider对象
/// </summary>
public RSACryptoServiceProvider RSAObject {
get {
return rsa;
}
}
/// <summary>
/// 密钥位数
/// </summary>
public int KeySize {
get {
return rsa.KeySize;
}
}
/// <summary>
/// 是否包含私钥
/// </summary>
public bool HasPrivate {
get {
return !rsa.PublicOnly;
}
}
/// <summary>
/// 用指定密钥大小创建一个新的RSA,出错抛异常
/// </summary>
public RSA(int keySize) {
var rsaParams = new CspParameters();
rsaParams.Flags = CspProviderFlags.UseMachineKeyStore;
rsa = new RSACryptoServiceProvider(keySize, rsaParams);
}
/// <summary>
/// 通过指定的密钥,创建一个RSA,xml内可以只包含一个公钥或私钥,或都包含,出错抛异常
/// </summary>
public RSA(string xml) {
var rsaParams = new CspParameters();
rsaParams.Flags = CspProviderFlags.UseMachineKeyStore;
rsa = new RSACryptoServiceProvider(rsaParams);
rsa.FromXmlString(xml);
}
/// <summary>
/// 通过一个pem文件创建RSA,pem为公钥或私钥,出错抛异常
/// </summary>
public RSA(string pem, bool noop) {
rsa = RSA_PEM.FromPEM(pem).GetRSA();
}
/// <summary>
/// 通过一个pem对象创建RSA,pem为公钥或私钥,出错抛异常
/// </summary>
public RSA(RSA_PEM pem) {
rsa = pem.GetRSA();
}
/// <summary>
/// 本方法会先生成RSA_PEM再创建RSA:通过公钥指数和私钥指数构造一个PEM,会反推计算出P、Q但和原始生成密钥的P、Q极小可能相同
/// 注意:所有参数首字节如果是0,必须先去掉
/// 出错将会抛出异常
/// </summary>
/// <param name="modulus">必须提供模数</param>
/// <param name="exponent">必须提供公钥指数</param>
/// <param name="dOrNull">私钥指数可以不提供,导出的PEM就只包含公钥</param>
public RSA(byte[] modulus, byte[] exponent, byte[] dOrNull) {
rsa = new RSA_PEM(modulus, exponent, dOrNull).GetRSA();
}
/// <summary>
/// 本方法会先生成RSA_PEM再创建RSA:通过全量的PEM字段数据构造一个PEM,除了模数modulus和公钥指数exponent必须提供外,其他私钥指数信息要么全部提供,要么全部不提供(导出的PEM就只包含公钥)
/// 注意:所有参数首字节如果是0,必须先去掉
/// </summary>
public RSA(byte[] modulus, byte[] exponent, byte[] d, byte[] p, byte[] q, byte[] dp, byte[] dq, byte[] inverseQ) {
rsa = new RSA_PEM(modulus, exponent, d, p, q, dp, dq, inverseQ).GetRSA();
}
}
}