服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C# - 同时兼容JS和C#的RSA加密解密算法详解(对web提交的数据加密传输)

同时兼容JS和C#的RSA加密解密算法详解(对web提交的数据加密传输)

2022-01-19 11:07JackWang-CUMT C#

这篇文章主要给大家介绍了关于同时兼容JS和C#的RSA加密解密算法,通过该算法可以对web提交的数据进行加密传输,文中通过图文及示例代码介绍的非常详细,需要的朋友们可以参考借鉴,下面来一起看看吧。

前言

我们在web应用中往往涉及到敏感的数据,由于http协议以明文的形式与服务器进行交互,因此可以通过截获请求的数据包进行分析来盗取有用的信息。虽然https可以对传输的数据进行加密,但是必须要申请证书(一般都是收费的),成本较高。那么问题来了,如果对web提交的敏感数据进行加密呢?web应用中,前端的数据处理和交互基本上都是靠javascript来完成,后台的逻辑处理可以c#(java)等进行处理。

微软的c#中虽然有rsa算法,但是格式和openssl生成的公钥/私钥文件格式并不兼容。这个也给贯通前后台的rsa加密解密带来了难度。为了兼容openssl生成的公钥/私钥文件格式,贯通javascript和c#的rsa加密解密算法,必须对c#内置的方法进行再度封装。

下面以登录为例,用户在密码框输入密码后,javascript发送ajax请求时,对密码先进行rsa加密后再发送,服务器接收到加密后的密码后,先对其进行解密, 然后再验证登录是否成功。

1、为了进行rsa加密解密,首先需要用openssl生成一对公钥和私钥(没有的先下载openssl):

   1) 打开openssl.exe文件,输入 genrsa -out openssl_rsa_priv.pem 1024

同时兼容JS和C#的RSA加密解密算法详解(对web提交的数据加密传输)

此命令在openssl.exe同目录下生成openssl_rsa_private_key.pem文件。

  2) 生成公钥 rsa  -in openssl_rsa__private.pem -pubout -out openssl_rsa__public.pem

同时兼容JS和C#的RSA加密解密算法详解(对web提交的数据加密传输)

  以上命令会创建如下的文件:

同时兼容JS和C#的RSA加密解密算法详解(对web提交的数据加密传输)

这个文件可以用文本编辑器进行打开,查看内容。

?
1
2
3
4
5
6
-----begin public key-----
migfma0gcsqgsib3dqebaquaa4gnadcbiqkbgqc0w036clsd0lvxpromun0u022r
ojlze6p3m+gjq3gpi4n7lo8jhtqmqgccdbvjqnifmzws9o3lnlqxwtxj3b4xj52f
acriy5broxuvgblx5qmhlld1gtjnmg4i7r4ytgx7xvkrnojr6zca1yns0lbggdf1
cgllb1rinrdkssqp+widaqab
-----end public key-----
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
-----begin rsa private key-----
miicxqibaakbgqc0w036clsd0lvxpromun0u022rojlze6p3m+gjq3gpi4n7lo8j
htqmqgccdbvjqnifmzws9o3lnlqxwtxj3b4xj52facriy5broxuvgblx5qmhlld1
gtjnmg4i7r4ytgx7xvkrnojr6zca1yns0lbggdf1cgllb1rinrdkssqp+widaqab
aogaioyl6lixxkulzobkbeqxfiz0gwxlgg1ywyn5mw2lagqzkmken0iobnd9xivw
rolhyhkivbcyuc0jgfe2avn93mlb3j0wruxmfljpcbleklmilo9zgmwl+vtb3vzb
8vzdreeeubio7lwp/kvso+iflnjdtkgaczbltwamj4w6g0ecqqdm4yxpdxcu2ywz
7pyjimm9qnsah9kcrju8gjeyhsupgtjhw1cx7peo+vrihqxdy1yasu1blwrr52pc
jknnl0qhakeaygx3nxeiilk2oxggbimz4p6gec8gyu01birnwvf0yi7+sch68eup
oi+g5bj8bvzxpvhjqi0s2olrfct/qtpqmwjbala+2donbxdy4lui3lo/esk0qvao
aoty3gomggnjkqro4zzoabxkgaif/6gp3u9j5ug4rffd1m19xp2pk0zk1aecqbyi
ljakw4zuf7ca3z3axozqckktwdnrjl4g6fwdsmpfonwvcw4ije+xsk64bbiktptr
hhpa9wchba6c+p6e4h0cqqdwegmmpkqpg/w4afncgmvrnm8vnkguamdgvcsfktid
ijpkl5sd55hphswe5rsv1tlupkwtrfbcg61bhwmup3cv
-----end rsa private key-----

2、用jsencrypt对密码进行加密:

首先需要导入js包文件

?
1
<script src="dist/js/jsencrypt.js"></script>
?
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
var encrypt = new jsencrypt();
var pubkey = "-----begin public key----- \
 migfma0gcsqgsib3dqebaquaa4gnadcbiqkbgqdaj0dpnbmf3z4vt1b8ee6bjkns \
 hlyj7xvgijaa8rcdmgr7mrtrexnk8mdulwdcs05gc4ssfoywjcytkuhpwn8/pks0 \
 vggol9bzn0xt9hiqtb3pzafyknrmdgzmgjgfd6ktnfzvuaoupvxjcgkcoj6/vv5i \
 emcx8mt/z3elfsdsjqidaqab \
 -----end public key-----";
encrypt.setpublickey(pubkey);
var encrypted = encrypt.encrypt($('#txtpwd').val());
//console.log(encrypted);
$.ajax({
 type: "post",
 url: "http://localhost:24830/services/rsa_pem.ashx",
 data: { "pwd": encrypted },
 datatype: "json",
 error: function (xhr, status, error) {
  // alert(error);
  $("#txtinfo").text(' 请求服务器失败!');
  $(that).text('登 录');
  $(that).attr('disabled', false);
 },
 success: function (json) {
 
 if (uid == "admin" && json.data=="000") {
  window.location.href = "index.html";
 }
 else {
  $("#txtinfo").text(' 用户名或者密码错误!');
  $(that).text('登 录');
  $(that).attr('disabled', false);
 }
 }
});

3、后台用c#进行解密

?
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
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
using system;
using system.collections.generic;
using system.io;
using system.linq;
using system.security.cryptography;
using system.text;
using system.threading.tasks;
 
namespace cmcloud.saas
{
 public class rsacryptoservice
 {
 private rsacryptoserviceprovider _privatekeyrsaprovider;
 private rsacryptoserviceprovider _publickeyrsaprovider;
 
 /// <summary>
 /// rsa解密
 /// </summary>
 /// <param name="ciphertext"></param>
 /// <returns></returns>
 public string decrypt(string ciphertext)
 {
  if (_privatekeyrsaprovider == null)
  {
  throw new exception("_privatekeyrsaprovider is null");
  }
  return decrypt2(ciphertext);
 }
 /// <summary>
 /// rsa加密
 /// </summary>
 /// <param name="text"></param>
 /// <returns></returns>
 public string encrypt(string text)
 {
  if (_publickeyrsaprovider == null)
  {
  throw new exception("_publickeyrsaprovider is null");
  }
  return encrypt2(text);
  //return convert.tobase64string(_publickeyrsaprovider.encrypt(encoding.utf8.getbytes(text), false));
 
 }
 private string encrypt2(string text)
 {
 
 
  byte[] plaintextdata = encoding.utf8.getbytes(text);
  int maxblocksize = _publickeyrsaprovider.keysize / 8 - 11;//加密块最大长度限制
 
  if (plaintextdata.length <= maxblocksize)
  {
  return convert.tobase64string(_publickeyrsaprovider.encrypt(plaintextdata, false));
  }
  else
  {
  using (memorystream plaistream = new memorystream(plaintextdata))
  using (memorystream crypstream = new memorystream())
  {
   byte[] buffer = new byte[maxblocksize];
   int blocksize = plaistream.read(buffer, 0, maxblocksize);
 
   while (blocksize > 0)
   {
   byte[] toencrypt = new byte[blocksize];
   array.copy(buffer, 0, toencrypt, 0, blocksize);
 
   byte[] cryptograph = _publickeyrsaprovider.encrypt(toencrypt, false);
   crypstream.write(cryptograph, 0, cryptograph.length);
 
   blocksize = plaistream.read(buffer, 0, maxblocksize);
   }
 
   return convert.tobase64string(crypstream.toarray(), base64formattingoptions.none);
  }
  }
 
 
 
 
 }
 
 private string decrypt2(string ciphertext)
 {
 
 
  byte[] ciphertextdata = convert.frombase64string(ciphertext);
  int maxblocksize = _privatekeyrsaprovider.keysize / 8; //解密块最大长度限制
 
  if (ciphertextdata.length <= maxblocksize)
  return system.text.encoding.utf8.getstring(_privatekeyrsaprovider.decrypt(ciphertextdata, false));
 
  using (memorystream crypstream = new memorystream(ciphertextdata))
  using (memorystream plaistream = new memorystream())
  {
  byte[] buffer = new byte[maxblocksize];
  int blocksize = crypstream.read(buffer, 0, maxblocksize);
 
  while (blocksize > 0)
  {
   byte[] todecrypt = new byte[blocksize];
   array.copy(buffer, 0, todecrypt, 0, blocksize);
 
   byte[] plaintext = _privatekeyrsaprovider.decrypt(todecrypt, false);
   plaistream.write(plaintext, 0, plaintext.length);
 
   blocksize = crypstream.read(buffer, 0, maxblocksize);
  }
 
  return system.text.encoding.utf8.getstring(plaistream.toarray());
  }
 }
 public rsacryptoservice(string privatekey, string publickey = null)
 {
  if (!string.isnullorempty(privatekey))
  {
  _privatekeyrsaprovider = creatersaproviderfromprivatekey(privatekey);
  }
 
  if (!string.isnullorempty(publickey))
  {
  _publickeyrsaprovider = creatersaproviderfrompublickey(publickey);
  }
 }
 
 
 
 private rsacryptoserviceprovider creatersaproviderfromprivatekey(string privatekey)
 {
  var privatekeybits = system.convert.frombase64string(privatekey);
 
  var rsa = new rsacryptoserviceprovider();
  var rsaparams = new rsaparameters();
 
  using (binaryreader binr = new binaryreader(new memorystream(privatekeybits)))
  {
  byte bt = 0;
  ushort twobytes = 0;
  twobytes = binr.readuint16();
  if (twobytes == 0x8130)
   binr.readbyte();
  else if (twobytes == 0x8230)
   binr.readint16();
  else
   throw new exception("unexpected value read binr.readuint16()");
 
  twobytes = binr.readuint16();
  if (twobytes != 0x0102)
   throw new exception("unexpected version");
 
  bt = binr.readbyte();
  if (bt != 0x00)
   throw new exception("unexpected value read binr.readbyte()");
 
  rsaparams.modulus = binr.readbytes(getintegersize(binr));
  rsaparams.exponent = binr.readbytes(getintegersize(binr));
  rsaparams.d = binr.readbytes(getintegersize(binr));
  rsaparams.p = binr.readbytes(getintegersize(binr));
  rsaparams.q = binr.readbytes(getintegersize(binr));
  rsaparams.dp = binr.readbytes(getintegersize(binr));
  rsaparams.dq = binr.readbytes(getintegersize(binr));
  rsaparams.inverseq = binr.readbytes(getintegersize(binr));
  }
 
  rsa.importparameters(rsaparams);
  return rsa;
 }
 
 private int getintegersize(binaryreader binr)
 {
  byte bt = 0;
  byte lowbyte = 0x00;
  byte highbyte = 0x00;
  int count = 0;
  bt = binr.readbyte();
  if (bt != 0x02)
  return 0;
  bt = binr.readbyte();
 
  if (bt == 0x81)
  count = binr.readbyte();
  else
  if (bt == 0x82)
  {
  highbyte = binr.readbyte();
  lowbyte = binr.readbyte();
  byte[] modint = { lowbyte, highbyte, 0x00, 0x00 };
  count = bitconverter.toint32(modint, 0);
  }
  else
  {
  count = bt;
  }
 
  while (binr.readbyte() == 0x00)
  {
  count -= 1;
  }
  binr.basestream.seek(-1, seekorigin.current);
  return count;
 }
 
 private rsacryptoserviceprovider creatersaproviderfrompublickey(string publickeystring)
 {
  // encoded oid sequence for pkcs #1 rsaencryption szoid_rsa_rsa = "1.2.840.113549.1.1.1"
  byte[] seqoid = { 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00 };
  byte[] x509key;
  byte[] seq = new byte[15];
  int x509size;
 
  x509key = convert.frombase64string(publickeystring);
  x509size = x509key.length;
 
  // --------- set up stream to read the asn.1 encoded subjectpublickeyinfo blob ------
  using (memorystream mem = new memorystream(x509key))
  {
  using (binaryreader binr = new binaryreader(mem)) //wrap memory stream with binaryreader for easy reading
  {
   byte bt = 0;
   ushort twobytes = 0;
 
   twobytes = binr.readuint16();
   if (twobytes == 0x8130) //data read as little endian order (actual data order for sequence is 30 81)
   binr.readbyte(); //advance 1 byte
   else if (twobytes == 0x8230)
   binr.readint16(); //advance 2 bytes
   else
   return null;
 
   seq = binr.readbytes(15); //read the sequence oid
   if (!comparebytearrays(seq, seqoid)) //make sure sequence for oid is correct
   return null;
 
   twobytes = binr.readuint16();
   if (twobytes == 0x8103) //data read as little endian order (actual data order for bit string is 03 81)
   binr.readbyte(); //advance 1 byte
   else if (twobytes == 0x8203)
   binr.readint16(); //advance 2 bytes
   else
   return null;
 
   bt = binr.readbyte();
   if (bt != 0x00) //expect null byte next
   return null;
 
   twobytes = binr.readuint16();
   if (twobytes == 0x8130) //data read as little endian order (actual data order for sequence is 30 81)
   binr.readbyte(); //advance 1 byte
   else if (twobytes == 0x8230)
   binr.readint16(); //advance 2 bytes
   else
   return null;
 
   twobytes = binr.readuint16();
   byte lowbyte = 0x00;
   byte highbyte = 0x00;
 
   if (twobytes == 0x8102) //data read as little endian order (actual data order for integer is 02 81)
   lowbyte = binr.readbyte(); // read next bytes which is bytes in modulus
   else if (twobytes == 0x8202)
   {
   highbyte = binr.readbyte(); //advance 2 bytes
   lowbyte = binr.readbyte();
   }
   else
   return null;
   byte[] modint = { lowbyte, highbyte, 0x00, 0x00 }; //reverse byte order since asn.1 key uses big endian order
   int modsize = bitconverter.toint32(modint, 0);
 
   int firstbyte = binr.peekchar();
   if (firstbyte == 0x00)
   { //if first byte (highest order) of modulus is zero, don't include it
   binr.readbyte(); //skip this null byte
   modsize -= 1; //reduce modulus buffer size by 1
   }
 
   byte[] modulus = binr.readbytes(modsize); //read the modulus bytes
 
   if (binr.readbyte() != 0x02//expect an integer for the exponent data
   return null;
   int expbytes = (int)binr.readbyte(); // should only need one byte for actual exponent data (for all useful values)
   byte[] exponent = binr.readbytes(expbytes);
 
   // ------- create rsacryptoserviceprovider instance and initialize with public key -----
   rsacryptoserviceprovider rsa = new rsacryptoserviceprovider();
   rsaparameters rsakeyinfo = new rsaparameters();
   rsakeyinfo.modulus = modulus;
   rsakeyinfo.exponent = exponent;
   rsa.importparameters(rsakeyinfo);
 
   return rsa;
  }
 
  }
 }
 
 private bool comparebytearrays(byte[] a, byte[] b)
 {
  if (a.length != b.length)
  return false;
  int i = 0;
  foreach (byte c in a)
  {
  if (c != b[i])
   return false;
  i++;
  }
  return true;
 }
 }
}

同时兼容JS和C#的RSA加密解密算法详解(对web提交的数据加密传输)

虽然将公钥暴露在js文件中,但是如果需要解密得到明文,必须需要私钥(这个存储在后台,不容易获取)。

调试运行,可以看到获取的密码是加密后的数据,然后在后台可以进行解密获取到明文。

同时兼容JS和C#的RSA加密解密算法详解(对web提交的数据加密传输)

总结

好了,大概就这样,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对服务器之家的支持

原文链接:http://www.cnblogs.com/isaboy/p/csharp_openssl_rsa_jsencrypt.html

延伸 · 阅读

精彩推荐
  • C#C#微信公众号与订阅号接口开发示例代码

    C#微信公众号与订阅号接口开发示例代码

    这篇文章主要介绍了C#微信公众号与订阅号接口开发示例代码,结合实例形式简单分析了C#针对微信接口的调用与处理技巧,需要的朋友可以参考下...

    smartsmile20127762021-11-25
  • C#SQLite在C#中的安装与操作技巧

    SQLite在C#中的安装与操作技巧

    SQLite,是一款轻型的数据库,用于本地的数据储存。其优点有很多,下面通过本文给大家介绍SQLite在C#中的安装与操作技巧,感兴趣的的朋友参考下吧...

    蓝曈魅11162022-01-20
  • C#三十分钟快速掌握C# 6.0知识点

    三十分钟快速掌握C# 6.0知识点

    这篇文章主要介绍了C# 6.0的相关知识点,文中介绍的非常详细,通过这篇文字可以让大家在三十分钟内快速的掌握C# 6.0,需要的朋友可以参考借鉴,下面来...

    雨夜潇湘8272021-12-28
  • C#深入理解C#的数组

    深入理解C#的数组

    本篇文章主要介绍了C#的数组,数组是一种数据结构,详细的介绍了数组的声明和访问等,有兴趣的可以了解一下。...

    佳园9492021-12-10
  • C#C#设计模式之Strategy策略模式解决007大破密码危机问题示例

    C#设计模式之Strategy策略模式解决007大破密码危机问题示例

    这篇文章主要介绍了C#设计模式之Strategy策略模式解决007大破密码危机问题,简单描述了策略模式的定义并结合加密解密算法实例分析了C#策略模式的具体使用...

    GhostRider10972022-01-21
  • C#VS2012 程序打包部署图文详解

    VS2012 程序打包部署图文详解

    VS2012虽然没有集成打包工具,但它为我们提供了下载的端口,需要我们手动安装一个插件InstallShield。网上有很多第三方的打包工具,但为什么偏要使用微软...

    张信秀7712021-12-15
  • C#如何使用C#将Tensorflow训练的.pb文件用在生产环境详解

    如何使用C#将Tensorflow训练的.pb文件用在生产环境详解

    这篇文章主要给大家介绍了关于如何使用C#将Tensorflow训练的.pb文件用在生产环境的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴...

    bbird201811792022-03-05
  • C#利用C#实现网络爬虫

    利用C#实现网络爬虫

    这篇文章主要介绍了利用C#实现网络爬虫,完整的介绍了C#实现网络爬虫详细过程,感兴趣的小伙伴们可以参考一下...

    C#教程网11852021-11-16