宝塔服务器面板,一键全能部署及管理,送你10850元礼包,点我领取

前言

非对称加密算法的优缺点就不赘述了,目前使用最广泛的就是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) CreateKeyPair(int strength = 1024)
        {
            RsaKeyPairGenerator r = new RsaKeyPairGenerator();
            r.Init(new KeyGenerationParameters(new SecureRandom(), strength));
            AsymmetricCipherKeyPair keys = r.GenerateKeyPair();

            TextWriter privateTextWriter = new StringWriter();
            PemWriter privatePemWriter = new PemWriter(privateTextWriter);
            privatePemWriter.WriteObject(keys.Private);
            privatePemWriter.Writer.Flush();


            TextWriter publicTextWriter = new StringWriter();
            PemWriter publicPemWriter = new PemWriter(publicTextWriter);
            publicPemWriter.WriteObject(keys.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 Decrypt(string privateKey, string decryptstring)
        {
            using (TextReader reader = new StringReader(privateKey))
            {
                dynamic key = new PemReader(reader).ReadObject();
                var rsaDecrypt = new Pkcs1Encoding(new RsaEngine());
                if (key is AsymmetricKeyParameter)
                {
                    key = (AsymmetricKeyParameter)key;
                }
                else if (key is AsymmetricCipherKeyPair)
                {
                    key = ((AsymmetricCipherKeyPair)key).Private;
                }
                rsaDecrypt.Init(false, key);  //这里加密是true;解密是false  

                byte[] entData = Convert.FromBase64String(decryptstring);
                entData = rsaDecrypt.ProcessBlock(entData, 0, entData.Length);
                return Encoding.UTF8.GetString(entData);
            }
        }/// <summary>

         /// 加密
         /// </summary>
         /// <param name="publicKey">公钥</param>
         /// <param name="encryptstring">待加密的字符串</param>
         /// <returns>加密后的Base64</returns>
        public static string Encrypt(string publicKey, string encryptstring)
        {
            using (TextReader reader = new StringReader(publicKey))
            {
                AsymmetricKeyParameter key = new PemReader(reader).ReadObject() as AsymmetricKeyParameter;
                Pkcs1Encoding pkcs1 = new Pkcs1Encoding(new RsaEngine());
                pkcs1.Init(true, key);//加密是true;解密是false;
                byte[] entData = Encoding.UTF8.GetBytes(encryptstring);
                entData = pkcs1.ProcessBlock(entData, 0, entData.Length);
                return Convert.ToBase64String(entData);
            }
        }
    }
}

如果想私钥加密,公钥解密可以引用类库:“BouncyCastle.Crypto”,参考地址如下:
https://www.cnblogs.com/dj258/p/6049786.html

前端

前端引用jsencrypt.js

/*
 * RSA算法加密
 * key:公钥
 * encryptstring:待加密信息
 */
function RSAEncryption(key, encryptstring) {
            //rsa加密随机密钥
            var rsa = new JSEncrypt();
            //设置后端接口传回的公钥(无需对公钥字符串做任何处理)
            rsa.setPublicKey(key);

            //注意:RSA加解密有大小限制(最多117 bytes)
            var rsaEncrypted = rsa.encrypt(encryptstring);

            //已加密的字符串(Base64)
            return rsaEncrypted;
        }

PEM格式存在换行,因此建议把公钥放在隐藏域中:

<input id="encryption" name="encryption" type="hidden" value="@ViewData["publicKey"]">