C# RSACryptoServiceProvider(.NET';s RSA)能否使用SHA256而不是SHA1进行加密(非签名)?

C# RSACryptoServiceProvider(.NET';s RSA)能否使用SHA256而不是SHA1进行加密(非签名)?,c#,cryptography,rsa,C#,Cryptography,Rsa,加密时,RSACryptServiceProvider(或.NET提供的任何其他RSA加密程序)是否可以使用SHA256而不是SHA1 SHA1似乎是硬编码的,无法更改。例如,RSACryptServiceProvider.SignatureAlgorithm被硬编码为返回“http://www.w3.org/2000/09/xmldsig#rsa-sha1” 如果无法让RSACryptoServiceProvider使用SHA256,有哪些替代方案 更新 下面的代码工作得很好,但我想将OAE

加密时,RSACryptServiceProvider(或.NET提供的任何其他RSA加密程序)是否可以使用SHA256而不是SHA1

SHA1似乎是硬编码的,无法更改。例如,RSACryptServiceProvider.SignatureAlgorithm被硬编码为返回“http://www.w3.org/2000/09/xmldsig#rsa-sha1”

如果无法让RSACryptoServiceProvider使用SHA256,有哪些替代方案


更新

下面的代码工作得很好,但我想将OAEPwithsha1和mgf1填充更改为OAEPwithsha256和mgf1填充。C端需要什么才能使用SHA256而不是SHA1进行加密

加密在C#中完成,使用:

解密在Java中通过以下方式完成:

Cipher cipher = Cipher.getInstance("RSA/NONE/OAEPWithSHA1AndMGF1Padding", "BC");
cipher.init(Cipher.DECRYPT_MODE, keyPair.getPrivate());
byte[] cipherText = ...;
byte[] plainText = cipher.doFinal(cipherText);

从任何Windows Server 2003和更高版本操作系统上的.NET 3.5 SP1开始,RSACryptServiceProvider都支持RSA-SHA256进行签名,但不支持加密

从博客帖子:


不过,你应该阅读原始帖子,因为有一些问题需要注意。

如果没有办法让RSACryptServiceProvider处理OAEP-with-SHA-256(其他人的答案似乎说明了这一点),那么你仍然可以自己实现该操作。我们讨论的是加密部分,它只使用公钥。公钥是公共的,这意味着您可以导出它(实际上,在您的代码中,您已经有了模数和指数作为字节数组),而且由于这里没有密钥,所以通过一个粗心的实现不会出现关于机密数据泄漏的问题

实施OAEP包括以下内容:

  • 遵循第7.1节。这会将要加密的数据转换为长度与RSA模数相同的字节序列。您需要一个SHA-256实现(
    System.Security.Cryptography.SHA256Managed
    )和一个加密质量源alea(
    System.Security.Cryptography.RandomNumberGenerator

  • 将结果序列解码为大整数,执行模幂运算(模n,RSA模),并将结果编码为与模长度相同的另一个字节序列。编码规则是大端、无符号位和固定大小(如果这是一个1024位RSA密钥,意味着在这个问题被问答之后,21023

    被更新为1.7。为了将来的引用,你可以考虑它,它支持很多密码算法,散列,有弹力城堡的签名可以用于java。点击链接,寻找‘1.7的发行说明’和‘当前特征列表:’。”/p> RSACryptServiceProvider确实使用基于SHA2的签名,但您必须投入一些精力

    当您使用证书获取RSACryptoServiceProvider时,底层CryptoAPI提供程序确实很重要。默认情况下,当您使用“makecert”创建证书时,它是“RSA-FULL”,仅支持SHA1哈希签名。您需要支持SHA2的新“RSA-AES”证书

    因此,您可以使用一个附加选项创建证书:-sp“Microsoft增强的RSA和AES加密提供程序”(或等效的-sy 24),然后您的代码将如下所示(在.NET 4.0中):

    如果您无法更改证书的颁发方式,则有一个半LigiMate解决方案,它基于以下事实:默认情况下,RSACryptServiceProvider是在支持SHA2的情况下创建的。因此,以下代码也可以工作,但有点难看:(此代码的作用是创建一个新的RSACryptServiceProvider,并从证书中获取的密钥导入密钥)


    这里的所有其他答案都是关于使用SHA256进行签名,而不是加密。我将实际回答这个问题

    任何SHA-2或更高的算法都是用于散列的,不一定是加密/解密的,但这并不意味着你不能使用这些算法生成密钥,然后对它们进行加密/解密。从技术上讲,我要提醒那些反对这个答案的人,这不是“用SHA256加密”,但它确实允许RSA使用使用该算法生成的散列密钥。让您的特定组织决定这是否足以符合NIST/FIPS,如果这是您的原因,就像我在研究此问题时一样

    加密(使用RSA或其他非对称加密算法)只需要一个公钥(用于加密)和一个私钥(用于解密)。一旦使用该散列创建密钥,就可以对它们进行加密/解密

    我将把我做的一些研究拼凑起来,展示几种方法,你可以使用使用SHA-256散列创建的密钥,然后对其进行加密/解密。你可以通过创建证书或让RSACryptServiceContainer给你一个证书来生成SHA-256密钥

    证书方法

    在命令行中使用以下行创建证书:

    makecert -r -pe -n "CN=MyCertificate" -a sha256 -b 09/01/2016 -sky exchange C:\Temp\MyCertificate.cer -sv C:\Temp\MyCertificate.pvk
    pvk2pfx.exe -pvk C:\Temp\MyCertificate.pvk -pi "MyP@ssw0rd" -spc C:\Temp\MyCertificate.cer -pfx C:\Temp\MyCertificate.pfx -po "MyP@ssw0rd"
    
    然后将证书导入本地根权限存储并使用以下代码:

    string input = "test";
    string output = string.Empty;
    
    X509Store store = new X509Store(StoreName.Root, StoreLocation.LocalMachine);
    store.Open(OpenFlags.ReadOnly);
    
    X509Certificate2Collection collection = store.Certificates.Find(X509FindType.FindBySubjectName, "MyCertificate", false);
    
    X509Certificate2 certificate = collection[0];
    
    using (RSACryptoServiceProvider cps = (RSACryptoServiceProvider)certificate.PublicKey.Key)
    {
        byte[] bytesData = Encoding.UTF8.GetBytes(input);
        byte[] bytesEncrypted = cps.Encrypt(bytesData, false);
        output = Convert.ToBase64String(bytesEncrypted);
    }
    
    store.Close();
    
    如果您想使用SHA512,您只需在制作证书时将该参数更改为
    SHA512

    参考

    使用RSACryptServiceProvider生成密钥

    private static string privateKey = String.Empty;
    
    private static void generateKeys()
    {
        int dwLen = 2048;
        RSACryptoServiceProvider csp = new RSACryptoServiceProvider(dwLen);
        privateKey = csp.ToXmlString(true).Replace("><",">\r\n");
    }
    
    public static string Encrypt(string data2Encrypt)
    {
        try
        {
            generateKeys();
            RSAx rsax = new RSAx(privateKey, 2048);
            rsax.RSAxHashAlgorithm = RSAxParameters.RSAxHashAlgorithm.SHA256;
            byte[] CT = rsax.Encrypt(Encoding.UTF8.GetBytes(data2Encrypt), false, true); // first bool is for using private key (false forces to use public), 2nd is for using OAEP
            return Convert.ToBase64String(CT);
        }
        catch (Exception ex) 
        { 
            // handle exception
            MessageBox.Show("Error during encryption: " + ex.Message);
            return String.Empty;
        }
    }
    
    public static string Decrypt(string data2Decrypt)
    {
        try
        {
            RSAx rsax = new RSAx(privateKey, 2048);
            rsax.RSAxHashAlgorithm = RSAxParameters.RSAxHashAlgorithm.SHA256;
            byte[] PT = rsax.Decrypt(Convert.FromBase64String(data2Decrypt), true, true); // first bool is for using private key, 2nd is for using OAEP
            return Encoding.UTF8.GetString(PT);
        }
        catch (Exception ex) 
        { 
            // handle exception
            MessageBox.Show("Error during encryption: " + ex.Message);
            return String.Empty;
        }
    }
    
    // @Date : 15th July 2012
    // @Author : Arpan Jati (arpan4017@yahoo.com; arpan4017@gmail.com)
    // @Library : ArpanTECH.RSAx
    // @CodeProject: http://www.codeproject.com/Articles/421656/RSA-Library-with-Private-Key-Encryption-in-Csharp  
    
    using System;
    using System.Collections.Generic;
    using System.Security.Cryptography;
    using System.Numerics;
    using System.Linq;
    using System.Text;
    using System.IO;
    
    namespace ArpanTECH
    {
        /// <summary>
        /// The main RSAx Class
        /// </summary>
        public class RSAx : IDisposable
        {
            private RSAxParameters rsaParams;
            private RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
    
            /// <summary>
            /// Initialize the RSA class.
            /// </summary>
            /// <param name="rsaParams">Preallocated RSAxParameters containing the required keys.</param>
            public RSAx(RSAxParameters rsaParams)
            {
                this.rsaParams = rsaParams;
                UseCRTForPublicDecryption = true;
            }
    
            /// <summary>
            /// Initialize the RSA class from a XML KeyInfo string.
            /// </summary>
            /// <param name="keyInfo">XML Containing Key Information</param>
           /// <param name="ModulusSize">Length of RSA Modulus in bits.</param>
           public RSAx(String keyInfo, int ModulusSize)
           {
                this.rsaParams = RSAxUtils.GetRSAxParameters(keyInfo, ModulusSize);
                UseCRTForPublicDecryption = true;
            }
    
            /// <summary>
            /// Hash Algorithm to be used for OAEP encoding.
            /// </summary>
            public RSAxParameters.RSAxHashAlgorithm RSAxHashAlgorithm
            {
                set
                {
                    rsaParams.HashAlgorithm = value;
                }
            }
    
            /// <summary>
            /// If True, and if the parameters are available, uses CRT for private key decryption. (Much Faster)
            /// </summary>
            public bool UseCRTForPublicDecryption
            {
                get;  set;
            }
    
            /// <summary>
            /// Releases all the resources.
            /// </summary>
            public void Dispose()
            {
                rsaParams.Dispose();
            }
    
            #region PRIVATE FUNCTIONS
    
            /// <summary>
            /// Low level RSA Process function for use with private key.
            /// Should never be used; Because without padding RSA is vulnerable to attacks.  Use with caution.
            /// </summary>
            /// <param name="PlainText">Data to encrypt. Length must be less than Modulus size in octets.</param>
            /// <param name="usePrivate">True to use Private key, else Public.</param>
            /// <returns>Encrypted Data</returns>
            public byte[] RSAProcess(byte[] PlainText, bool usePrivate)
            {
    
                if (usePrivate && (!rsaParams.Has_PRIVATE_Info))
                {
                    throw new CryptographicException("RSA Process: Incomplete Private Key Info");
                }
    
                if ((usePrivate == false) && (!rsaParams.Has_PUBLIC_Info))
                {
                    throw new CryptographicException("RSA Process: Incomplete Public Key Info");
                }            
    
                BigInteger _E;
                if (usePrivate)
                    _E = rsaParams.D; 
                else
                    _E = rsaParams.E;
    
                BigInteger PT = RSAxUtils.OS2IP(PlainText, false);
                BigInteger M = BigInteger.ModPow(PT, _E, rsaParams.N);
    
                if (M.Sign == -1)
                    return RSAxUtils.I2OSP(M + rsaParams.N, rsaParams.OctetsInModulus, false);            
                else
                    return RSAxUtils.I2OSP(M, rsaParams.OctetsInModulus, false);                   
            }
    
            /// <summary>
            /// Low level RSA Decryption function for use with private key. Uses CRT and is Much faster.
            /// Should never be used; Because without padding RSA is vulnerable to attacks. Use with caution.
            /// </summary>
            /// <param name="Data">Data to encrypt. Length must be less than Modulus size in octets.</param>
            /// <returns>Encrypted Data</returns>
            public byte[] RSADecryptPrivateCRT(byte[] Data)
            {
                if (rsaParams.Has_PRIVATE_Info && rsaParams.HasCRTInfo)
                {
                    BigInteger C = RSAxUtils.OS2IP(Data, false);
    
                    BigInteger M1 = BigInteger.ModPow(C, rsaParams.DP, rsaParams.P);
                    BigInteger M2 = BigInteger.ModPow(C, rsaParams.DQ, rsaParams.Q);
                    BigInteger H = ((M1 - M2) * rsaParams.InverseQ) % rsaParams.P;
                    BigInteger M = (M2 + (rsaParams.Q * H));
    
                    if (M.Sign == -1)
                        return RSAxUtils.I2OSP(M + rsaParams.N, rsaParams.OctetsInModulus, false);
                    else
                        return RSAxUtils.I2OSP(M, rsaParams.OctetsInModulus, false); 
                }
                else
                {
                    throw new CryptographicException("RSA Decrypt CRT: Incomplete Key Info");
                }                             
            }        
    
            private byte[] RSAProcessEncodePKCS(byte[] Message, bool usePrivate)
            {
                if (Message.Length > rsaParams.OctetsInModulus - 11)
                {
                    throw new ArgumentException("Message too long.");
                }
                else
                {
                    // RFC3447 : Page 24. [RSAES-PKCS1-V1_5-ENCRYPT ((n, e), M)]
                    // EM = 0x00 || 0x02 || PS || 0x00 || Msg 
    
                    List<byte> PCKSv15_Msg = new List<byte>();
    
                    PCKSv15_Msg.Add(0x00);
                    PCKSv15_Msg.Add(0x02);
    
                    int PaddingLength = rsaParams.OctetsInModulus - Message.Length - 3;
    
                    byte[] PS = new byte[PaddingLength];
                    rng.GetNonZeroBytes(PS);
    
                    PCKSv15_Msg.AddRange(PS);
                    PCKSv15_Msg.Add(0x00);
    
                    PCKSv15_Msg.AddRange(Message);
    
                    return RSAProcess(PCKSv15_Msg.ToArray() ,  usePrivate);
                }
            }
    
            /// <summary>
            /// Mask Generation Function
            /// </summary>
            /// <param name="Z">Initial pseudorandom Seed.</param>
            /// <param name="l">Length of output required.</param>
            /// <returns></returns>
            private byte[] MGF(byte[] Z, int l)
            {
                if (l > (Math.Pow(2, 32)))
                {
                    throw new ArgumentException("Mask too long.");
                }
                else
                {
                    List<byte> result = new List<byte>();
                    for (int i = 0; i <= l / rsaParams.hLen; i++)
                    {
                        List<byte> data = new List<byte>();
                        data.AddRange(Z);
                        data.AddRange(RSAxUtils.I2OSP(i, 4, false));
                        result.AddRange(rsaParams.ComputeHash(data.ToArray()));
                    }
    
                    if (l <= result.Count)
                    {
                        return result.GetRange(0, l).ToArray();
                    }
                    else
                    {
                        throw new ArgumentException("Invalid Mask Length.");
                    }
                }
            }
    
    
            private byte[] RSAProcessEncodeOAEP(byte[] M, byte[] P, bool usePrivate)
            {
                //                           +----------+---------+-------+
                //                      DB = |  lHash   |    PS   |   M   |
                //                           +----------+---------+-------+
                //                                          |
                //                +----------+              V
                //                |   seed   |--> MGF ---> XOR
                //                +----------+              |
                //                      |                   |
                //             +--+     V                   |
                //             |00|    XOR <----- MGF <-----|
                //             +--+     |                   |
                //               |      |                   |
                //               V      V                   V
                //             +--+----------+----------------------------+
                //       EM =  |00|maskedSeed|          maskedDB          |
                //             +--+----------+----------------------------+
    
                int mLen = M.Length;
                if (mLen > rsaParams.OctetsInModulus - 2 * rsaParams.hLen - 2)
                {
                    throw new ArgumentException("Message too long.");
                }
                else
                {
                    byte[] PS = new byte[rsaParams.OctetsInModulus - mLen - 2 * rsaParams.hLen - 2];
                    //4. pHash = Hash(P),
                    byte[] pHash = rsaParams.ComputeHash(P);
    
                    //5. DB = pHash||PS||01||M.
                    List<byte> _DB = new List<byte>();
                    _DB.AddRange(pHash);
                    _DB.AddRange(PS);
                    _DB.Add(0x01);
                    _DB.AddRange(M);
                    byte[] DB = _DB.ToArray();
    
                    //6. Generate a random octet string seed of length hLen.                
                    byte[] seed = new byte[rsaParams.hLen];
                    rng.GetBytes(seed);
    
                    //7. dbMask = MGF(seed, k - hLen -1).
                    byte[] dbMask = MGF(seed, rsaParams.OctetsInModulus - rsaParams.hLen - 1);
    
                    //8. maskedDB = DB XOR dbMask
                    byte[] maskedDB = RSAxUtils.XOR(DB, dbMask);
    
                    //9. seedMask = MGF(maskedDB, hLen)
                    byte[] seedMask = MGF(maskedDB, rsaParams.hLen);
    
                    //10. maskedSeed = seed XOR seedMask.
                    byte[] maskedSeed = RSAxUtils.XOR(seed, seedMask);
    
                    //11. EM = 0x00 || maskedSeed || maskedDB.
                    List<byte> result = new List<byte>();
                    result.Add(0x00);
                    result.AddRange(maskedSeed);
                    result.AddRange(maskedDB);
    
                    return RSAProcess(result.ToArray(), usePrivate);
                }
            }
    
    
            private byte[] Decrypt(byte[] Message, byte [] Parameters, bool usePrivate, bool fOAEP)
            {
                byte[] EM = new byte[0];
                try
                {
                    if ((usePrivate == true) && (UseCRTForPublicDecryption) && (rsaParams.HasCRTInfo))
                    {
                        EM = RSADecryptPrivateCRT(Message);
                    }
                    else
                    {
                        EM = RSAProcess(Message, usePrivate);
                    }
                }
                catch (CryptographicException ex)
                {
                    throw new CryptographicException("Exception while Decryption: " + ex.Message);
                }
                catch
                {
                    throw new Exception("Exception while Decryption: ");
                }
    
                try
                {
                    if (fOAEP) //DECODE OAEP
                    {
                        if ((EM.Length == rsaParams.OctetsInModulus) && (EM.Length > (2 * rsaParams.hLen + 1)))
                        {
                            byte[] maskedSeed;
                            byte[] maskedDB;
                            byte[] pHash = rsaParams.ComputeHash(Parameters);
                            if (EM[0] == 0) // RFC3447 Format : http://tools.ietf.org/html/rfc3447
                            {
                                maskedSeed = EM.ToList().GetRange(1, rsaParams.hLen).ToArray();
                                maskedDB = EM.ToList().GetRange(1 + rsaParams.hLen, EM.Length - rsaParams.hLen - 1).ToArray();
                                byte[] seedMask = MGF(maskedDB, rsaParams.hLen);
                                byte[] seed = RSAxUtils.XOR(maskedSeed, seedMask);
                                byte[] dbMask = MGF(seed, rsaParams.OctetsInModulus - rsaParams.hLen - 1);
                                byte[] DB = RSAxUtils.XOR(maskedDB, dbMask);
    
                                if (DB.Length >= (rsaParams.hLen + 1))
                                {
                                    byte[] _pHash = DB.ToList().GetRange(0, rsaParams.hLen).ToArray();
                                    List<byte> PS_M = DB.ToList().GetRange(rsaParams.hLen, DB.Length - rsaParams.hLen);
                                    int pos = PS_M.IndexOf(0x01);
                                    if (pos >= 0 && (pos < PS_M.Count))
                                    {
                                        List<byte> _01_M = PS_M.GetRange(pos, PS_M.Count - pos);
                                        byte[] M;
                                        if (_01_M.Count > 1)
                                        {
                                            M = _01_M.GetRange(1, _01_M.Count - 1).ToArray();
                                        }
                                        else
                                        {
                                            M = new byte[0];
                                        }
                                        bool success = true;
                                        for (int i = 0; i < rsaParams.hLen; i++)
                                        {
                                             if (_pHash[i] != pHash[i])
                                            {
                                                success = false;
                                                break;
                                            }
                                        }
    
                                        if (success)
                                        {
                                            return M;
                                        }
                                        else
                                        {
                                            M = new byte[rsaParams.OctetsInModulus]; //Hash Match Failure.
                                            throw new CryptographicException("OAEP Decode Error");
                                        }
                                    }
                                    else
                                    {// #3: Invalid Encoded Message Length.
                                        throw new CryptographicException("OAEP Decode Error");
                                    }
                                }
                                else
                                {// #2: Invalid Encoded Message Length.
                                    throw new CryptographicException("OAEP Decode Error");
                                }
                            }
                            else // Standard : ftp://ftp.rsasecurity.com/pub/rsalabs/rsa_algorithm/rsa-oaep_spec.pdf
                            {//OAEP : THIS STADNARD IS NOT IMPLEMENTED
                                throw new CryptographicException("OAEP Decode Error");
                            }
                        }
                        else
                        {// #1: Invalid Encoded Message Length.
                            throw new CryptographicException("OAEP Decode Error");
                        }
                    }
                    else // DECODE PKCS v1.5
                    {
                        if (EM.Length >= 11)
                        {
                            if ((EM[0] == 0x00) && (EM[1] == 0x02))
                            {
                                int startIndex = 2;
                                List<byte> PS = new List<byte>();
                                for (int i = startIndex; i < EM.Length; i++)
                                {
                                    if (EM[i] != 0)
                                    {
                                        PS.Add(EM[i]);
                                    }
                                    else
                                    {
                                        break;
                                    }
                                }
    
                                if (PS.Count >= 8)
                                {
                                    int DecodedDataIndex = startIndex + PS.Count + 1;
                                    if (DecodedDataIndex < (EM.Length - 1))
                                    {
                                        List<byte> DATA = new List<byte>();
                                        for (int i = DecodedDataIndex; i < EM.Length; i++)
                                        {
                                            DATA.Add(EM[i]);
                                        }
                                        return DATA.ToArray();
                                    }
                                    else
                                    {
                                        return new byte[0];
                                        //throw new CryptographicException("PKCS v1.5 Decode Error #4: No Data");
                                    }
                                }
                                else
                                {// #3: Invalid Key / Invalid Random Data Length
                                    throw new CryptographicException("PKCS v1.5 Decode Error");
                                }
                            }
                            else
                            {// #2: Invalid Key / Invalid Identifiers
                                throw new CryptographicException("PKCS v1.5 Decode Error");
                            }
                        }
                        else
                        {// #1: Invalid Key / PKCS Encoding
                            throw new CryptographicException("PKCS v1.5 Decode Error");
                        }
    
                    }
                }
                catch (CryptographicException ex)
                {
                    throw new CryptographicException("Exception while decoding: " + ex.Message);
                }
                catch
                {
                    throw new CryptographicException("Exception while decoding");
                }
    
    
            }
    
            #endregion
    
            #region PUBLIC FUNCTIONS
    
            /// <summary>
            /// Encrypts the given message with RSA, performs OAEP Encoding.
            /// </summary>
            /// <param name="Message">Message to Encrypt. Maximum message length is (ModulusLengthInOctets - 2 * HashLengthInOctets - 2)</param>
            /// <param name="OAEP_Params">Optional OAEP parameters. Normally Empty. But, must match the parameters while decryption.</param>
            /// <param name="usePrivate">True to use Private key for encryption. False to use Public key.</param>
            /// <returns>Encrypted message.</returns>
            public byte[] Encrypt(byte[] Message, byte[] OAEP_Params, bool usePrivate)
            {
                return RSAProcessEncodeOAEP(Message, OAEP_Params, usePrivate);
            }
    
            /// <summary>
            /// Encrypts the given message with RSA.
            /// </summary>
            /// <param name="Message">Message to Encrypt. Maximum message length is For OAEP [ModulusLengthInOctets - (2 * HashLengthInOctets) - 2] and for PKCS [ModulusLengthInOctets - 11]</param>
            /// <param name="usePrivate">True to use Private key for encryption. False to use Public key.</param>
            /// <param name="fOAEP">True to use OAEP encoding (Recommended), False to use PKCS v1.5 Padding.</param>
            /// <returns>Encrypted message.</returns>
            public byte[] Encrypt(byte[] Message, bool usePrivate, bool fOAEP)
            {
                if (fOAEP)
                {
                    return RSAProcessEncodeOAEP(Message, new byte[0], usePrivate);
                }
                else
                {
                    return RSAProcessEncodePKCS(Message, usePrivate);
                }
            }
    
            /// <summary>
            /// Encrypts the given message using RSA Public Key.
            /// </summary>
            /// <param name="Message">Message to Encrypt. Maximum message length is For OAEP [ModulusLengthInOctets - (2 * HashLengthInOctets) - 2] and for PKCS [ModulusLengthInOctets - 11]</param>
            /// <param name="fOAEP">True to use OAEP encoding (Recommended), False to use PKCS v1.5 Padding.</param>
            /// <returns>Encrypted message.</returns>
            public byte[] Encrypt(byte[] Message,  bool fOAEP)
            {
                if (fOAEP)
                {
                    return RSAProcessEncodeOAEP(Message, new byte[0], false);
                }
                else
                {
                    return RSAProcessEncodePKCS(Message, false);
                }
            }
    
            /// <summary>
            /// Decrypts the given RSA encrypted message.
            /// </summary>
            /// <param name="Message">The encrypted message.</param>
            /// <param name="usePrivate">True to use Private key for decryption. False to use Public key.</param>
            /// <param name="fOAEP">True to use OAEP.</param>
            /// <returns>Encrypted byte array.</returns>
            public byte[] Decrypt(byte[] Message, bool usePrivate, bool fOAEP)
            {
                return Decrypt(Message, new byte[0], usePrivate, fOAEP);
            }
    
            /// <summary>
            /// Decrypts the given RSA encrypted message.
            /// </summary>
            /// <param name="Message">The encrypted message.</param>
            /// <param name="OAEP_Params">Parameters to the OAEP algorithm (Must match the parameter while Encryption).</param>
            /// <param name="usePrivate">True to use Private key for decryption. False to use Public key.</param>
            /// <returns>Decrypted byte array.</returns>
            public byte[] Decrypt(byte[] Message, byte[] OAEP_Params, bool usePrivate)
            {
                return Decrypt(Message, OAEP_Params, usePrivate, true);
            }
    
            /// <summary>
            /// Decrypts the given RSA encrypted message using Private key.
            /// </summary>
            /// <param name="Message">The encrypted message.</param>
            /// <param name="fOAEP">True to use OAEP.</param>
            /// <returns>Decrypted byte array.</returns>
            public byte[] Decrypt(byte[] Message,  bool fOAEP)
            {
                return Decrypt(Message, new byte[0], true, fOAEP);
            }
            #endregion
        }
    }
    

    仅供参考:如何更改.p12或.pfx(带私钥的证书)中的CSP。您需要.pfx中私钥的密码才能执行以下步骤

    步骤1:将文件转换为开放格式temp.pem

    openssl pkcs12 -in myCert.p12 -out temp.pem -passin pass:myPassword -passout pass:temppwd
    
    或 openssl pkcs12-in myCert.pfx-out temp.pem-passin pass:myPassword-passout pass:temppwd

    步骤2:创建文件myCert2.pfx,其中包含Windows所需的CSP引用

    openssl pkcs12 -export -in temp.pem -out myCert2.pfx -CSP "Microsoft Enhanced RSA and AES Cryptographic Provider" -passin pass:temppwd -passout pass:myPassword
    
    步骤3:删除temp.pem。不再需要它

    del temp.pem
    
    步骤4:验证是否正确完成

    openssl pkcs12 -info -nodes -in myCert2.pfx -passin pass:myPassword
    
    这必须显示
    Microsoft CSP名称:Microsoft
    
    openssl pkcs12 -in myCert.p12 -out temp.pem -passin pass:myPassword -passout pass:temppwd
    
    openssl pkcs12 -export -in temp.pem -out myCert2.pfx -CSP "Microsoft Enhanced RSA and AES Cryptographic Provider" -passin pass:temppwd -passout pass:myPassword
    
    del temp.pem
    
    openssl pkcs12 -info -nodes -in myCert2.pfx -passin pass:myPassword