使用RSACryptoServiceProvider进行公钥加密

时间:2013-03-29 11:55:40

标签: c# .net cryptography rsa encryption-asymmetric

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

RSA Private Key Encryption

虽然2009年的旧版本有问题,但新的2012版本(支持System.Numerics.BigInteger)似乎更可靠。此版本缺少的是使用 public 键加密并使用私有解密的方法。< / p>

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

有人看到这有什么问题吗? 以下是带有PUBLIC密钥的加密:

// 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”或指数吗?

显然,我需要加密来兼顾私人 - 公共 - 私人。 非常感谢任何帮助!

2 个答案:

答案 0 :(得分:17)

采用此编码/解码示例

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

答案 1 :(得分:10)

这是一个例子:

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