0
点赞
收藏
分享

微信扫一扫

网Js RSA加密,后端(Asp.Net)解码(非对称加解密)

guanguans 2022-07-12 阅读 33

前言

RSA加解密知识自行百度了解决一下

1、取得公钥与私钥方法

​​JSEncrypt Download​​ 

网Js RSA加密,后端(Asp.Net)解码(非对称加解密)_html

 

 

下载后将其发布成网站进入:http://127.0.0.1:3000/demo/index.html (各自服务器站口不一样自行)

网Js RSA加密,后端(Asp.Net)解码(非对称加解密)_4s_02

 

 

这样就得到一公钥和私钥

另一种生成公钥与私钥的方法如下​

======================================Begin======================================

1. OpenSSL官网
官方下载地址: https://www.openssl.org/source/

2. Windows安装方法
OpenSSL官网没有提供windows版本的安装包,可以选择其他开源平台提供的工具。例如 http://slproweb.com/products/Win32OpenSSL.html
以该工具为例,安装步骤和使用方法如下:

2.1 选择32位或者64位合适的版本下载,例如Win64OpenSSL_Light-1_0_2h.exe:

2.2 设置环境变量,例如工具安装在C:\OpenSSL-Win64,则将C:\OpenSSL-Win64\bin;复制到Path中

2.3 打开命令行程序cmd(以管理员身份运行),运行以下命令:

这里路径就是保存地址

利用 openssl 生成公钥私钥
生成公钥: openssl genrsa -out rsa_private_key.pem 1024
生成私钥: openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem

======================================End=======================================

2、实践(引用:​​https://www.jb51.net/article/117127.htm​​)

参数传递的+号处理,在传输时会把+变成空格,不处理后端就报错了。

1、前端代码

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


​<!DOCTYPE html>​

​<html>​

​<head>​

​<meta name=​​​​"viewport"​​​ ​​content=​​​​"width=device-width"​​​ ​​/>​

​<title>Login</title>​

​<script src=​​​​"jquery-1.10.2.min.js"​​​​></script>​

​<script src=​​​​"jsencrypt.min.js"​​​​></script>​

​<script type=​​​​"text/javascript"​​​​>​

​$(​​​​function​​​ ​​() {​

​var​​​ ​​encrypt = ​​​​new​​​ ​​JSEncrypt();​

​encrypt.setPublicKey($(​​​​"#tra"​​​​).val());​

​var​​​ ​​data = encrypt.encrypt(​​​​"123456789"​​​​);​

​alert(data);​

​$(​​​​"#btn"​​​​).click(​​​​function​​​ ​​() {​

​$.ajax({​

​url: ​​​​'@Url.Action("Login")'​​​​,​

​data: ​​​​"pwd="​​​ ​​+ encodeURI(data).replace(/\+/g, ​​​​'%2B'​​​​), ​​​​//+号的处理:因为数据在网络上传输时,非字母数字字符都将被替换成百分号(%)后跟两位十六进制数,而base64编码在传输到后端的时候,+会变成空格,因此先替换掉。后端再替换回来​

​type: ​​​​'post'​​​​,​

​success: ​​​​function​​​ ​​(msg) {​

​alert(msg);​

​}​

​});​

​});​

​});​

​</script>​

​</head>​

​<body>​

​<div>​

​<input type=​​​​"button"​​​ ​​id=​​​​"btn"​​​ ​​value=​​​​"点我"​​​ ​​/>​

​<textarea id=​​​​"tra"​​​ ​​rows=​​​​"15"​​​ ​​cols=​​​​"65"​​​​>​

​MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCa4KHNwDX44gGmmIAtRu4gjVYt​

​GWZzcm4t+1wjUD4dn7fMLPvuK7ai4UrfDeEJE1RPwudJw+lJ6crql8wSIg7/DbTl​

​G3ihsCT6dT9H5B9OoeR7K9VWUesaW/iyVL6HXiYOANabW14pvJATDmdq91Tfgp6P​

​SQyvdfiRdV4r07crpQIDAQAB​

​</textarea>​

​<hr/>​

​注意+号的处理​

​</div>​

​</body>​

​</html>​


2、后端代码

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


​public​​​ ​​class​​​ ​​IndexController : Controller​

​{​

​public​​​ ​​ActionResult Login()​

​{​

​return​​​ ​​View();​

​}​

​[HttpPost]​

​public​​​ ​​ActionResult Login(​​​​string​​​ ​​pwd)​

​{​

​//密钥格式要生成pkcs#1格式的  而不是pkcs#8格式的​

​string​​​ ​​privateKey = ​​​​@"MIICWwIBAAKBgQCa4KHNwDX44gGmmIAtRu4gjVYtGWZzcm4t+1wjUD4dn7fMLPvuK7ai4UrfDeEJE1RPwudJw+lJ6crql8wSIg7/DbTlG3ihsCT6dT9H5B9OoeR7K9VW​

​UesaW/iyVL6HXiYOANabW14pvJATDmdq91Tfgp6PSQyvdfiRdV4r07crpQIDAQAB​

​AoGABb+3gdb+qeG0b1CogVsT/7//UOaTzPk/FGneKQQTf4SsN+H7lVhTYTG9ARFC​

​JyoWg8IXqmn2ljhywHPTWWD2RCZIn2sYT1sVkGb70EgHGQLBraFHElmw+DsVJ+nD​

​fBCfMrJ1TYXlwigjRkaueaoGgG8LdR8XD+Xs5LersPLjZgECQQCguSB7C4wF6oSw​

​EDmwNF8ffT5cQc1U2OIq6NBG8rafrjb7LsjhOd03pmY7i4LbW3Vvq4AhQpJEdF1C​

​vd+Sk/BBAkEA9rBhqnyumV09zFEomSX3zZu+bdhTzM4bJDfEa95swp1gANCVvF/t​

​DCnlBf51EhCWdeGSpARPUkQnXrYfFUDiZQJAAZEshuaa6+fYeVr/JP+tucHf3Mhr​

​dxtSQTbZ6QcuzqnFMXfIT6HfzU4bCxOWKAthPsB+VFSw1mgIDMGLL4OvwQJAJlVy​

​V9PYLezXVZCnBmVoBINXLCqZmxHMFey0kS6XKAbcjEPdgNBHPcSk2jGYb540Q00y​

​RFqHGPmORKF4Yw0aIQJAd5JRtD3z2MgP/vPoKHJNHqY8bboVcmwqVAm6xCZoTCZz​

​jNV1Cnsdf4wBV3LCDzYBy+xR4qYNUy5CFXN+8WzzAA=="​​​​;​

​try​

​{​

​RSACryptoServiceProvider rsaCryptoServiceProvider = CreateRsaProviderFromPrivateKey(privateKey);​

​//把+号,再替换回来​

​byte​​​​[] res = rsaCryptoServiceProvider.Decrypt(Convert.FromBase64String(pwd.Replace(​​​​"%2B"​​​​,​​​​"+"​​​​)), ​​​​false​​​​);​

​return​​​ ​​Content(Encoding.UTF8.GetString(res));​

​}​

​catch​​​ ​​(Exception exception)​

​{​

​}​

​return​​​ ​​Content(​​​​""​​​​);​

​}​

​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;​

​}​

​}​


测试源码在下面GitHub上有(可以给我留言)

​​https://github.com/xiaoruilin/EncryptionDecrypt​​

 

加解密算法:

网Js RSA加密,后端(Asp.Net)解码(非对称加解密)_4s_03

网Js RSA加密,后端(Asp.Net)解码(非对称加解密)_html_04

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace Common
{
public class RSA
{
/// <summary>
/// RSA公钥加密
/// </summary>
/// <param name="publickey">公钥</param>
/// <param name="content">待加密字符串</param>
/// <param name="input_charset">编码格式,UTF-8</param>
/// <returns></returns>
public static string RasEncrypt(string publickey, string content, string input_charset)
{
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
byte[] cipherbytes;
rsa.ImportParameters(ConvertFromPublicKey(publickey));
cipherbytes = rsa.Encrypt(Encoding.GetEncoding(input_charset).GetBytes(content), false);
return Convert.ToBase64String(cipherbytes);
}

/// <summary>
/// RSA私钥解密
/// </summary>
/// <param name="resData">RSA加密后字符串</param>
/// <param name="privateKey">私钥</param>
/// <param name="input_charset">编码格式,UTF-8</param>
/// <returns>明文</returns>
public static string RsaDecrypt(string resData, string privateKey, string input_charset)
{
byte[] DataToDecrypt = Convert.FromBase64String(resData);
string result = "";
for (int j = 0; j < DataToDecrypt.Length / 128; j++)
{
byte[] buf = new byte[128];
for (int i = 0; i < 128; i++)
{

buf[i] = DataToDecrypt[i + 128 * j];
}
result += decrypt(buf, privateKey, input_charset);
}
return result;
}

#region 内部方法

private static string decrypt(byte[] data, string privateKey, string input_charset)
{
string result = "";
RSACryptoServiceProvider rsa = DecodePemPrivateKey(privateKey);
using (var sh = SHA1.Create())
{
byte[] source = rsa.Decrypt(data, false);
char[] asciiChars = new char[Encoding.GetEncoding(input_charset).GetCharCount(source, 0, source.Length)];
Encoding.GetEncoding(input_charset).GetChars(source, 0, source.Length, asciiChars, 0);
result = new string(asciiChars);
return result;
}

}

private static RSACryptoServiceProvider DecodePemPrivateKey(String pemstr)
{
RSACryptoServiceProvider rsa = DecodeRSAPrivateKey(Convert.FromBase64String(pemstr));
return rsa;
}

private static RSACryptoServiceProvider DecodeRSAPrivateKey(byte[] privkey)
{
byte[] MODULUS, E, D, P, Q, DP, DQ, IQ;

// --------- Set up stream to decode the asn.1 encoded RSA private key ------
MemoryStream mem = new MemoryStream(privkey);
BinaryReader binr = new BinaryReader(mem); //wrap Memory Stream with BinaryReader for easy reading
byte bt = 0;
ushort twobytes = 0;
int elems = 0;
try
{
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();
if (twobytes != 0x0102) //version number
return null;
bt = binr.ReadByte();
if (bt != 0x00)
return null;


//------ all private key components are Integer sequences ----
elems = GetIntegerSize(binr);
MODULUS = binr.ReadBytes(elems);

elems = GetIntegerSize(binr);
E = binr.ReadBytes(elems);

elems = GetIntegerSize(binr);
D = binr.ReadBytes(elems);

elems = GetIntegerSize(binr);
P = binr.ReadBytes(elems);

elems = GetIntegerSize(binr);
Q = binr.ReadBytes(elems);

elems = GetIntegerSize(binr);
DP = binr.ReadBytes(elems);

elems = GetIntegerSize(binr);
DQ = binr.ReadBytes(elems);

elems = GetIntegerSize(binr);
IQ = binr.ReadBytes(elems);


// ------- create RSACryptoServiceProvider instance and initialize with public key -----
CspParameters CspParameters = new CspParameters();
CspParameters.Flags = CspProviderFlags.UseMachineKeyStore;
RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(1024, CspParameters);
RSAParameters RSAparams = new RSAParameters();
RSAparams.Modulus = MODULUS;
RSAparams.Exponent = E;
RSAparams.D = D;
RSAparams.P = P;
RSAparams.Q = Q;
RSAparams.DP = DP;
RSAparams.DQ = DQ;
RSAparams.InverseQ = IQ;
RSA.ImportParameters(RSAparams);
return RSA;
}
catch
{
return null;
}
finally
{
binr.Dispose();
}
}

private static int GetIntegerSize(BinaryReader binr)
{
byte bt = 0;
byte lowbyte = 0x00;
byte highbyte = 0x00;
int count = 0;
bt = binr.ReadByte();
if (bt != 0x02) //expect integer
return 0;
bt = binr.ReadByte();

if (bt == 0x81)
count = binr.ReadByte(); // data size in next byte
else
if (bt == 0x82)
{
highbyte = binr.ReadByte(); // data size in next 2 bytes
lowbyte = binr.ReadByte();
byte[] modint = { lowbyte, highbyte, 0x00, 0x00 };
count = BitConverter.ToInt32(modint, 0);
}
else
{
count = bt; // we already have the data size
}

while (binr.ReadByte() == 0x00)
{ //remove high order zeros in data
count -= 1;
}
binr.BaseStream.Seek(-1, SeekOrigin.Current); //last ReadByte wasn't a removed zero, so back up a byte
return count;
}

#endregion

#region 生成的Pem
private static RSAParameters ConvertFromPublicKey(string pemFileConent)
{

if (string.IsNullOrEmpty(pemFileConent))
{
throw new ArgumentNullException("pemFileConent", "This arg cann't be empty.");
}
pemFileConent = pemFileConent.Replace("-----BEGIN PUBLIC KEY-----", "").Replace("-----END PUBLIC KEY-----", "").Replace("\n", "").Replace("\r", "");
byte[] keyData = Convert.FromBase64String(pemFileConent);
bool keySize1024 = (keyData.Length == 162);
bool keySize2048 = (keyData.Length == 294);
if (!(keySize1024 || keySize2048))
{
throw new ArgumentException("pem file content is incorrect, Only support the key size is 1024 or 2048");
}
byte[] pemModulus = (keySize1024 ? new byte[128] : new byte[256]);
byte[] pemPublicExponent = new byte[3];
Array.Copy(keyData, (keySize1024 ? 29 : 33), pemModulus, 0, (keySize1024 ? 128 : 256));
Array.Copy(keyData, (keySize1024 ? 159 : 291), pemPublicExponent, 0, 3);
RSAParameters para = new RSAParameters();
para.Modulus = pemModulus;
para.Exponent = pemPublicExponent;
return para;
}

#endregion

}
}

View Code

 

 

加密参数过长?​​https://www.jianshu.com/p/444011941cac​​

布署:

System.Security.Cryptography.CryptographicException: 系统找不到指定的文件。

在 System.Security.Cryptography.Utils.CreateProvHandle(CspParameters parameters, Boolean randomKeyContainer)
在 System.Security.Cryptography.RSACryptoServiceProvider.ImportParameters(RSAParameters parameters)
在 Utils.RSAHelper.CreateRsaProviderFromPrivateKey(String privateKey)
在 Yst.DataBase.SystemManage.Handler.Login.ValidateLogin()

IIS发布后报错配置:应用程序池-》对应网站有应用程序-》右键-》高级-》进程模式-》加载用户配置文件=True;

网Js RSA加密,后端(Asp.Net)解码(非对称加解密)_html_05

 



举报

相关推荐

0 条评论