zoukankan      html  css  js  c++  java
  • C#.NET RSA 私钥签名 公钥验证签名

    C#.NET RSA 私钥签名 公钥验证签名 公钥验签

    1.待签名字符串转为byte数组时,一般使用UTF8。

    2.将私钥字符串(PKCS8或PKCS1格式)转为C#.NET的RSACryptoServiceProvider对象。

    3.使用RSACryptoServiceProvider对象的SignData方法算出签名值,结果为byte数组。

    4.签名值是byte数组,不便于传输,一般是转为BASE64字符串来传输。

    5.RSACryptoServiceProvider对象+SHA256算法,对标JAVA的SHA256withRSA。

    6.openssl生成的私钥默认是PKCS1的,示例中是转成了PKCS8格式,在解决方案的“公私钥”文件夹,用记事本打开,填入程序即可。

    7.如果要和其它语言互通,需要协商好:待签名字符串转为byte数组的编码、签名值byte数组转字符串的编码、哈希算法(SHA1WithRSA 还是 SHA256WithRSA)。

    私钥签名:

    private void btnSign_Click(object sender, EventArgs e)
            {
                try
                {
                    if (string.IsNullOrWhiteSpace(txtPrivateKey.Text) || string.IsNullOrWhiteSpace(txtToSignStr.Text))
                    {
                        MessageBox.Show("私钥和字符串不能为空");
                        return;
                    }
    
                    //SHA256withRSA
                    string fnstr = txtToSignStr.Text;//待签名字符串
                    //1。转换私钥字符串为RSACryptoServiceProvider对象
                    RSACryptoServiceProvider rsaP = RsaUtil.LoadPrivateKey(txtPrivateKey.Text, "PKCS8");
                    byte[] data = Encoding.UTF8.GetBytes(fnstr);//待签名字符串转成byte数组,UTF8
                    byte[] byteSign = rsaP.SignData(data, "SHA256");//对应JAVA的RSAwithSHA256
                    string sign = Convert.ToBase64String(byteSign);//签名byte数组转为BASE64字符串
    
                    txtSign.Text = sign;
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }

    公钥验证签名:

    private void button1_Click(object sender, EventArgs e)
            {
                try
                {
                    if (string.IsNullOrWhiteSpace(txtPubKey.Text) || string.IsNullOrWhiteSpace(txtToSignStr.Text) || string.IsNullOrWhiteSpace(txtSign.Text))
                    {
                        MessageBox.Show("公钥,签名字符串,签名 不能为空");
                        return;
                    }
                    byte[] signature = Convert.FromBase64String(txtSign.Text);//签名值转为byte数组
                    //SHA256withRSA
                    string fnstr = txtToSignStr.Text;
                    //1。转换私钥字符串为RSACryptoServiceProvider对象
                    RSACryptoServiceProvider rsaP = RsaUtil.LoadPublicKey(txtPubKey.Text );
                    byte[] data = Encoding.UTF8.GetBytes(fnstr);//待签名字符串转成byte数组,UTF8
                    bool validSign = rsaP.VerifyData(data, "SHA256", signature);//对应JAVA的RSAwithSHA256
    
                    if(validSign)
                        lblValidRst.Text = "验证签名通过:"+DateTime.Now.ToString();
                    else
                        lblValidRst.Text = "验证签名 不通过:" + DateTime.Now.ToString();
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }

    工具类:

    using Org.BouncyCastle.Crypto.Parameters;
    using Org.BouncyCastle.Security;
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Security.Cryptography;
    using System.Security.Cryptography.X509Certificates;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace CommonUtils
    {
        public static class RsaUtil
        {
            #region 加载私钥
    
    
            /// <summary>
            /// 转换私钥字符串为RSACryptoServiceProvider
            /// </summary>
            /// <param name="privateKeyStr">私钥字符串</param>
            /// <param name="keyFormat">PKCS8,PKCS1</param>
            /// <param name="signType">RSA 私钥长度1024 ,RSA2 私钥长度2048</param>
            /// <returns></returns>
            public static RSACryptoServiceProvider LoadPrivateKey(string privateKeyStr, string keyFormat)
            {
                string signType = "RSA";
                if (privateKeyStr.Length > 1024)
                {
                    signType = "RSA2";
                }
                //PKCS8,PKCS1
                if (keyFormat == "PKCS1")
                {
                    return LoadPrivateKeyPKCS1(privateKeyStr, signType);
                }
                else
                {
                    return LoadPrivateKeyPKCS8(privateKeyStr);
                }
            }
    
            /// <summary>
            /// PKCS1 格式私钥转 RSACryptoServiceProvider 对象
            /// </summary>
            /// <param name="strKey">pcsk1 私钥的文本内容</param>
            /// <param name="signType">RSA 私钥长度1024 ,RSA2 私钥长度2048 </param>
            /// <returns></returns>
            public static RSACryptoServiceProvider LoadPrivateKeyPKCS1(string privateKeyPemPkcs1, string signType)
            {
                try
                {
                    privateKeyPemPkcs1 = privateKeyPemPkcs1.Replace("-----BEGIN RSA PRIVATE KEY-----", "").Replace("-----END RSA PRIVATE KEY-----", "").Replace("
    ", "").Replace("
    ", "").Trim();
                    privateKeyPemPkcs1 = privateKeyPemPkcs1.Replace("-----BEGIN PRIVATE KEY-----", "").Replace("-----END PRIVATE KEY-----", "").Replace("
    ", "").Replace("
    ", "").Trim();
    
                    byte[] data = null;
                    //读取带
    
                    data = Convert.FromBase64String(privateKeyPemPkcs1);
    
    
                    RSACryptoServiceProvider rsa = DecodeRSAPrivateKey(data, signType);
                    return rsa;
                }
                catch (Exception ex)
                {
                    throw ex;
                }
                return null;
            }
    
            private static RSACryptoServiceProvider DecodeRSAPrivateKey(byte[] privkey, string signType)
            {
                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;
    
                    int bitLen = 1024;
                    if ("RSA2".Equals(signType))
                    {
                        bitLen = 2048;
                    }
    
                    RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(bitLen, CspParameters);
                    //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 ex)
                {
                    throw ex;
                    // 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;
            }
    
            /// <summary>
            /// PKCS8 文本转RSACryptoServiceProvider 对象
            /// </summary>
            /// <param name="privateKeyPemPkcs8"></param>
            /// <returns></returns>
            public static RSACryptoServiceProvider LoadPrivateKeyPKCS8(string privateKeyPemPkcs8)
            {
    
                try
                {
                    //PKCS8是“BEGIN PRIVATE KEY”
                    privateKeyPemPkcs8 = privateKeyPemPkcs8.Replace("-----BEGIN RSA PRIVATE KEY-----", "").Replace("-----END RSA PRIVATE KEY-----", "").Replace("
    ", "").Replace("
    ", "").Trim();
                    privateKeyPemPkcs8 = privateKeyPemPkcs8.Replace("-----BEGIN PRIVATE KEY-----", "").Replace("-----END PRIVATE KEY-----", "").Replace("
    ", "").Replace("
    ", "").Trim();
    
                    //pkcs8 文本先转为 .NET XML 私钥字符串
                    string privateKeyXml = RSAPrivateKeyJava2DotNet(privateKeyPemPkcs8);
    
                    RSACryptoServiceProvider publicRsa = new RSACryptoServiceProvider();
                    publicRsa.FromXmlString(privateKeyXml);
                    return publicRsa;
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }
    
            /// <summary>
            /// PKCS8 私钥文本 转 .NET XML 私钥文本
            /// </summary>
            /// <param name="privateKeyPemPkcs8"></param>
            /// <returns></returns>
            public static string RSAPrivateKeyJava2DotNet(string privateKeyPemPkcs8)
            {
                RsaPrivateCrtKeyParameters privateKeyParam = (RsaPrivateCrtKeyParameters)PrivateKeyFactory.CreateKey(Convert.FromBase64String(privateKeyPemPkcs8));
                return string.Format("<RSAKeyValue><Modulus>{0}</Modulus><Exponent>{1}</Exponent><P>{2}</P><Q>{3}</Q><DP>{4}</DP><DQ>{5}</DQ><InverseQ>{6}</InverseQ><D>{7}</D></RSAKeyValue>",
                Convert.ToBase64String(privateKeyParam.Modulus.ToByteArrayUnsigned()),
                Convert.ToBase64String(privateKeyParam.PublicExponent.ToByteArrayUnsigned()),
                Convert.ToBase64String(privateKeyParam.P.ToByteArrayUnsigned()),
                Convert.ToBase64String(privateKeyParam.Q.ToByteArrayUnsigned()),
                Convert.ToBase64String(privateKeyParam.DP.ToByteArrayUnsigned()),
                Convert.ToBase64String(privateKeyParam.DQ.ToByteArrayUnsigned()),
                Convert.ToBase64String(privateKeyParam.QInv.ToByteArrayUnsigned()),
                Convert.ToBase64String(privateKeyParam.Exponent.ToByteArrayUnsigned()));
            }
    
            #endregion
    
    
            /// <summary>
            /// 加载公钥证书
            /// </summary>
            /// <param name="publicKeyCert">公钥证书文本内容</param>
            /// <returns></returns>
            public static RSACryptoServiceProvider LoadPublicCert(string publicKeyCert)
            {
    
                publicKeyCert = publicKeyCert.Replace("-----BEGIN CERTIFICATE-----", "").Replace("-----END CERTIFICATE-----", "").Replace("
    ", "").Replace("
    ", "").Trim();
    
                byte[] bytesCerContent = Convert.FromBase64String(publicKeyCert);
                X509Certificate2 x509 = new X509Certificate2(bytesCerContent);
                RSACryptoServiceProvider rsaPub = (RSACryptoServiceProvider)x509.PublicKey.Key;
                return rsaPub;
    
            }
    
    
            /// <summary>
            /// pem 公钥文本 转  .NET RSACryptoServiceProvider。
            /// </summary>
            /// <param name="publicKeyPem"></param>
            /// <returns></returns>
            public static RSACryptoServiceProvider LoadPublicKey(string publicKeyPem)
            {
    
                publicKeyPem = publicKeyPem.Replace("-----BEGIN PUBLIC KEY-----", "").Replace("-----END PUBLIC KEY-----", "").Replace("
    ", "").Replace("
    ", "").Trim();
    
                //pem 公钥文本 转  .NET XML 公钥文本。
                string publicKeyXml = RSAPublicKeyJava2DotNet(publicKeyPem);
    
                RSACryptoServiceProvider publicRsa = new RSACryptoServiceProvider();
                publicRsa.FromXmlString(publicKeyXml);
                return publicRsa;
    
    
            }
    
            /// <summary>
            /// pem 公钥文本 转  .NET XML 公钥文本。
            /// </summary>
            /// <param name="publicKey"></param>
            /// <returns></returns>
            private static string RSAPublicKeyJava2DotNet(string publicKey)
            {
                RsaKeyParameters publicKeyParam = (RsaKeyParameters)PublicKeyFactory.CreateKey(Convert.FromBase64String(publicKey));
                return string.Format("<RSAKeyValue><Modulus>{0}</Modulus><Exponent>{1}</Exponent></RSAKeyValue>",
                    Convert.ToBase64String(publicKeyParam.Modulus.ToByteArrayUnsigned()),
                    Convert.ToBase64String(publicKeyParam.Exponent.ToByteArrayUnsigned()));
            }
    
        }
    }

    -源码:https://gitee.com/runliuv/mypub/tree/master/donetproj

  • 相关阅读:
    我爱java系列之---【微服务间的认证—Feign拦截器】
    我爱java系列之---【设置权限的三种解决方案】
    581. Shortest Unsorted Continuous Subarray
    129. Sum Root to Leaf Numbers
    513. Find Bottom Left Tree Value
    515. Find Largest Value in Each Tree Row
    155. Min Stack max stack Maxpop O(1) 操作
    painting house
    Minimum Adjustment Cost
    k Sum
  • 原文地址:https://www.cnblogs.com/runliuv/p/15071807.html
Copyright © 2011-2022 走看看