最近在做银联的一个接口,用到RSA签名,悲剧来了,.net用的RSA密钥格式和JAVA用的不一样

.net为XML格式

<RSAKeyValue><Modulus>53KnujHcV0962zoLigW8d4AUb+1TS3LiySGrXhF5FgjUQhLzI6PCM/hyHPhUat6MTcgWK3kAVInughtNOHXrBI92I1nAdwlMwBPh+F+0UGhQDR5LMaBg7tQq7ebyhy8/QRCtxEO+F0QQYYv0t15RIup+F+08HdWSnTroTBwcEpU=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>

JAVA需要PEM文件或DER格式

PEM文件

-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCz4PgoQ/2o5cMmFJgcFHLwEl1V
2olZxAEMb7mWfwH36JvORq/maQEE4kYbF2gQN7lQ0C+km0WK6s6ZdzHlhIm/CoK9
YdFCssoTyzj9BDc1RpCtiF1siz/f9vOmGzYKp3bHYHCoEX21XaOuDuVURLuVCWws
HPBpk841ayGwoz4PWQIDAQAB
-----END PUBLIC KEY-----

x50916进制展开

30819f300d06092a864886f70d010101050003818d0030818902818100c166a9a72c74666ed033492d99fa85dffab5230511a3099cd2103a3c89024bcaa8e53b3811fe1588d4827f0621f806c7598fcb4de4624dac420cbbcb84e265589d9fb636a727c7046bcc83ca3bd15980c0ea64246c286b62f55be382b75901f1ee20875018612c69e30e316179460f00cb6f1d965223738c4e58b0da9da4bc4d0203010001

  

DER16进制展开

30818902818100c166a9a72c74666ed033492d99fa85dffab5230511a3099cd2103a3c89024bcaa8e53b3811fe1588d4827f0621f806c7598fcb4de4624dac420cbbcb84e265589d9fb636a727c7046bcc83ca3bd15980c0ea64246c286b62f55be382b75901f1ee20875018612c69e30e316179460f00cb6f1d965223738c4e58b0da9da4bc4d0203010001

问题来了,它们之间是它喵的啥关系

x509与DER

/**
* x509格式公钥转换为Der格式
*
* @param x509PublicKey x509格式公钥字符串
* @return Der格式公钥字符串
*/
public static String getRsaPublicKeyDerFromX509(String x509PublicKey) {
try {
ASN1InputStream aIn = new ASN1InputStream(hexString2ByteArr(x509PublicKey));
SubjectPublicKeyInfo info = SubjectPublicKeyInfo.getInstance(aIn.readObject());
RSAPublicKeyStructure struct = RSAPublicKeyStructure.getInstance(info.getPublicKey());
if (aIn != null)
aIn.close();
return byteArr2HexString(struct.getDERObject().getEncoded());
} catch (IOException e) {
return null;
}
}

x509与PEM

对于公钥,x509=Convert.FromBase64String(PEM中间内容)

私钥就不知道怎么算的

因此JAVA使用格式都是可以用x509进行转换的,剩下的就是如何将.NET的和JAVA的相互转换

格式转换要用到一个开源加密库Bouncy Castle Crypto APIs,官网地址: http://www.bouncycastle.org/csharp/

x509与.NET相互转换

/// <summary>
/// RSA私钥格式转换,java->.net
/// </summary>
/// <param name="privateKeyInfoData">java生成的RSA私钥</param>
/// <returns></returns>
public static string RSAPrivateKeyJava2DotNet(byte[] privateKeyInfoData)
{
RsaPrivateCrtKeyParameters privateKeyParam = (RsaPrivateCrtKeyParameters)PrivateKeyFactory.CreateKey(privateKeyInfoData); return string.Format("<RSAKeyValue><Modulus>{0}</Modulus><Exponent>{1}</Exponent><P>{2}</P><Q>{3}</Q><DP>{4}</DP><DQ>{5}</DQ><InverseQ>{6}</InverseQ><D>{7}</D></RSAKeyValue>",
Convert.ToBase64String(privateKeyParam.Modulus.ToByteArrayUnsigned()),
Convert.ToBase64String(privateKeyParam.PublicExponent.ToByteArrayUnsigned()),
Convert.ToBase64String(privateKeyParam.P.ToByteArrayUnsigned()),
Convert.ToBase64String(privateKeyParam.Q.ToByteArrayUnsigned()),
Convert.ToBase64String(privateKeyParam.DP.ToByteArrayUnsigned()),
Convert.ToBase64String(privateKeyParam.DQ.ToByteArrayUnsigned()),
Convert.ToBase64String(privateKeyParam.QInv.ToByteArrayUnsigned()),
Convert.ToBase64String(privateKeyParam.Exponent.ToByteArrayUnsigned()));
} /// <summary>
/// RSA私钥格式转换,.net->java
/// </summary>
/// <param name="privateKey">.net生成的私钥</param>
/// <returns></returns>
public static byte[] RSAPrivateKeyDotNet2Java(string privateKey)
{
XmlDocument doc = new XmlDocument();
doc.LoadXml(privateKey);
BigInteger m = new BigInteger(, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Modulus")[].InnerText));
BigInteger exp = new BigInteger(, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Exponent")[].InnerText));
BigInteger d = new BigInteger(, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("D")[].InnerText));
BigInteger p = new BigInteger(, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("P")[].InnerText));
BigInteger q = new BigInteger(, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Q")[].InnerText));
BigInteger dp = new BigInteger(, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("DP")[].InnerText));
BigInteger dq = new BigInteger(, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("DQ")[].InnerText));
BigInteger qinv = new BigInteger(, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("InverseQ")[].InnerText)); RsaPrivateCrtKeyParameters privateKeyParam = new RsaPrivateCrtKeyParameters(m, exp, d, p, q, dp, dq, qinv); PrivateKeyInfo privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(privateKeyParam);
byte[] serializedPrivateBytes = privateKeyInfo.ToAsn1Object().GetEncoded();
return serializedPrivateBytes;
//return Convert.ToBase64String(serializedPrivateBytes);
} /// <summary>
/// RSA公钥格式转换,java->.net
/// </summary>
/// <param name="keyInfoData">java生成的公钥</param>
/// <returns></returns>
public static string RSAPublicKeyJava2DotNet(byte[] keyInfoData)
{
RsaKeyParameters publicKeyParam = (RsaKeyParameters)PublicKeyFactory.CreateKey(keyInfoData);
return string.Format("<RSAKeyValue><Modulus>{0}</Modulus><Exponent>{1}</Exponent></RSAKeyValue>",
Convert.ToBase64String(publicKeyParam.Modulus.ToByteArrayUnsigned()),
Convert.ToBase64String(publicKeyParam.Exponent.ToByteArrayUnsigned()));
} /// <summary>
/// RSA公钥格式转换,.net->java
/// </summary>
/// <param name="publicKey">.net生成的公钥</param>
/// <returns></returns>
public static byte[] RSAPublicKeyDotNet2Java(string publicKey)
{
XmlDocument doc = new XmlDocument();
doc.LoadXml(publicKey);
BigInteger m = new BigInteger(, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Modulus")[].InnerText));
BigInteger p = new BigInteger(, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Exponent")[].InnerText));
RsaKeyParameters pub = new RsaKeyParameters(false, m, p); SubjectPublicKeyInfo publicKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(pub);
byte[] serializedPublicBytes = publicKeyInfo.ToAsn1Object().GetDerEncoded();
return serializedPublicBytes;
//return Convert.ToBase64String(serializedPublicBytes);
}

PEM与.NET相互转换

 public static void Xml2PemPrivate(string xml,string saveFile)
{
var rsa = new RSACryptoServiceProvider();
rsa.FromXmlString(xml);
var p = rsa.ExportParameters(true);
var key = new RsaPrivateCrtKeyParameters(
new BigInteger(, p.Modulus), new BigInteger(, p.Exponent), new BigInteger(, p.D),
new BigInteger(, p.P), new BigInteger(, p.Q), new BigInteger(, p.DP), new BigInteger(, p.DQ),
new BigInteger(, p.InverseQ));
using (var sw = new StreamWriter(saveFile))
{
var pemWriter = new Org.BouncyCastle.OpenSsl.PemWriter(sw);
pemWriter.WriteObject(key);
}
}
public static string Pem2XmlPrivate(string pemFile)
{
AsymmetricCipherKeyPair keyPair;
using (var sr = new StreamReader(pemFile))
{
var pemReader = new Org.BouncyCastle.OpenSsl.PemReader(sr);
keyPair = (AsymmetricCipherKeyPair)pemReader.ReadObject();
}
var key = (RsaPrivateCrtKeyParameters)keyPair.Private;
var p = new RSAParameters
{
Modulus = key.Modulus.ToByteArrayUnsigned(),
Exponent = key.PublicExponent.ToByteArrayUnsigned(),
D = key.Exponent.ToByteArrayUnsigned(),
P = key.P.ToByteArrayUnsigned(),
Q = key.Q.ToByteArrayUnsigned(),
DP = key.DP.ToByteArrayUnsigned(),
DQ = key.DQ.ToByteArrayUnsigned(),
InverseQ = key.QInv.ToByteArrayUnsigned(),
};
var rsa = new RSACryptoServiceProvider();
rsa.ImportParameters(p);
return rsa.ToXmlString(true);
} public static string Xml2PemPublic(string xml, string saveFile)
{
var rsa = new RSACryptoServiceProvider();
rsa.FromXmlString(xml);
var p = rsa.ExportParameters(false);
RsaKeyParameters key = new RsaKeyParameters(false, new BigInteger(, p.Modulus), new BigInteger(, p.Exponent));
using (var sw = new StreamWriter(saveFile))
{
var pemWriter = new Org.BouncyCastle.OpenSsl.PemWriter(sw);
pemWriter.WriteObject(key);
}
return System.IO.File.ReadAllText(saveFile);
} public static string Pem2XmlPublic(string pemFileConent)
{
pemFileConent = pemFileConent.Replace("-----BEGIN PUBLIC KEY-----", "").Replace("-----END PUBLIC KEY-----", "").Replace("\n", "").Replace("\r", "");
var data = Convert.FromBase64String(pemFileConent);
return RSAPublicKeyJava2DotNet(data);
}

RSA密钥,JAVA与.NET之间转换的更多相关文章

  1. RSA密钥——JAVA与C#的区别和联系

    PS:好久没写博了,最近在考虑以后的事情,而且手上杂事也比较多,终于得空来写两篇.   首先感谢:http://www.codeproject.com/Articles/25487/Cryptogra ...

  2. Java数值类型之间转换

    Java之间的数值转换如图所示,实心箭头代表无数据丢失,虚线箭头代表可能丢失 例如:123456789是一个大的整数,包含的位数比float类型能够表达的位数多,但这个数转换为float类型时,将会得 ...

  3. Java基本数据类型之间转换

    一.自动类型转换 转换的过程自动发生规则:小——>大byte->short->int->long->float->double char类型识别为int,可以转成i ...

  4. Java中几种常用数据类型之间转换的方法

    Java中几种常用的数据类型之间转换方法: 1. short-->int 转换 exp: short shortvar=0; int intvar=0; shortvar= (short) in ...

  5. JAVA基本数据类型及其转换

    Java语言是一种强类型语言.这意味着每个变量都必须有一个声明好的类型.Java语言提供了八种基本类型.六种数字类型(四个整数型,两个浮点型),一种字符类型,还有一种布尔型.Java另外还提供大数字对 ...

  6. .NET与JAVA RSA密钥格式转换

    一.该篇内容用于记录.net和Java之间,RSA公密钥的转换 using Org.BouncyCastle.Asn1.Pkcs; using Org.BouncyCastle.Asn1.X509; ...

  7. RSA密钥之C#格式与Java格式转换

    前言 最近由于项目需求,服务端由c#编写,客户端由java编写.通信数据使用RSA非对称加密.但是java和c#生成的密钥格式是不一样的,所以需要转换格式才可以正常使用.网上搜到使用java进行格式转 ...

  8. JAVA,NET RSA密钥格式转换

    JAVA和NET RSA密钥格式相互转换(公钥,私钥) 做了一个小项目遇到java和.net非对称加密问题,java的公钥和私钥就直接是一个字符串的形式展示的,但是.net是以xml简单包裹形式展示的 ...

  9. .NET Core RSA密钥的xml、pkcs1、pkcs8格式转换和JavaScript、Java等语言进行对接

    众所周知在.NET下的RSA类所生成的密钥为Xml格式,而其他语言比如java一般使用pkcs8格式的密钥,JavaScript一般使用pkcs1格式.我们在开发过程中很可能遇到需要与其他语言开发的a ...

随机推荐

  1. CentOS安装配置redis

    安装前准备,安装gcc 先用 gcc -v命令检测本机是否安装gcc,如果没有则用下面命令安装: yum install cpp yum install binutils yum install gl ...

  2. PHP 之 CURL 模拟登陆并获取数据

    1.CURL模拟登陆的流程和步骤 2.tempnam 创建一个临时文件 3.使用CURL模拟登陆到PHP100论坛 <?php $cookie_file = tempnam('./temp',' ...

  3. 利用闭包实现多次ajax请求只执行最后一次

    点一个按钮,则向服务器请求资源,不作处理时,多次点击后会有很多个请求在等待.我们知道一般我们用ajax是异步请求,那么我们快速重复点击一个按钮得到的结果其实我们并不知道是哪次点击的结果可能是第一次可能 ...

  4. java并发编程(十六)happen-before规则

    转载请注明出处:http://blog.csdn.net/ns_code/article/details/17348313 happen-before规则介绍 Java语言中有一个"先行发生 ...

  5. 一鼓作气 博客--第二篇 note2

    1.循环正常结束是指没有中间截断,即没有执行break; for i in range(10) print(i) else: print("循环正常结束") 2.嵌套循环 for ...

  6. Android WiFi密码(查看工具)

    纯手机端AIDE编写,现在分享出源码 & apk文件. 注: 使用此工具需要root权限. apk文件 : http://yunpan.cn/cHPLZ8zH5BQBV (提取码:9cd2) ...

  7. 登陆数据库,界面一直保持正在登陆的状态,oracle使用界面无法登陆

    原因:关机时没有关闭oracle窗口. 导致在登陆数据库的时候,使用oracle的这个界面登陆时,界面一直保持''正在登陆''的状态,一旦点击就会卡住,使界面变得无法响应. 然后使用sqlplus仍然 ...

  8. 如何识别一个字符串是否Json格式

    前言: 距离上一篇文章,又过去一个多月了,近些时间,工作依旧很忙碌,除了管理方面的事,代码方面主要折腾三个事: 1:开发框架(一整套基于配置型的开发体系框架) 2:CYQ.Data 数据层框架(持续的 ...

  9. 微软StockTrader应用程序

    这是一个采用 .NET Enterprise Application Server 技术的端到端示例应用程序.应用程序代码可以从 这里 下载. 代码中演示了WCF服务和移动开发,包括用Xamarin ...

  10. Hadoop学习笔记—3.Hadoop RPC机制的使用

    一.RPC基础概念 1.1 RPC的基础概念 RPC,即Remote Procdure Call,中文名:远程过程调用: (1)它允许一台计算机程序远程调用另外一台计算机的子程序,而不用去关心底层的网 ...