原创文章,转载请注明出处 http://boytnt.blog.51cto.com/966121/1351207。c#
在上一篇文章里,咱们已经成功的解析出了公钥加密相当重要的modulus和publicExponent,胜利在望,心急的同窗确定要开始这么写了:安全
/*********** C#代码 ***********/ //设定RSA参数,用于指定modulus和exponent var parameter = new RSAParameters(); parameter.Modulus = modulusBytes; //modulusBytes是转化后的byte[] parameter.Exponent = exponentBytes; //加密 var rsa = RSACryptoServiceProvider.Create("RSA"); rsa.ImportParameters(parameter); byte[] result = rsa.EncryptValue(Encoding.UTF8.GetBytes("PASSWORD")); //把密文转化为HEX形式 string resultHex = BitConverter.ToString(result).Replace("-", "");
对不起要无情的打击你了,这么作行不通,由于C#的RSA加密不是标准RSA,为了增强安全性,它强制使用了PKCS1填充(或OAEP填充),致使密文在Java端解密失败,由于Java端用的是无填充模式(RSA/ECB/NoPadding)。ide
怎么办? 本身实现标准RSA加密吧。modulus和publicExponent都有了,再加上密码,都转化成大整数,作一个ModPow操做,就获得结果密文了。正好.NetFramework从4.0起在System.Numerics命名空间下直接提供BigInterger类了,上手试试:加密
/*********** C#代码 ***********/ //把3个变量转化为System.Numerics.BigInteger var modulus = new BigInteger(modulusBytes); var exponent = new BigInteger(exponentBytes); var data = new BigInteger(Encoding.UTF8.GetBytes("PASSWORD")); //作ModPow运算获得密文,也是BigInteger var result = BigInteger.ModPow(data, exponent, modulus); //把密文BigInteger对应的byte[]转化为HEX形式 string resultHex = BitConverter.ToString(result.ToByteArray()).Replace("-", "");
OH MY GOD!!! 仍是不行,为何?spa
是字节序在捣乱,咱们上面分析ASN.1结构时获得的全部数据都是大字节序的,而System.Numerics.BigInteger是小字节序的,须要转化以后才能使用。这点很烦人,要转来转去的。code
/*********** C#代码 ***********/ //把3个变量转化为System.Numerics.BigInteger var modulus = new BigInteger(modulusBytes.Reverse().ToArray()); var exponent = new BigInteger(exponentBytes.Reverse().ToArray()); var data = new BigInteger(Encoding.UTF8.GetBytes("PASSWORD").Reverse().ToArray()); //作ModPow运算获得密文,也是BigInteger var result = BigInteger.ModPow(d, e, m); //把密文BigInteger对应的byte[]转化为HEX形式 string resultHex = BitConverter.ToString(result.ToByteArray().Reverse().ToArray()).Replace("-", "");
再试一下,这下终于OK了。blog
问题完美解决了吗? 很遗憾,没有,由于System.Numerics.BigInteger是4.0以上版本才提供的,低于此版本的只好去使用第三方的实现,好比这个:http://www.codeproject.com/Articles/2728/Csharp-BigInteger-Class,但要注意如下2点:get
一、它默认只支持560bit,代码最开头有写:private const int maxLength = 70;string
把maxLength改为256才能支持2048位的RSA运算了。
it
二、它是大字节序的,在使用时不用反转modulus和publicExponent对应的byte[]。
三、咱们获得的modulus是257个字节,须要去掉首字节的0,用剩下的256个字节实例化BigInteger。
好,至此问题算是告一段落了,实测经过。之后想起来什么再继续补充吧。
我没有提供完整解决方案的代码,只给出了部分代码片段,但愿对此问题有兴趣的同窗把重点放在理解过程上,而不是仅仅搬代码。