各位乡亲父老,欢迎大家来捧场!江湖卖艺,生活不易!技艺交流(投稿、打广告、链接交换),请搓这里

  .NET RSA解密、签名、验签

2019/11/21 19:00:50管理员 2376
- N +
来吧,直接上代码!!!
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;

namespace API.Tools
{
        /// <summary>
        /// 类名:RSAFromPkcs8
        /// 功能:RSA解密、签名、验签
        /// 详细:该类对Java生成的密钥进行解密和签名以及验签专用类,不需要修改
        /// 版本:2.0
        /// 修改日期:2011-05-10
        /// 说明:
        /// 以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。
        /// 该代码仅供学习和研究支付宝接口使用,只是提供一个参考。
        /// </summary>
        public sealed class Signatory
        {
                /// <summary>
                /// 签名(C#解释证书导出的,会出现“数据不正确”的错误)
                /// </summary>
                /// <param name="privateKey">私钥</param>
                /// <param name="content">需要签名的内容</param>
                /// <param name="encode">编码格式</param>
                /// <returns></returns>
                public static string sign(string privateKey, string content, Encoding encode)
                {
                        byte[] Data = encode.GetBytes(content);
                        RSACryptoServiceProvider rsa = DecodePemPrivateKey(privateKey);
                        MD5CryptoServiceProvider m5 = new MD5CryptoServiceProvider();

                        byte[] signData = rsa.SignData(Data, m5);
                        return Convert.ToBase64String(signData);
                }
/// <summary>
                /// 验证签名
                /// </summary>
                /// <param name="publicKey">公钥</param>
                /// <param name="content">需要验证的内容</param>
                /// <param name="signedString">签名结果</param>
                /// <param name="encode">编码格式</param>
                /// <returns></returns>
                public static bool verify(string publicKey, string content, string signedString, Encoding encode)
                {
                        bool result = false;
                        byte[] Data = encode.GetBytes(content);
                        byte[] data = Convert.FromBase64String(signedString);
                        RSAParameters paraPub = ConvertFromPublicKey(publicKey);
                        RSACryptoServiceProvider rsaPub = new RSACryptoServiceProvider();
                        rsaPub.ImportParameters(paraPub);

                        MD5CryptoServiceProvider m5 = new MD5CryptoServiceProvider();
                        result = rsaPub.VerifyData(Data, m5, data);
                        return result;
                }

                /// <summary>
                /// 解析java生成的pem文件私钥
                /// </summary>
                /// <param name="pemstr"></param>
                /// <returns></returns>
                private static RSACryptoServiceProvider DecodePemPrivateKey(String pemstr)
                {
                        byte[] pkcs8privatekey;
                        pkcs8privatekey = Convert.FromBase64String(pemstr);
                        if (pkcs8privatekey != null)
                        {

                                RSACryptoServiceProvider rsa = DecodePrivateKeyInfo(pkcs8privatekey);
                                return rsa;
                        }
                        else
                                return null;
                }

                private static RSACryptoServiceProvider DecodePrivateKeyInfo(byte[] pkcs8)
                {

                        byte[] SeqOID = { 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00 };
                        byte[] seq = new byte[15];

                        MemoryStream mem = new MemoryStream(pkcs8);
                        int lenstream = (int)mem.Length;
                        BinaryReader binr = new BinaryReader(mem);        //wrap Memory Stream with BinaryReader for easy reading
                        byte bt = 0;
                        ushort twobytes = 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;


                                bt = binr.ReadByte();
                                if (bt != 0x02)
                                        return null;

                                twobytes = binr.ReadUInt16();

                                if (twobytes != 0x0001)
                                        return null;

                                seq = binr.ReadBytes(15);                //read the Sequence OID
                                if (!CompareBytearrays(seq, SeqOID))        //make sure Sequence for OID is correct
                                        return null;

                                bt = binr.ReadByte();
                                if (bt != 0x04)        //expect an Octet string
                                        return null;

                                bt = binr.ReadByte();                //read next byte, or next 2 bytes is    0x81 or 0x82; otherwise bt is the byte count
                                if (bt == 0x81)
                                        binr.ReadByte();
                                else
                                        if (bt == 0x82)
                                                binr.ReadUInt16();
                                //------ at this stage, the remaining sequence should be the RSA private key

                                byte[] rsaprivkey = binr.ReadBytes((int)(lenstream - mem.Position));
                                RSACryptoServiceProvider rsacsp = DecodeRSAPrivateKey(rsaprivkey);
                                return rsacsp;
                        }

                        catch (Exception)
                        {
                                return null;
                        }

                        finally { binr.Close(); }

                }

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

                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 -----
                                RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
                                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 (Exception)
                        {
                                return null;
                        }
                        finally { binr.Close(); }
                }

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

                private static RSAParameters ConvertFromPublicKey(string pemFileConent)
                {

                        byte[] keyData = Convert.FromBase64String(pemFileConent);
                        if (keyData.Length < 162)
                        {
                                throw new ArgumentException("pem file content is incorrect.");
                        }
                        byte[] pemModulus = new byte[128];
                        byte[] pemPublicExponent = new byte[3];
                        Array.Copy(keyData, 29, pemModulus, 0, 128);
                        Array.Copy(keyData, 159, pemPublicExponent, 0, 3);
                        RSAParameters para = new RSAParameters();
                        para.Modulus = pemModulus;
                        para.Exponent = pemPublicExponent;
                        return para;
                }
        }
}

.net里可以直接使用证书进行RSA签名:

/// <summary>
                /// 签名,直接使用证书签名
                /// </summary>
                /// <param name="filePath"></param>
                /// <param name="password"></param>
                /// <param name="content"></param>
                /// <param name="encode"></param>
                /// <returns></returns>
                public static string sign(string filePath,string password, string content, Encoding encode)
                {
                        byte[] Data = encode.GetBytes(content);

                        X509Certificate2 myX509 = new X509Certificate2(filePath, password, X509KeyStorageFlags.Exportable);
                        var rsa = (RSACryptoServiceProvider)myX509.PrivateKey;
                        MD5CryptoServiceProvider m5 = new MD5CryptoServiceProvider();

                        byte[] signData = rsa.SignData(Data, m5);
                        return Convert.ToBase64String(signData);
                }
0人赞 分享 二维码 赏一个
选择分享方式
移步手机端
文章手机二维码

1、打开你手机的二维码扫描APP
2、扫描左则的二维码
3、点击扫描获得的网址
4、可以在手机端阅读此文章
选择打赏方式
微信赞助

打赏