最近遇到一个项目需要做单点, 用户方是采用 java rsa 公钥加密传递信息的, 我这边是. net 使用私钥解密. 而对方提供的解密源码是 java 版本的, 并且也没有做过与. net 平台的单点对接.
于是在网上找到了如下版本的 c# 版本 rsa 私钥解密方法
- /// <summary>
- /// RSA 的解密函数
- /// </summary>
- /// <param name="xmlPrivateKey"> 私钥 </param>
- /// <param name="decryptString"> 待解密的字符串 </param>
- /// <returns></returns>
- public string RSADecrypt(string xmlPrivateKey, string decryptString)
- {
- byte[] PlainTextBArray;// 解密前字节流
- byte[] DypherTextBArray;// 解密后字节流
- string Result = "";
- System.Security.Cryptography.RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
- rsa.FromXmlString(xmlPrivateKey);
- PlainTextBArray = Convert.FromBase64String(decryptString);
- DypherTextBArray = rsa.Decrypt(PlainTextBArray, false);
- Result = Encoding.UTF8.GetString(DypherTextBArray);
- return Result;
- }
拿过来之后把私钥和带解密字符串传入, 发现报错, 于是研究发现, c# 的 rsa 解密私钥是 xml 格式的, 而对方提供的是 base64 字符串, 所以需要先把私钥转成 xml 格式,
转换无法在 c# 中进行, 需要打开在 java 下面转换, 可以下个 exclipse 把如下代码复制进去就行.
- package com;
- import java.security.KeyFactory;
- import java.security.PublicKey;
- import java.security.interfaces.RSAPrivateCrtKey;
- import java.security.interfaces.RSAPublicKey;
- import java.security.spec.PKCS8EncodedKeySpec;
- import java.security.spec.X509EncodedKeySpec;
- //import org.castor.util.Base64Decoder;
- //import org.castor.util.Base64Encoder;
- public class test {
- public static void main(String[] args)
- {
- String tes="MIICeQIBADANBgkqhkiG9w0BAQEFAASCAmMwggJfAgEAAoGBAL8z2QlXCL6w7rvY0Gbl8ARtQSXY+pEW5hlUHlmspqHt4k8/SkoF796gDqk4yyOcoWhkZWLPPugK35Mn7V+m5Jyfu8C0gVKOfWOA8A0T4hxV2ThAoMUq7QtB2K6s9AoumrxDfAkMBbsXEHYwfD/hxr/3DQ3lUvSFB6BnhiHEOyzpAgMBAAECgYEAol/9qRjorEjF9XEjSr9rHddKxEGIST8RGeF+BNnCiTHkRziQdlykYIO876jzmsKhsG3STB+EZLsXM3ls9RZefcsPF5mLOCSOCow3DikfCtAy4hntsU9JwpuYE0V4A+Sgfd24fatqbu+JxE2nvpSbAPczDOgBFPNfYBkhMiuZ/iECQQDzUeq7lFcIE4uWhRGveVFjNAGuSsW+q9GOwO7tS5YwuAIQ2M+XgYGRFo8xMC6V/9SfqJtmSU1zk72pMlYufIqHAkEAySqkcKbWuobq5I9KSQISq2qCuGKtj/iUFho4PCD1YxhnQ7gcHA4OpS1dRFjtXJYQPTX9be+mmypsCFIyofE5DwJBAPGZ20wahTh9v9Lbmq3z9n5ce3bGxAcJsHDg3d09eooxi8uSnL5BV5frII+k2f0TI9rMnlE4Y/FpN5+zXaOXAi0CQQCs3Aqfjo23jJWtPv/LSo+2YnjfblPMAgNmFrO532xc8axSgZMN/HpTL28UewHD7GMZ5hnWbPcSIFrir5c4luq7AkEAi90WdnZVPxtSTqkkLYbnh4Ro2WhdwRjkfyBxBZZx8hfaM6MfLPi3A0rw9DPOSB4M/BMchtEh3bXuI7bue2tG+A==";
- byte[] temp=b64decode(tes);
- String ver=getRSAPrivateKeyAsNetFormat(temp);// 转换私钥
- String tes1="MIGfMA0GCSqGSIb4DQEBAQUAA4GNADCBiQKBgQC/M9kJVwi+sO672NBm5fAEbUEl2PqRFuYZVB5ZrKah7eJPP0pKBe/eoA6pOMsjnKFoZGVizz7oCt+TJ+1fpuScn7vAtIFSjn1jgPANE+IcVdk4QKDFKu0LQdiurPQKLpq8Q3wJDAW7FxB2MHw/4ca/9w0N5VL0hQegZ4YhxDss6QIDAQAB";
- byte[] temp1=b64decode(tes1);
- String ver1=getRSAPublicKeyAsNetFormat(temp1);// 转换公钥
- //String temp2= encodePublicKeyToXml(temp1);
- }
- private static String getRSAPrivateKeyAsNetFormat(byte[] encodedPrivkey) {
- try {
- StringBuffer buff = new StringBuffer(1024);
- PKCS8EncodedKeySpec pvkKeySpec = new PKCS8EncodedKeySpec(
- encodedPrivkey);
- KeyFactory keyFactory = KeyFactory.getInstance("RSA");
- RSAPrivateCrtKey pvkKey = (RSAPrivateCrtKey) keyFactory
- .generatePrivate(pvkKeySpec);
- buff.append("<RSAKeyValue>");
- buff.append("<Modulus>"
- + b64encode(removeMSZero(pvkKey.getModulus().toByteArray()))
- + "</Modulus>");
- buff.append("<Exponent>"
- + b64encode(removeMSZero(pvkKey.getPublicExponent()
- .toByteArray())) + "</Exponent>");
- buff.append("<P>"
- + b64encode(removeMSZero(pvkKey.getPrimeP().toByteArray()))
- + "</P>");
- buff.append("<Q>"
- + b64encode(removeMSZero(pvkKey.getPrimeQ().toByteArray()))
- + "</Q>");
- buff.append("<DP>"
- + b64encode(removeMSZero(pvkKey.getPrimeExponentP()
- .toByteArray())) + "</DP>");
- buff.append("<DQ>"
- + b64encode(removeMSZero(pvkKey.getPrimeExponentQ()
- .toByteArray())) + "</DQ>");
- buff.append("<InverseQ>"
- + b64encode(removeMSZero(pvkKey.getCrtCoefficient()
- .toByteArray())) + "</InverseQ>");
- buff.append("<D>"
- + b64encode(removeMSZero(pvkKey.getPrivateExponent()
- .toByteArray())) + "</D>");
- buff.append("</RSAKeyValue>");
- return buff.toString().replaceAll("[ \t\n\r]", "");
- } catch (Exception e) {
- System.err.println(e);
- return null;
- }
- }
- private static String getRSAPublicKeyAsNetFormat(byte[] encodedPrivkey) {
- try {
- StringBuffer buff = new StringBuffer(1024);
- PKCS8EncodedKeySpec pvkKeySpec = new PKCS8EncodedKeySpec(encodedPrivkey);
- KeyFactory keyFactory = KeyFactory.getInstance("RSA");
- RSAPublicKey pukKey=(RSAPublicKey) keyFactory.generatePublic(new X509EncodedKeySpec(encodedPrivkey));
- // RSAPrivateCrtKey pvkKey = (RSAPrivateCrtKey) keyFactory.generatePrivate(pvkKeySpec);
- //PublicKey publicKey =KeyFactory.getInstance("RSA").generatePublic(pvkKeySpec);
- buff.append("<RSAKeyValue>");
- buff.append("<Modulus>"
- + b64encode(removeMSZero(pukKey.getModulus().toByteArray()))
- + "</Modulus>");
- buff.append("<Exponent>"
- + b64encode(removeMSZero(pukKey.getPublicExponent()
- .toByteArray())) + "</Exponent>");
- buff.append("</RSAKeyValue>");
- return buff.toString().replaceAll("[ \t\n\r]", "");
- } catch (Exception e) {
- System.err.println(e);
- return null;
- }
- }
- public static String encodePublicKeyToXml(PublicKey key) {
- if (!RSAPublicKey.class.isInstance(key)) {
- return null;
- }
- RSAPublicKey pubKey = (RSAPublicKey) key;
- StringBuilder sb = new StringBuilder();
- sb.append("<RSAKeyValue>");
- sb.append("<Modulus>")
- .append(Base64.encode(pubKey.getModulus().toByteArray()))
- .append("</Modulus>");
- sb.append("<Exponent>")
- .append(Base64.encode(pubKey.getPublicExponent()
- .toByteArray())).append("</Exponent>");
- sb.append("</RSAKeyValue>");
- return sb.toString();
- }
- private static byte[] removeMSZero(byte[] data) {
- byte[] data1;
- int len = data.length;
- if (data[0] == 0) {
- data1 = new byte[data.length - 1];
- System.arraycopy(data, 1, data1, 0, len - 1);
- } else
- data1 = data;
- return data1;
- }
- private static String b64encode(byte[] data) {
- String b64str = new String(Base64.encode(data));
- return b64str;
- }
- private static byte[] b64decode(String data) {
- byte[] decodeData = Base64.decode(data);
- return decodeData;
- }
- }
参考: http://www.cnblogs.com/hvaning/p/3636288.html
现在拿到 c# 的私钥了, 发现解密还是报错, 又看了下, 发现用户给的加密文本是 16 进制文本, 并不是 base64 文本, 于是写了个 16 进制转字节的方法供调用.
16 进制文本转字节流方法如下
- /// <summary>
- /// 16 进制文本转字节流
- /// </summary>
- /// <param name="src">16 进制文本 </param>
- /// <returns></returns>
- public byte[] hexStr2ByteArr(string src)
- {
- int l = src.Length / 2;//2 个 16 进制文本等于一个字节, 所以字节数组长度是 16 进制文本长度的一半
- String str;
- byte[] ret = new byte[l];
- for (int i = 0; i <l; i++)
- {
- str = src.Substring(i * 2, 2);
- ret[i] = Convert.ToByte(str, 16);
- }
- return ret;
- }
然后下一个坑又出来了, rsa 解密一次只能 128 个字节, 所以又写了个循环的方法, 每次解密 128 个字节数组, 最终再拼接起来, 最终代码如下:
- /// <summary>
- /// RSA 的解密函数
- /// </summary>
- /// <param name="xmlPrivateKey"> 私钥 </param>
- /// <param name="decryptString"> 待解密的字符串 </param>
- /// <returns></returns>
- public string RSADecrypt(string xmlPrivateKey, string decryptString)
- {
- try
- {
- byte[] PlainTextBArray;
- byte[] DypherTextBArray;
- string Result = "";
- System.Security.Cryptography.RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
- rsa.FromXmlString(xmlPrivateKey);
- PlainTextBArray = hexStr2ByteArr(decryptString);
- var outlength = PlainTextBArray.Length;
- var i = 0;
- while (true) {
- if (outlength> 128)
- {
- var aa = new byte[128];
- Array.Copy(PlainTextBArray, i, aa, 0, 128);
- DypherTextBArray = rsa.Decrypt(aa, false);
- Result = Result + Encoding.UTF8.GetString(DypherTextBArray);
- outlength = outlength - 128;
- i = i + 128;
- }
- else {
- var aa = new byte[outlength];
- Array.Copy(PlainTextBArray, i, aa, 0, outlength);
- DypherTextBArray = rsa.Decrypt(aa, false);
- Result = Result + Encoding.UTF8.GetString(DypherTextBArray);
- break;
- }
- }
- return Result;
- }
- catch (Exception ex)
- {
- throw ex;
- }
- }
来源: https://www.cnblogs.com/xiaofridge/p/10278300.html