zoukankan      html  css  js  c++  java
  • 网Js RSA加密,后端(Asp.Net)解码(非对称加解密)

    前言

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

    1、取得公钥与私钥方法

    JSEncrypt Download 

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

    这样就得到一公钥和私钥

    另一种生成公钥与私钥的方法如下:引用 https://blog.csdn.net/qq_39081974/article/details/81059022

    ======================================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-Win64in;复制到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

    加解密算法:

    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("
    ", "").Replace("
    ", "");
                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;

  • 相关阅读:
    3-为什么很多 对 1e9+7(100000007)取模
    6-关于#include<bits/stdc++.h>
    7-n!的位数(斯特灵公式)
    5-math中函数汇总
    6-找数的倍数
    6-Collision-hdu5114(小球碰撞)
    5-青蛙的约会(ex_gcd)
    4-圆数Round Numbers(数位dp)
    4-memset函数总结
    一种Furture模式处理请求中循环独立的任务的方法
  • 原文地址:https://www.cnblogs.com/xiaoruilin/p/11747701.html
Copyright © 2011-2022 走看看