RSACryptoServiceProvider(.NET的RSA)可以使用SHA256进行加密(不签名)而不是SHA1吗?

加密时,RSACryptoServiceProvider(或.NET提供的任何其他RSA加密器)可以使用SHA256而不是SHA1吗?

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

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


更新

以下代码完美地运行,但我想将OAEPWithSHA1AndMGF1Padding更改为OAEPWithSHA256AndMGF1Padding。 C#端需要什么才能使用SHA256而不是SHA1进行加密?

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

var parameters = new RSAParameters(); parameters.Exponent = new byte[] {0x01, 0x00, 0x01}; parameters.Modulus = new byte[] {0x9d, 0xc1, 0xcc, ...}; rsa.ImportParameters(parameters); var cipherText = rsa.Encrypt(new byte[] { 0, 1, 2, 3 }, true); 

解密是在Java中使用:

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

RSACryptoServiceProvider可以使用基于SHA2的签名,但您必须投入一些精力。

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

因此,您可以使用其他选项创建证书:-sp“Microsoft Enhanced RSA and AES Cryptographic Provider”(或等效的-sy 24),然后您的代码看起来像(在.NET 4.0中):

 var rsa = signerCertificate.PrivateKey as RSACryptoServiceProvider; // byte[] signature = rsa.SignData(data, CryptoConfig.CreateFromName("SHA256")); 

如果您无法更改颁发证书的方式,则会有一个半连续的解决方法,该解决方案基于以下事实:默认情况下,RSACryptoServiceProvider是在支持SHA2的情况下创建的。 所以,下面的代码也可以工作,但它有点丑陋:(这段代码的作用是创建一个新的RSACryptoServiceProvider并从我们从证书中获取的密钥导入密钥)

 var rsa = signerCertificate.PrivateKey as RSACryptoServiceProvider; // Create a new RSACryptoServiceProvider RSACryptoServiceProvider rsaClear = new RSACryptoServiceProvider(); // Export RSA parameters from 'rsa' and import them into 'rsaClear' rsaClear.ImportParameters(rsa.ExportParameters(true)); byte[] signature = rsaClear.SignData(data, CryptoConfig.CreateFromName("SHA256")); 

从任何Windows Server 2003及更高版本操作系统上的.NET 3.5 SP1起,是的,RSACryptoServiceProvider支持RSA-SHA256进行签名 ,但不支持加密。

从博客文章使用RSACryptoServiceProvider获取RSA-SHA256签名 :

 byte[] data = new byte[] { 0, 1, 2, 3, 4, 5 }; using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider()) { byte[] signature = rsa.SignData(data, "SHA256"); if (rsa.VerifyData(data, "SHA256", signature)) { Console.WriteLine("RSA-SHA256 signature verified"); } else { Console.WriteLine("RSA-SHA256 signature failed to verify"); } } 

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

如果没有办法让RSACryptoServiceProvider处理OAEP-with-SHA-256(其他人的回答似乎就是这样说的话),那么你仍然可以自己实现这个操作。 我们谈论的是加密部分,它只使用公钥。 公钥是公共的,这意味着您可以将其导出(实际上,在您的代码中,您已经将模数和指数作为字节数组),并且通过粗心的实现没有关于秘密数据泄漏的问题,因为这里没有密钥。

实施OAEP需要以下内容:

  • 遵循PKCS#1 ,第7.1节。 这将数据转换为加密成与RSA模数长度相同的字节序列。 您将需要一个SHA-256实现( System.Security.Cryptography.SHA256Managed将没问题)和一个加密质量的alea源( System.Security.Cryptography.RandomNumberGenerator )。
  • 将得到的序列解码为大整数,执行模幂运算(模n ,RSA模数),并将结果编码为与模数相同长度的另一个字节序列。 编码规则是big-endian,没有符号位和固定大小(如果这是一个1024位RSA密钥,意味着2 1023 <= n <2 1024 ,那么加密消息将始终具有正好128字节的长度,甚至如果数值适合较小,例如127或126字节)。

.NET 4.0及更高版本提供了System.Numerics.BigInteger ,它具有您需要的代码(方法ModPow() )。 对于以前的版本,您必须使用自定义实现; 有几个躺着,谷歌一如既往地是你的朋友。 这里不需要绝对性能:RSA 加密很快,因为公共指数很短(示例代码中为17位)。

在提出问题并回答之后, Bounty Castle C#更新为1.7。 为了将来你可以考虑它,它增加了对Bouncy Castle为Java提供的许多加密算法,哈希,签名的支持。 点击链接,查找“1.7版发行说明”和“当前function列表:”。

据微软MVP (Rob Teixeira)称,没有。 您可以使用第三方库,例如Security.Cryptography.dll

仅供参考:如何在.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:创建包含Windows所需的CSP引用的文件myCert2.pfx

 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步:validation它是否正确完成

 openssl pkcs12 -info -nodes -in myCert2.pfx -passin pass:myPassword 

这必须显示Microsoft CSP Name: Microsoft Enhanced RSA and AES Cryptographic Provider

使用这样的修改后的证书,您可以使用Kastorskijs答案中的第一个代码。

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

任何SHA-2或更高版本的算法都用于散列,不一定是加密/解密,但这并不意味着您无法使用这些算法生成密钥,然后对它们进行加密/解密。 从技术上讲,我会告诫那些不同意这个答案的人,这不是“使用SHA256加密”,但它确实允许RSA使用使用该算法生成的散列密钥。 让你的特定组织决定是否足以符合NIST / FIPS标准,这应该是你的原因,因为在我研究这个时,它是我的。

加密(使用RSA或其他非对称加密算法)只需要公钥(用于加密)和私钥(用于解密)。 使用该哈希创建密钥后,您可以对它们进行加密/解密。

我将把我做过的一些研究拼凑起来,展示一些路由,你可以使用一个使用SHA-256哈希创建的密钥,然后加密/解密。 您可以通过创建证书或让RSACryptoServiceContainer为您提供一个证书来生成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,则只需在制作证书时将该sha256参数更改为sha512

参考 : https : //social.msdn.microsoft.com/Forums/en-US/69e39ad0-13c2-4b5e-bb1b-972a614813fd/encrypt-with-certificate-sha512?forum=csharpgeneral

使用RSACryptoServiceProvider生成密钥

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

如果要使用SHA512,可以将RSAxHashAlgorithm.SHA256更改为RSAxHashAlgorithm.SHA512

这些方法使用名为RSAx.DLL的DLL,使用https://www.codeproject.com/Articles/421656/RSA-Library-with-Private-Key-Encryption-in-Csharp中的源代码构建,这不是我的(作者:Arpan Jati),但我已经使用过它,并且在CodeProject的开源许可下可供开发者社区使用。 您也可以从该项目中引入3个类,而不是:RSAx.cs,RSAxParameters.cs,RSAxUtils.cs

代码将在30000字符限制上发布此post,因此我将发布RSAx,以便您可以看到正在发生的事情,但所有3个类都是必需的。 您必须更改命名空间并引用System.Numerics程序集。

RSAx.cs

 // @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 { ///  /// The main RSAx Class ///  public class RSAx : IDisposable { private RSAxParameters rsaParams; private RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider(); ///  /// Initialize the RSA class. ///  /// Preallocated RSAxParameters containing the required keys. public RSAx(RSAxParameters rsaParams) { this.rsaParams = rsaParams; UseCRTForPublicDecryption = true; } ///  /// Initialize the RSA class from a XML KeyInfo string. ///  /// XML Containing Key Information /// Length of RSA Modulus in bits. public RSAx(String keyInfo, int ModulusSize) { this.rsaParams = RSAxUtils.GetRSAxParameters(keyInfo, ModulusSize); UseCRTForPublicDecryption = true; } ///  /// Hash Algorithm to be used for OAEP encoding. ///  public RSAxParameters.RSAxHashAlgorithm RSAxHashAlgorithm { set { rsaParams.HashAlgorithm = value; } } ///  /// If True, and if the parameters are available, uses CRT for private key decryption. (Much Faster) ///  public bool UseCRTForPublicDecryption { get; set; } ///  /// Releases all the resources. ///  public void Dispose() { rsaParams.Dispose(); } #region PRIVATE FUNCTIONS ///  /// 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. ///  /// Data to encrypt. Length must be less than Modulus size in octets. /// True to use Private key, else Public. /// Encrypted Data 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); } ///  /// 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. ///  /// Data to encrypt. Length must be less than Modulus size in octets. /// Encrypted Data 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 PCKSv15_Msg = new List(); 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); } } ///  /// Mask Generation Function ///  /// Initial pseudorandom Seed. /// Length of output required. ///  private byte[] MGF(byte[] Z, int l) { if (l > (Math.Pow(2, 32))) { throw new ArgumentException("Mask too long."); } else { List result = new List(); for (int i = 0; i <= l / rsaParams.hLen; i++) { List data = new List(); 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 <-----| // +--+ | | // | | | // VVV // +--+----------+----------------------------+ // 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 _DB = new List(); _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 result = new List(); 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 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 _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 PS = new List(); 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 DATA = new List(); 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 ///  /// Encrypts the given message with RSA, performs OAEP Encoding. ///  /// Message to Encrypt. Maximum message length is (ModulusLengthInOctets - 2 * HashLengthInOctets - 2) /// Optional OAEP parameters. Normally Empty. But, must match the parameters while decryption. /// True to use Private key for encryption. False to use Public key. /// Encrypted message. public byte[] Encrypt(byte[] Message, byte[] OAEP_Params, bool usePrivate) { return RSAProcessEncodeOAEP(Message, OAEP_Params, usePrivate); } ///  /// Encrypts the given message with RSA. ///  /// Message to Encrypt. Maximum message length is For OAEP [ModulusLengthInOctets - (2 * HashLengthInOctets) - 2] and for PKCS [ModulusLengthInOctets - 11] /// True to use Private key for encryption. False to use Public key. /// True to use OAEP encoding (Recommended), False to use PKCS v1.5 Padding. /// Encrypted message. public byte[] Encrypt(byte[] Message, bool usePrivate, bool fOAEP) { if (fOAEP) { return RSAProcessEncodeOAEP(Message, new byte[0], usePrivate); } else { return RSAProcessEncodePKCS(Message, usePrivate); } } ///  /// Encrypts the given message using RSA Public Key. ///  /// Message to Encrypt. Maximum message length is For OAEP [ModulusLengthInOctets - (2 * HashLengthInOctets) - 2] and for PKCS [ModulusLengthInOctets - 11] /// True to use OAEP encoding (Recommended), False to use PKCS v1.5 Padding. /// Encrypted message. public byte[] Encrypt(byte[] Message, bool fOAEP) { if (fOAEP) { return RSAProcessEncodeOAEP(Message, new byte[0], false); } else { return RSAProcessEncodePKCS(Message, false); } } ///  /// Decrypts the given RSA encrypted message. ///  /// The encrypted message. /// True to use Private key for decryption. False to use Public key. /// True to use OAEP. /// Encrypted byte array. public byte[] Decrypt(byte[] Message, bool usePrivate, bool fOAEP) { return Decrypt(Message, new byte[0], usePrivate, fOAEP); } ///  /// Decrypts the given RSA encrypted message. ///  /// The encrypted message. /// Parameters to the OAEP algorithm (Must match the parameter while Encryption). /// True to use Private key for decryption. False to use Public key. /// Decrypted byte array. public byte[] Decrypt(byte[] Message, byte[] OAEP_Params, bool usePrivate) { return Decrypt(Message, OAEP_Params, usePrivate, true); } ///  /// Decrypts the given RSA encrypted message using Private key. ///  /// The encrypted message. /// True to use OAEP. /// Decrypted byte array. public byte[] Decrypt(byte[] Message, bool fOAEP) { return Decrypt(Message, new byte[0], true, fOAEP); } #endregion } }