使用RSACryptoServiceProvider进行公钥加密

我已经在CodeProject上发表了一篇文章,解释了如何使用RSA提供程序进行加密和解密:

RSA私钥加密

虽然2009年的旧版本是错误的,但新的2012版本(具有System.Numerics.BigInteger支持)似乎更可靠。 这个版本缺少的是一种使用公钥加密并使用私钥 解密的方法。

所以,我自己尝试了,但是当我解密时会得到垃圾。 我不熟悉RSA提供商,所以我在这里很黑暗。 很难找到关于它应该如何工作的更多信息。

有谁看到这有什么问题? 以下是带有PUBLIC密钥的ENcryption:

// Add 4 byte padding to the data, and convert to BigInteger struct BigInteger numData = GetBig( AddPadding( data ) ); RSAParameters rsaParams = rsa.ExportParameters( false ); //BigInteger D = GetBig( rsaParams.D ); //only for private key BigInteger Exponent = GetBig( rsaParams.Exponent ); BigInteger Modulus = GetBig( rsaParams.Modulus ); BigInteger encData = BigInteger.ModPow( numData, Exponent, Modulus ); return encData.ToByteArray(); 

当我这样做时,我是否使用提供商提供的大“D”? 可能不是因为它是没有“D”的公钥。

然后是对应的(使用PRIVATE键进行DEcrypting):

 BigInteger numEncData = new BigInteger( cipherData ); RSAParameters rsaParams = rsa.ExportParameters( true ); BigInteger D = GetBig( rsaParams.D ); //BigInteger Exponent = GetBig( rsaParams.Exponent ); BigInteger Modulus = GetBig( rsaParams.Modulus ); BigInteger decData = BigInteger.ModPow( numEncData, D, Modulus ); byte[] data = decData.ToByteArray(); byte[] result = new byte[ data.Length - 1 ]; Array.Copy( data, result, result.Length ); result = RemovePadding( result ); Array.Reverse( result ); return result; 

我需要“D”或指数吗?

显然,我需要加密来兼顾私人 – 公共 – 私人。 任何帮助深表感谢!

这是一个例子:

  public static void rsaPlayground() { byte[] data = new byte[] { 1, 2, 3, 4, 5 }; RSACryptoServiceProvider csp = new RSACryptoServiceProvider();//make a new csp with a new keypair var pub_key = csp.ExportParameters(false); // export public key var priv_key = csp.ExportParameters(true); // export private key var encData = csp.Encrypt(data, false); // encrypt with PKCS#1_V1.5 Padding var decBytes = MyRSAImpl.plainDecryptPriv(encData, priv_key); //decrypt with own BigInteger based implementation var decData = decBytes.SkipWhile(x => x != 0).Skip(1).ToArray();//strip PKCS#1_V1.5 padding } public class MyRSAImpl { private static byte[] rsaOperation(byte[] data, BigInteger exp, BigInteger mod) { BigInteger bData = new BigInteger( data //our data block .Reverse() //BigInteger has another byte order .Concat(new byte[] { 0 }) // append 0 so we are allways handling positive numbers .ToArray() // constructor wants an array ); return BigInteger.ModPow(bData, exp, mod) // the RSA operation itself .ToByteArray() //make bytes from BigInteger .Reverse() // back to "normal" byte order .ToArray(); // return as byte array /* * * A few words on Padding: * * you will want to strip padding after decryption or apply before encryption * */ } public static byte[] plainEncryptPriv(byte[] data, RSAParameters key) { MyRSAParams myKey = MyRSAParams.fromRSAParameters(key); return rsaOperation(data, myKey.privExponent, myKey.Modulus); } public static byte[] plainEncryptPub(byte[] data, RSAParameters key) { MyRSAParams myKey = MyRSAParams.fromRSAParameters(key); return rsaOperation(data, myKey.pubExponent, myKey.Modulus); } public static byte[] plainDecryptPriv(byte[] data, RSAParameters key) { MyRSAParams myKey = MyRSAParams.fromRSAParameters(key); return rsaOperation(data, myKey.privExponent, myKey.Modulus); } public static byte[] plainDecryptPub(byte[] data, RSAParameters key) { MyRSAParams myKey = MyRSAParams.fromRSAParameters(key); return rsaOperation(data, myKey.pubExponent, myKey.Modulus); } } public class MyRSAParams { public static MyRSAParams fromRSAParameters(RSAParameters key) { var ret = new MyRSAParams(); ret.Modulus = new BigInteger(key.Modulus.Reverse().Concat(new byte[] { 0 }).ToArray()); ret.privExponent = new BigInteger(key.D.Reverse().Concat(new byte[] { 0 }).ToArray()); ret.pubExponent = new BigInteger(key.Exponent.Reverse().Concat(new byte[] { 0 }).ToArray()); return ret; } public BigInteger Modulus; public BigInteger privExponent; public BigInteger pubExponent; } 

以此编码/解码示例为例

  byte[] toEncryptData = Encoding.ASCII.GetBytes("hello world"); //Generate keys RSACryptoServiceProvider rsaGenKeys = new RSACryptoServiceProvider(); string privateXml = rsaGenKeys.ToXmlString(true); string publicXml = rsaGenKeys.ToXmlString(false); //Encode with public key RSACryptoServiceProvider rsaPublic = new RSACryptoServiceProvider(); rsaPublic.FromXmlString(publicXml); byte[] encryptedRSA = rsaPublic.Encrypt(toEncryptData, false); string EncryptedResult = Encoding.Default.GetString(encryptedRSA); //Decode with private key var rsaPrivate = new RSACryptoServiceProvider(); rsaPrivate.FromXmlString(privateXml); byte[] decryptedRSA = rsaPrivate.Decrypt(encryptedRSA, false); string originalResult = Encoding.Default.GetString(decryptedRSA);