• .Net Core RSA加解密,签名


       note: 最近在对接微信支付V3,发现微信支付需要SHA256 with RSA签名,现在的项目是Net Core的,原来的RSA帮助类用不了,折腾了许久,终于把.Net Core版 的RSAHelper搞出来了。

           其中使用了开源项目:The Legion of the Bouncy Castle C# Cryptography APIs

      

    using System;
    using System.IO;
    using System.Security.Cryptography;
    using Org.BouncyCastle.Crypto.Parameters;
    using Org.BouncyCastle.Security;
    using Org.BouncyCastle.Asn1.X509;
    using Org.BouncyCastle.Asn1.Pkcs;
    using Org.BouncyCastle.Pkcs;
    using Org.BouncyCastle.X509;
    using System.Text;
    using System.Security.Cryptography.X509Certificates;
    
    namespace Xu.Helper
    {
        /// <summary>
        /// API 公用操作类:权限校验、参数校验、POST等
        /// </summary>
        public class RSAHelper
        {
    
            private readonly string privateKey;
            private readonly string publicKey;
    
            /// <summary>
            /// 适应于Pkcs12证书
            /// </summary>
            /// <param name="certPath"></param>
            /// <param name="mchIdPwd"></param>
            public RSAHelper(string certPath, string mchIdPwd)
            {
                var pc = new X509Certificate2(certPath, mchIdPwd, X509KeyStorageFlags.Exportable);
                var keyPair = DotNetUtilities.GetKeyPair(pc.PrivateKey);
                var subjectPublicKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(keyPair.Public);
                var privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(keyPair.Private);
                privateKey = Convert.ToBase64String(privateKeyInfo.ParsePrivateKey().GetEncoded());
                publicKey = Convert.ToBase64String(subjectPublicKeyInfo.GetEncoded());
            }
    
            #region RSA解密
    
            /// <summary>
            /// RSA解密
            /// </summary>
            /// <param name="decryptstring"></param>
            /// <param name="str_PrivateKey">证书上的密钥</param>
            /// <param name="encodingtype"></param>
            /// <returns></returns>
            public string RSADecrypt(string decryptstring, string encodingtype = "utf-8")
            {
                // 构造函数中 Org.BouncyCastle  会自动转成Pkcs1的密钥
                RSA rsa = CreateRsaFromPrivateKey(privateKey);
                return RSADecrypt(decryptstring, encodingtype, rsa);
            }
    
            /// <summary>
            /// RSA解密
            /// </summary>
            /// <param name="decryptstring"></param>
            /// <param name="str_PrivateKey">证书上的密钥</param>
            /// <param name="encodingtype"></param>
            /// <returns></returns>
            public static string RSADecrypt(string decryptstring, string str_PrivateKey, string encodingtype = "utf-8")
            {
                //生成对应Pkcs1的密钥
                string privateKey = ConvertPrivateKeyPkcs8ToPcks1(str_PrivateKey);
                RSA rsa = CreateRsaFromPrivateKey(privateKey);
                return RSADecrypt(decryptstring, encodingtype, rsa);
            }
    
            private static string RSADecrypt(string decryptstring, string encodingtype, RSA rsa)
            {
                int keySize = rsa.KeySize / 8;
                byte[] buffer = new byte[keySize];
                byte[] PlainTextBArray = Convert.FromBase64String(decryptstring);
    
                using (MemoryStream input = new MemoryStream(PlainTextBArray))
                using (MemoryStream output = new MemoryStream())
                {
                    while (true)
                    {
                        int readLine = input.Read(buffer, 0, keySize);
                        if (readLine <= 0)
                        {
                            break;
                        }
                        byte[] temp = new byte[readLine];
                        Array.Copy(buffer, 0, temp, 0, readLine);
                        byte[] decrypt = rsa.Decrypt(temp, RSAEncryptionPadding.Pkcs1);
                        output.Write(decrypt, 0, decrypt.Length);
                    }
                    rsa.Dispose();
                    return Encoding.GetEncoding(encodingtype).GetString(output.ToArray());
                }
            }
    
            #endregion
    
            #region RSA公钥加密 
    
            public static string RSAEncrypt(string str_DataToSign, string str_PublicKey, string encodingtype = "utf-8")
            {
                //生成对应Pkcs1的密钥
                string publicKey = ConvertPublicKeyPkcs8ToPcks1(str_PublicKey);
                var rsa = CreateRsaFromPublicKey(str_PublicKey);
    
                return RSAEncrypt(str_DataToSign, encodingtype, rsa);
            }
    
            public  string RSAEncrypt(string str_DataToSign, string encodingtype = "utf-8")
            {
                // 构造函数中 Org.BouncyCastle  会自动转成Pkcs1的公钥
                var rsa = CreateRsaFromPublicKey(publicKey);
                return RSAEncrypt(str_DataToSign, encodingtype, rsa);
            }
    
            private static string RSAEncrypt(string str_DataToSign, string encodingtype, RSA rsa)
            {
                var inputBytes = Encoding.GetEncoding(encodingtype).GetBytes(str_DataToSign);//有含义的字符串转化为字节流                              
                int bufferSize = (rsa.KeySize / 8) - 11;//单块最大长度
                var buffer = new byte[bufferSize];
                using (MemoryStream inputStream = new MemoryStream(inputBytes),
                     outputStream = new MemoryStream())
                {
                    while (true)
                    { //分段加密
                        int readSize = inputStream.Read(buffer, 0, bufferSize);
                        if (readSize <= 0)
                        {
                            break;
                        }
    
                        var temp = new byte[readSize];
                        Array.Copy(buffer, 0, temp, 0, readSize);
                        var encryptedBytes = rsa.Encrypt(temp, RSAEncryptionPadding.Pkcs1);
                        outputStream.Write(encryptedBytes, 0, encryptedBytes.Length);
                        rsa.Dispose();
                    }
                    return Convert.ToBase64String(outputStream.ToArray());//转化为字节流方便传输
                }
            }
    
    
            #region 导入密钥算法
    
    
    
            private static int GetIntegerSize(BinaryReader binr)
            {
                byte bt = 0;
                int count = 0;
                bt = binr.ReadByte();
                if (bt != 0x02)
                    return 0;
                bt = binr.ReadByte();
    
                if (bt == 0x81)
                    count = binr.ReadByte();
                else
                if (bt == 0x82)
                {
                    var highbyte = binr.ReadByte();
                    var 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 static 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;
            }
    
            #endregion
    
            
            #endregion
    
    
            #region 签名和验签
    
            /// <summary>
            /// 私钥签名
            /// </summary>
            /// <param name="data"></param>
            /// <param name="str_PrivateKey"></param>
            /// <returns></returns>
            public static string Sign(string data, string str_PrivateKey)
            {
                //生成对应Pkcs1的密钥   Pkcs12,Pkcs8需先转成kcs1
                string privateKey = ConvertPrivateKeyPkcs8ToPcks1(str_PrivateKey);
                RSA rsa = CreateRsaFromPrivateKey(str_PrivateKey);
    
                byte[] dataBytes = Encoding.UTF8.GetBytes(data);
    
                var signatureBytes = rsa.SignData(dataBytes, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
    
                return Convert.ToBase64String(signatureBytes);
            }
    
            /// <summary>
            /// 私钥签名
            /// </summary>
            /// <param name="data"></param>
            /// <param name="str_PrivateKey"></param>
            /// <returns></returns>
            public string Sign(string data)
            {
                RSA rsa = CreateRsaFromPrivateKey(privateKey);
                byte[] dataBytes = Encoding.UTF8.GetBytes(data);
                var signatureBytes = rsa.SignData(dataBytes, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
                return Convert.ToBase64String(signatureBytes);
            }
    
    
            /// <summary>
            /// 公钥验签
            /// </summary>
            /// <param name="data">原始数据</param>
            /// <param name="sign">签名</param>
            /// <returns></returns>
            public static bool Verify(string data, string sign, string publicKeyString)
            {
                byte[] dataBytes = Encoding.UTF8.GetBytes(data);
                byte[] signBytes = Convert.FromBase64String(sign);
    
                //生成对应Pkcs1的公钥   Pkcs12,Pkcs8需先转成kcs1
                string privateKey = ConvertPublicKeyPkcs8ToPcks1(publicKeyString);
                RSA rsa = CreateRsaFromPublicKey(publicKeyString);
                var verify = rsa.VerifyData(dataBytes, signBytes, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
    
                return verify;
            }
    
            /// <summary>
            /// 公钥验签
            /// </summary>
            /// <param name="data">原始数据</param>
            /// <param name="sign">签名</param>
            /// <returns></returns>
            public bool Verify(string data, string sign)
            {
                byte[] dataBytes = Encoding.UTF8.GetBytes(data);
                byte[] signBytes = Convert.FromBase64String(sign);
                RSA rsa = CreateRsaFromPublicKey(publicKey);
                var verify = rsa.VerifyData(dataBytes, signBytes, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
    
                return verify;
            }
            #endregion
    
    
            #region 生成RSA
    
            /// <summary>
            /// 根据PrivateKey生成RSA (适用于Pkcs1)
            /// </summary>
            /// <param name="privateKey">证书上的密钥</param>
            /// <returns></returns>
            private static RSA CreateRsaFromPrivateKey(string privateKey)
            {
                var privateKeyBits = System.Convert.FromBase64String(privateKey);
                var rsa = RSA.Create();
                var RSAparams = new RSAParameters();
    
                using (var 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;
            }
    
            /// <summary>
            /// 根据PublicKey 创建RSA实例
            /// </summary>
            /// <param name="publicKeyString"></param>
            /// <returns></returns>
            public static RSA CreateRsaFromPublicKey(string publicKeyString)
            {
                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;
    
                using (var mem = new MemoryStream(x509key))
                {
                    using (var binr = new BinaryReader(mem))
                    {
                        byte bt = 0;
                        ushort twobytes = 0;
    
                        twobytes = binr.ReadUInt16();
                        if (twobytes == 0x8130)
                            binr.ReadByte();
                        else if (twobytes == 0x8230)
                            binr.ReadInt16();
                        else
                            return null;
    
                        seq = binr.ReadBytes(15);
                        if (!CompareBytearrays(seq, SeqOID))
                            return null;
    
                        twobytes = binr.ReadUInt16();
                        if (twobytes == 0x8103)
                            binr.ReadByte();
                        else if (twobytes == 0x8203)
                            binr.ReadInt16();
                        else
                            return null;
    
                        bt = binr.ReadByte();
                        if (bt != 0x00)
                            return null;
    
                        twobytes = binr.ReadUInt16();
                        if (twobytes == 0x8130)
                            binr.ReadByte();
                        else if (twobytes == 0x8230)
                            binr.ReadInt16();
                        else
                            return null;
    
                        twobytes = binr.ReadUInt16();
                        byte lowbyte = 0x00;
                        byte highbyte = 0x00;
    
                        if (twobytes == 0x8102)
                            lowbyte = binr.ReadByte();
                        else if (twobytes == 0x8202)
                        {
                            highbyte = binr.ReadByte();
                            lowbyte = binr.ReadByte();
                        }
                        else
                            return null;
                        byte[] modint = { lowbyte, highbyte, 0x00, 0x00 };
                        int modsize = BitConverter.ToInt32(modint, 0);
    
                        int firstbyte = binr.PeekChar();
                        if (firstbyte == 0x00)
                        {
                            binr.ReadByte();
                            modsize -= 1;
                        }
    
                        byte[] modulus = binr.ReadBytes(modsize);
    
                        if (binr.ReadByte() != 0x02)
                            return null;
                        int expbytes = (int)binr.ReadByte();
                        byte[] exponent = binr.ReadBytes(expbytes);
    
                        var rsa = RSA.Create();
                        var rsaKeyInfo = new RSAParameters
                        {
                            Modulus = modulus,
                            Exponent = exponent
                        };
                        rsa.ImportParameters(rsaKeyInfo);
                        return rsa;
                    }
    
                }
            }
    
            #endregion
    
            #region pcks8格式转化为pcks1格式
    
            /// <summary>
            /// 将pcks8格式的RSA公钥转化为pcks1格式
            /// </summary>
            /// <param name="pubicKey">pcks8格式的RSA公钥 base64格式</param>
            /// <returns>pcks1格式的RSA公钥 base64格式</returns>
            public static string ConvertPublicKeyPkcs8ToPcks1(string pubicKey)
            {
                return Convert.ToBase64String(ConvertPublicKeyPkcs8ToPcks1(Convert.FromBase64String(pubicKey)));
            }
            /// <summary>
            /// 将pcks8格式的RSA公钥转化为pcks1格式
            /// </summary>
            /// <param name="pubicKey">pcks8格式的RSA公钥</param>
            /// <returns>pcks1格式的RSA公钥</returns>
            public static byte[] ConvertPublicKeyPkcs8ToPcks1(byte[] pubicKey)
            {
                RsaKeyParameters publicKeyParam = (RsaKeyParameters)PublicKeyFactory.CreateKey(pubicKey);
                SubjectPublicKeyInfo spkInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(publicKeyParam);
                return spkInfo.ParsePublicKey().ToAsn1Object().GetEncoded();
            }
    
            /// <summary>
            /// 将pcks8格式的RSA私钥转化为pcks1格式
            /// </summary>
            /// <param name="privateKey">pcks8格式的RSA私钥 base64格式</param>
            /// <returns>pcks1格式的RSA私钥 base64格式</returns>
            public static string ConvertPrivateKeyPkcs8ToPcks1(string privateKey)
            {
                return Convert.ToBase64String(ConvertPrivateKeyPkcs8ToPcks1(Convert.FromBase64String(privateKey)));
            }
            /// <summary>
            /// 将pcks8格式的RSA私钥转化为pcks1格式
            /// </summary>
            /// <param name="privateKey">pcks8格式的RSA私钥</param>
            /// <returns>pcks1格式的RSA私钥</returns>
            public static byte[] ConvertPrivateKeyPkcs8ToPcks1(byte[] privateKey)
            {
                RsaPrivateCrtKeyParameters privateKeyParam = (RsaPrivateCrtKeyParameters)PrivateKeyFactory.CreateKey(privateKey);
                PrivateKeyInfo pkInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(privateKeyParam);
                return pkInfo.ParsePrivateKey().ToAsn1Object().GetEncoded();
            }
    
            #endregion
    
        }
    }
  • 相关阅读:
    4_url_for的使用
    3_Flask中URL与视图函数的映射
    2_Fiask的配置文件config
    C10K问题渣翻译
    (转载)Linux 套接字编程中的 5 个隐患
    linux2.6.24内核源代码分析(2)——扒一扒网络数据包在链路层的流向路径之一
    linux2.6.24内核源代码分析(1)——扒一扒sk_buff
    andriod手机签到应用服务器设计
    (转)ubuntu安装opengl
    线段树
  • 原文地址:https://www.cnblogs.com/shiding/p/15168088.html
Copyright © 2020-2023  润新知