.Net中RSA私钥加密及其与Java的兼容问题
2012-10-27 15:38
399 查看
在.Net中,RSA加密的一般用法如下:
上述方法的参数中,key_xml是XML格式的RSA密钥,data是需要加密的数据。但是上述代码实际上只是实现了使用公钥加密。即使所提供的参数key_xml是一个私钥,由于RSA的私钥中是包含公钥的,因此在调用RSACryptoServiceProvider.Encrypt()时也只会使用公钥来进行加密。换言之,在.Net所提供的API中,不包含使用私钥进行加密的功能。
对于RSA来说,其公钥和私钥在一定程度来说其实是等价的,使用公钥加密可以使用私钥解密,使用私钥加密则可以使用公钥解密。虽然大部分的RSA应用模式是使用公钥加密私钥解密,但是在某些特殊的场景中,需要使用私钥加密公钥解密(笔者就遇到了这种需求)。在遇到这种需求时,.Net所提供的RSA实现就无法满足需求,需要自己实现RSA加密算法。
好在RSA的加密算法其实比较简单,就是大整数的幂运算和模运算,使用BigInteger类可以比较简单的实现。当然在某些版本的.Net Framework中不包含BigInteger类的实现,这就需要自己实现这个类,这就相对比较复杂了。不过幸好网上比较容易找到该类的开源实现。
下面的实例代码使用BigInteger类实现同时支持RSA公钥和私钥加密的算法,符合PKCS#1(RFC2313)的定义,并与Java的实现兼容。
byte[] RSAEncrypt(String key_xml, byte[] data) { RSACryptoServiceProvider rcp = new RSACryptoServiceProvider(); rcp.FromXmlString(key_xml); return rcp2.Encrypt(data, false); // false 表示PKCS#1 v1.5 Padding }
上述方法的参数中,key_xml是XML格式的RSA密钥,data是需要加密的数据。但是上述代码实际上只是实现了使用公钥加密。即使所提供的参数key_xml是一个私钥,由于RSA的私钥中是包含公钥的,因此在调用RSACryptoServiceProvider.Encrypt()时也只会使用公钥来进行加密。换言之,在.Net所提供的API中,不包含使用私钥进行加密的功能。
对于RSA来说,其公钥和私钥在一定程度来说其实是等价的,使用公钥加密可以使用私钥解密,使用私钥加密则可以使用公钥解密。虽然大部分的RSA应用模式是使用公钥加密私钥解密,但是在某些特殊的场景中,需要使用私钥加密公钥解密(笔者就遇到了这种需求)。在遇到这种需求时,.Net所提供的RSA实现就无法满足需求,需要自己实现RSA加密算法。
好在RSA的加密算法其实比较简单,就是大整数的幂运算和模运算,使用BigInteger类可以比较简单的实现。当然在某些版本的.Net Framework中不包含BigInteger类的实现,这就需要自己实现这个类,这就相对比较复杂了。不过幸好网上比较容易找到该类的开源实现。
下面的实例代码使用BigInteger类实现同时支持RSA公钥和私钥加密的算法,符合PKCS#1(RFC2313)的定义,并与Java的实现兼容。
byte[] RSAEncrypt(String key_xml, byte[] data) { RSACryptoServiceProvider rcp = new RSACryptoServiceProvider(); rcp.FromXmlString(key_xml); RSAParameters pm = rcp.ExportParameters(!rcp.PublicOnly); BigInteger mod = new BigInteger(pm.Modulus); BigInteger ep = new BigInteger(pm.D != null ? pm.D : pm.Exponent); int k_len = pm.Modulus.Length; int pad_len = k_len - data.Length - 3; byte[] em = new byte[k_len]; Stream stream = new MemoryStream(em); stream.WriteByte(0x00); stream.WriteByte(0x01); // 为了与Java兼容,BlockType设为1 for (int i = 0; i < pad_len; i++) stream.WriteByte(0xff); // 为了与Java兼容,填充字节设为0xff stream.WriteByte(0x00); stream.Write(data, 0, data.Length); BigInteger m = new BigInteger(em); BigInteger c = m.modPow(ep, mod); return c.getBytes(); }
相关文章推荐
- C# RSA加密、解密、加签、验签、支持JAVA格式公钥私钥、PEM格式公钥私钥、.NET格式公钥私钥、一般模式【支持公钥加密,私钥解密】(一)
- Java与.Net环境下RSA加密解密交互不成功的问题解决【续】
- Java与.Net环境下RSA加密解密交互不成功的问题解决
- JAVA生成RSA非对称型加密的公钥和私钥(利用JAVA API)
- java非对称加密RSA的工具类及其源代码
- Java生成RSA非对称型加密的公钥和私钥
- java 实现RSA实现数据的私钥加密以及公钥解密
- Java生成RSA非对称型加密的公钥和私钥
- 基于公私钥文件的RSA非对称加密的Java端实现
- [原创]Java与.NET兼容的RSA密钥持久化方法
- C# 与JAVA 的RSA 加密解密交互,互通,C#使用BouncyCastle来实现私钥加密,公钥解密的方法
- Java生成RSA非对称型加密的公钥和私钥
- java 与 php 做rsa 加密数据通讯问题处理
- Java安全架构____RSA加密配置第三方加密库问题_javax.crypto.BadPaddingException: Decryption error
- Java生成RSA非对称型加密的公钥和私钥
- RSA公钥加密私钥解密--jsp加密,java解密
- JAVA生成RSA非对称型加密的公钥和私钥(利用JAVA API)
- Java生成RSA非对称型加密的公钥和私钥
- RSA加密:Windows Phone 公钥加密,Java私钥解密
- java 非对称加密rsa的工具类及其源代码