前言
非对称加密算法的优缺点就不赘述了,目前使用最广泛的就是RSA算法,而在Web项目中一些关键信息肯定是不能明文传输的,最简单的就是用户密码。
而.NET下的RSA类所生成的密钥为Xml格式,而其他语言比如java一般使用pkcs8格式的密钥,前端JavaScript一般使用pkcs1格式。格式不同导致后端密钥无法被前端使用,我们就得想办法统一key进行加解密,下面是我总结的解决方案(我只是一个总结者,下面内容来源于博客园多个前辈,只是当时没有记录来源,写文时没法贴上链接)
正文
后端
使用类库:“BouncyCastle.NetCore”(.Net FrameWork使用“BouncyCastle”)
using System;
using System.IO;
using System.Text;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Encodings;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Security;
namespace Utility
{
/// <summary>
/// RAS非对称算法
/// </summary>
public class RSAUtility
{
/// <summary>
/// 生成PEM格式的公钥和密钥
/// </summary>
/// <param name="strength">长度</param>
/// <returns>Item1:公钥;Item2:私钥;</returns>
public static string, string) CreateKeyPairint strength = 1024)
{
RsaKeyPairGenerator r = new RsaKeyPairGenerator);
r.Initnew KeyGenerationParametersnew SecureRandom), strength));
AsymmetricCipherKeyPair keys = r.GenerateKeyPair);
TextWriter privateTextWriter = new StringWriter);
PemWriter privatePemWriter = new PemWriterprivateTextWriter);
privatePemWriter.WriteObjectkeys.Private);
privatePemWriter.Writer.Flush);
TextWriter publicTextWriter = new StringWriter);
PemWriter publicPemWriter = new PemWriterpublicTextWriter);
publicPemWriter.WriteObjectkeys.Public);
publicPemWriter.Writer.Flush);
return publicTextWriter.ToString), privateTextWriter.ToString));
}
/// <summary>
/// RSA解密
/// </summary>
/// <param name="privateKey">私钥</param>
/// <param name="decryptstring">待解密的字符串Base64)</param>
/// <returns>解密后的字符串</returns>
public static string Decryptstring privateKey, string decryptstring)
{
using TextReader reader = new StringReaderprivateKey))
{
dynamic key = new PemReaderreader).ReadObject);
var rsaDecrypt = new Pkcs1Encodingnew RsaEngine));
if key is AsymmetricKeyParameter)
{
key = AsymmetricKeyParameter)key;
}
else if key is AsymmetricCipherKeyPair)
{
key = AsymmetricCipherKeyPair)key).Private;
}
rsaDecrypt.Initfalse, key); //这里加密是true;解密是false
byte[] entData = Convert.FromBase64Stringdecryptstring);
entData = rsaDecrypt.ProcessBlockentData, 0, entData.Length);
return Encoding.UTF8.GetStringentData);
}
}/// <summary>
/// 加密
/// </summary>
/// <param name="publicKey">公钥</param>
/// <param name="encryptstring">待加密的字符串</param>
/// <returns>加密后的Base64</returns>
public static string Encryptstring publicKey, string encryptstring)
{
using TextReader reader = new StringReaderpublicKey))
{
AsymmetricKeyParameter key = new PemReaderreader).ReadObject) as AsymmetricKeyParameter;
Pkcs1Encoding pkcs1 = new Pkcs1Encodingnew RsaEngine));
pkcs1.Inittrue, key);//加密是true;解密是false;
byte[] entData = Encoding.UTF8.GetBytesencryptstring);
entData = pkcs1.ProcessBlockentData, 0, entData.Length);
return Convert.ToBase64StringentData);
}
}
}
}
如果想私钥加密,公钥解密可以引用类库:“BouncyCastle.Crypto”,参考地址如下:
https://www.cnblogs.com/dj258/p/6049786.html
前端
前端引用jsencrypt.js
/*
* RSA算法加密
* key:公钥
* encryptstring:待加密信息
*/
function RSAEncryptionkey, encryptstring) {
//rsa加密随机密钥
var rsa = new JSEncrypt);
//设置后端接口传回的公钥(无需对公钥字符串做任何处理)
rsa.setPublicKeykey);
//注意:RSA加解密有大小限制(最多117 bytes)
var rsaEncrypted = rsa.encryptencryptstring);
//已加密的字符串(Base64)
return rsaEncrypted;
}
PEM格式存在换行,因此建议把公钥放在隐藏域中:
<input id="encryption" name="encryption" type="hidden" value="@ViewData["publicKey"]">