• C#.NET Rsa私钥加密公钥解密


    在C#中,RSA私钥只能签名,不能加密,如果要加密,要借助BouncyCastle库。

    nuget 中引用 Portable.BouncyCastle。

    工具类:

    RsaEncryptUtil

    using Org.BouncyCastle.Crypto;
    using Org.BouncyCastle.Crypto.Parameters;
    using Org.BouncyCastle.Security;
    using System;
    using System.Security.Cryptography;
    using System.Text;
    
    namespace CommonUtils
    {
        public static class RsaEncryptUtil
        {
            /// <summary>
            /// 私钥加密 .Net平台默认是使用公钥进行加密,私钥进行解密。私钥加密需要自己实现或者使用第三方dll
            /// </summary>
            /// <param name="data"></param>
            /// <param name="key">私钥,格式:PKCS8</param>
            /// <returns></returns>
            public static byte[] encryptByPrivateKey(String data, String key)
            {
                String priKey = key.Trim();
                String xmlPrivateKey = RSAPrivateKeyJava2DotNet(priKey);
                //加载私钥  
                RSACryptoServiceProvider privateRsa = new RSACryptoServiceProvider();
                privateRsa.FromXmlString(xmlPrivateKey);
                //转换密钥  
                AsymmetricCipherKeyPair keyPair = DotNetUtilities.GetKeyPair(privateRsa);
                IBufferedCipher c = CipherUtilities.GetCipher("RSA/ECB/PKCS1Padding");// 参数与Java中加密解密的参数一致       
                c.Init(true, keyPair.Private); //第一个参数为true表示加密,为false表示解密;第二个参数表示密钥 
                byte[] DataToEncrypt = Encoding.UTF8.GetBytes(data);
                byte[] outBytes = c.DoFinal(DataToEncrypt);//加密  
                return outBytes;
    
            }
    
            /// <summary>
            /// 私钥加密
            /// </summary>
            /// <param name="data">明文</param>
            /// <param name="key">私钥</param>
            /// <param name="keyFormat">私钥格式:PKCS1,PKCS8</param>
            /// <returns></returns>
            public static byte[] encryptByPrivateKey(String data, String key,string keyFormat)
            {
                String priKey = key.Trim();
                 
                //加载私钥  
                RSACryptoServiceProvider privateRsa = RsaUtil.LoadPrivateKey(key,keyFormat);
                 
                //转换密钥  
                AsymmetricCipherKeyPair keyPair = DotNetUtilities.GetKeyPair(privateRsa);
                IBufferedCipher c = CipherUtilities.GetCipher("RSA/ECB/PKCS1Padding");// 参数与Java中加密解密的参数一致       
                c.Init(true, keyPair.Private); //第一个参数为true表示加密,为false表示解密;第二个参数表示密钥 
                byte[] DataToEncrypt = Encoding.UTF8.GetBytes(data);
                byte[] outBytes = c.DoFinal(DataToEncrypt);//加密  
                return outBytes;
    
            }
    
            /// <summary>
            /// RSA私钥格式转换,java->.net
            /// </summary>
            /// <param name="privateKey"></param>
            /// <returns></returns>
            private static string RSAPrivateKeyJava2DotNet(string privateKey)
            {
                RsaPrivateCrtKeyParameters privateKeyParam = (RsaPrivateCrtKeyParameters)PrivateKeyFactory.CreateKey(Convert.FromBase64String(privateKey));
    
                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()));
            }
    
            /// <summary>
            /// 用公钥解密
            /// </summary>
            /// <param name="data"></param>
            /// <param name="key"></param>
            /// <returns></returns>
            public static byte[] decryptByPublicKey(String data, String key)
            {
                String pubKey = key.Trim();
                String xmlPublicKey = RSAPublicKeyJava2DotNet(pubKey);
    
                RSACryptoServiceProvider publicRsa = new RSACryptoServiceProvider();
                publicRsa.FromXmlString(xmlPublicKey);
    
                AsymmetricKeyParameter keyPair = DotNetUtilities.GetRsaPublicKey(publicRsa);
                //转换密钥  
                // AsymmetricCipherKeyPair keyPair = DotNetUtilities.GetRsaKeyPair(publicRsa);
                IBufferedCipher c = CipherUtilities.GetCipher("RSA/ECB/PKCS1Padding");// 参数与Java中加密解密的参数一致       
                c.Init(false, keyPair); //第一个参数为true表示加密,为false表示解密;第二个参数表示密钥 
                byte[] DataToEncrypt = Convert.FromBase64String(data);
                byte[] outBytes = c.DoFinal(DataToEncrypt);//解密  
                return outBytes;
            }
    
            /// <summary>
            /// RSA公钥格式转换,java->.net
            /// </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()));
            }
    
    
        }
    }

    RsaUtil

    using Org.BouncyCastle.Crypto.Parameters;
    using Org.BouncyCastle.Security;
    using System;
    using System.IO;
    using System.Security.Cryptography;
    using System.Security.Cryptography.X509Certificates;
    
    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("\r", "").Replace("\n", "").Trim();
                    privateKeyPemPkcs1 = privateKeyPemPkcs1.Replace("-----BEGIN PRIVATE KEY-----", "").Replace("-----END PRIVATE KEY-----", "").Replace("\r", "").Replace("\n", "").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("\r", "").Replace("\n", "").Trim();
                    privateKeyPemPkcs8 = privateKeyPemPkcs8.Replace("-----BEGIN PRIVATE KEY-----", "").Replace("-----END PRIVATE KEY-----", "").Replace("\r", "").Replace("\n", "").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("\r", "").Replace("\n", "").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("\r", "").Replace("\n", "").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()));
            }
    
    
        }
    }

    使用:

    这个方法只能加密 私钥长度/8 -11 个字符,分段加密的代码要自己处理了。

    私钥加密:

    private void btnPrivateKeyEncrypt_Click(object sender, EventArgs e)
            {
                try
                {
                    //byte[] rst = RsaEncryptUtil.encryptByPrivateKey(txtMingWen.Text, txtPrivateKey.Text);
                    byte[] rst = RsaEncryptUtil.encryptByPrivateKey(txtMingWen.Text, txtPrivateKey.Text,cbxPrivateKeyFormat.Text);
    
                    //加密后一般转Base64String ,Base64FormattingOptions.InsertLineBreaks.
                    string base64str = Convert.ToBase64String(rst, Base64FormattingOptions.InsertLineBreaks);
    
                    txtJiaMiHou.Text = base64str;
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }

    公钥解密:

    private void btnPubKeyDecrypt_Click(object sender, EventArgs e)
            {
                try
                {
                    byte[] rst = RsaEncryptUtil.decryptByPublicKey(txtJiaMiHou.Text, txtPubKey.Text);
                     
                    string strRst = Encoding.UTF8.GetString(rst);
                    txtJieMiHou.Text = strRst;
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }

    -

  • 相关阅读:
    [网络流24题] 最长k可重区间集问题 (费用流)
    [网络流24题] 方格取数问题/骑士共存问题 (最大流->最大权闭合图)
    [网络流24题] 太空飞行计划问题 (最大流->最大权闭合图)
    [网络流24题] 最小路径覆盖问题 (最大流/匈牙利 二分图匹配)
    [网络流24题] 试题库问题 (最大流)
    [网络流24题] 运输问题 (费用流)
    luogu P4364 [九省联考2018]IIIDX
    loj 6031「雅礼集训 2017 Day1」字符串
    CF702F T-Shirts
    uoj #46[清华集训2014]玄学
  • 原文地址:https://www.cnblogs.com/runliuv/p/16300237.html
Copyright © 2020-2023  润新知