C#使用私钥进行RSA加密

背景:接口方开发环境是Java,要求我使用私钥对数据进行加密,他使用公钥进行解密。

开发时遇到的问题:

1).Net平台默认是使用公钥进行加密,私钥进行解密。私钥加密需要自己实现或者使用第三方dll。

2)双方平台不一致,出现了我加密的数据对方不能解密,对方加密的数据我不能解密,但是自身是可以正常加密解密。


解决办法:

1)使用第三方dll,此处使用的是C#的BouncyCastle.Crypto进行加密及解密。在官网http://www.bouncycastle.org/csharp/ 下载最新dll。

2)设置Cipher为“RSA/ECB/PKCS1Padding”,与Java平台统一。


这是实现的方法,方法后面是解决过程,有兴趣可以看一看。如果这个代码不能解决你的问题,建议看下后面的解决过程,里面的链接也许对你有帮助。

    /// <summary>用私钥给数据进行RSA加密
    /// 
    /// </summary>
    /// <param name="xmlPrivateKey">私钥</param>
    /// <param name="m_strEncryptString">待加密数据</param>
    /// <returns>加密后的数据(Base64)</returns>
    public static string RSAEncryptByPrivateKey(string xmlPrivateKey, string strEncryptString) 
    {
        //加载私钥
        RSACryptoServiceProvider privateRsa = new RSACryptoServiceProvider();
        privateRsa.FromXmlString(xmlPrivateKey);

        //转换密钥
        AsymmetricCipherKeyPair keyPair = DotNetUtilities.GetKeyPair(privateRsa);

        IBufferedCipher c = CipherUtilities.GetCipher("RSA/ECB/PKCS1Padding");// 参数与Java中加密解密的参数一致     
        //第一个参数为true表示加密,为false表示解密;第二个参数表示密钥
        c.Init(true, keyPair.Private);

        byte[] DataToEncrypt = Encoding.UTF8.GetBytes(strEncryptString);
        byte[] outBytes = c.DoFinal(DataToEncrypt);//加密
        string strBase64 = Convert.ToBase64String(outBytes);
        
        return strBase64;
    }


-------------------------------------解决过程-------------------------------------

1.确认是使用私钥进行加密后,发现.Net没有使用私钥进行加密的方法。搜索后得知需要自己实现。

2.搜索实现方式,但得到的方法里需要两个BigInteger,由于对私钥的xml并不了解,不清楚参数该用什么值。只好放弃这种方式。不过后来查资料找到私钥xml中各节点的含义以及加密时该用哪些节点的值。不过这是后话了。

微软对公钥私钥各节点的解释:RSAParameters 结构 https://msdn.microsoft.com/zh-cn/library/system.security.cryptography.rsaparameters%28v=vs.110%29.aspx

加密解密时该使用什么节点:http://blog.csdn.net/a351945755/article/details/21965533

3.找到一个已经封装好的方法,只需要把密钥和加密数据传进去就可以实现的方法。但是加密出来的结果本身可以解密,但是对方无法解密。对方提供的加密数据使用此方法无法解密。

此处使用的代码:http://www.codeproject.com/Articles/38739/RSA-Private-Key-Encryption

4.在前两步搜索资料的时候,得知BouncyCastle。看到相关介绍,于是使用其提供的dll进行加密解密操作。但是此时网上找到的都是BouncyCastle自动生成密钥进行加密解密而不是读取.Net的密钥进行加密解密。

使用BouncyCastle进行加密解密的代码是:http://blog.csdn.net/popozhu/article/details/5789382

5.查找密钥转换方式,找到以下资料:http://stackoverflow.com/questions/3240222/get-private-key-from-bouncycastle-x509-certificate-c-sharp

使用“CriGoT”或者“majkinetor”提供的代码都可以进行私钥的转换。

6.通过第四步和第五步可以获得完整的加密解密方法。在使用此方法进行私钥加密后对方解密时报错“javax.crypto.BadPaddingException: Blocktype mismatch: 0”,查找资料后得知,也许与Cipher.getInstance("RSA")中的参数有关,需要改为“RSA/ECB/PKCS1Padding”。但对方排查后应当默认就是“RSA/ECB/PKCS1Padding”。最终在 http://www.xuebuyuan.com/301023.html 找到另一种调用的方法可以传入“RSA/ECB/PKCS1Padding”。

至此.Net和Java之间RSA私钥加密公钥解密进行数据交互完成。





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章