.Net中RSA私钥加密及其与Java的兼容问题

    在.Net中,RSA加密的一般用法如下:

 

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

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
javascript进行RSA加密并用C#后台接收解码。 /// <summary> /// 产生一组RSA公钥、私钥 /// </summary> /// <returns></returns> public static Dictionary<string, string> CreateRsaKeyPair() { var keyPair = new Dictionary<string, string>(); var rsaProvider = new RSACryptoServiceProvider(1024); RSAParameters parameter = rsaProvider.ExportParameters(true); keyPair.Add("PUBLIC", BytesToHexString(parameter.Exponent) + "," + BytesToHexString(parameter.Modulus)); keyPair.Add("PRIVATE", rsaProvider.ToXmlString(true)); keyPair.Add("PUBLICKEY", rsaProvider.ToXmlString(false)); return keyPair; } /// <summary> /// RSA解密字符串 /// </summary> /// <param name="encryptData">密文</param> /// <param name="privateKey">私钥</param> /// <returns>明文</returns> public static string DecryptRSA(string encryptData, string privateKey) { string decryptData = ""; try { var provider = new RSACryptoServiceProvider(); provider.FromXmlString(privateKey); byte[] result = provider.Decrypt(HexStringToBytes(encryptData), false); ASCIIEncoding enc = new ASCIIEncoding(); decryptData = enc.GetString(result); } catch (Exception e) { throw new Exception("RSA解密出错!", e); } return decryptData; } public static string BytesToHexString(byte[] input) { StringBuilder hexString = new StringBuilder(64); for (int i = 0; i < input.Length; i++) { hexString.Append(String.Format("{0:X2}", input[i])); } return hexString.ToString(); } public static byte[] HexStringToBytes(string hex) { if (hex.Length == 0) { return new byte[] { 0 }; } if (hex.Length % 2 == 1) { hex = "0" + hex; } byte[] result = new byte[hex.Length / 2]; for (int i = 0; i < hex.Length / 2; i++) { result[i] = byte.Parse(hex.Substring(2 * i, 2), System.Globalization.NumberStyles.AllowHexSpecifier); } return result; }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值