rsa加密跨语言的那点事

最近公司将要开展和银行合作的项目,这中间必然少不了接口通信,和银行之间的接口通信,必然要重视加密、签名等等。于是,开始进行相关准备。

其实通信接口的加密,以前也做过不少,简单的比如接口定义一个算法,对方请求先请求一个接口获取密钥,以后所有的接口通信,都以这个密钥作为依据,避免信息被篡改,复杂点的比如之前文章里写过的openssl,但这些都限制在同一种开发语言中,c#或c++,这次的通信接口加密,就跨语言了,对方使用的是java开发的rsa加解密,我们使用的是c#,本来以为rsa通用加解密算法,不会有什么困难,用个半天就能搞定,结果却花费了我2天的时间,大致说说这中间遇到的问题,避免大家也走同样的弯路。

加解密,首先就是密钥,rsa有公钥和私钥之分,java生成的公钥私钥,转成16进制字符串是这样的格式:

30819f300d06092a864886f70d010101050003818d0030818902818100ab2c94707691da26e34c7d3e99d36faa2d2b622a6b6b5d72dc4930c96a8cd58be17b427758b16a335126e35e10dd670e52abf18f4c60330f7c0a07db08fa8231f7b81e18352af17b244c4f8aadbdd8bb9d4d1f32a30586ad3f09177544c0d644957872cf4d59b06583672452a6fadfbd6041f23ffb9778b40c1d647e8c6802510203010001

而c#的公钥私钥,是xml格式:

<RSAKeyValue><Modulus>AIa66kPFEkboBL+GdMuIxmMJ+8pYq/nymlBGmNNcISIUQnJS5XkB3fXE7UlMlbm01e2WiA1o71B2BDRnCgv8cl9VwZuMeen7EA7ksCDS4KHiWkV5X+tpwGFC+N6U7zjUjJt1ZlG05fMs3s8FqLgUdS0g0FtVIjuRtRcdvYIOSUYR</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>

他们之间怎么转换呢?于是在网上找方法,一个是java代码,一个是c#代码,先试试转换公钥,把java的公钥转成c#公钥格式后,我用c#进行加密,然后用java的私钥解密,成功!心里高兴了一下,以为私钥转换也是这样简单,结果大失所望,转换后的私钥在c#中使用FromXmlString总是提示不正确的数据,上网各种找解决办法,有些方法还说用了一定能解决问题,如果不能解决因为人品不够好,结果,就是解决不了,不知道是谁人品问题了,唉,怎么办呢?带着这个疑问,一天的研究结束了。回家路上忽然想起来,既然java生成的密钥c#无法正常使用,那反过来,用c#生成密钥,转成java格式试试。

第二天,按这个想法试了试,结果java加载私钥时也报错,密钥格式不对,唉,正着来不行,反着来也不行,怎么办?期间使用了如下关键字:

c#:ImportParameters、FromXmlString、getKeyPara、DecodeRSAPrivateKey

java:privatekeyinfoToXMLRSAPriKey、privatekeyinfoToXMLRSAPubKey

算了,先不想了,打场篮球下午继续。

有时候,真的是不能钻牛角尖。。。

篮球打完回来,继续查一些资料,忽然发现一篇文章,关于openssl证书的,openssl可以生成公钥、私钥文件,好,既然java生成的c#不能用,c#生成的java也不能用,那就用第三者openssl生成试试。实践证明,有个第三者插足,确实能使事情有所进展。openssl生成证书后,先用c#加载下试试,结果公钥成功,私钥失败,然后文章中正好也遇到我这个问题,对证书进行格式转换后,java加载成功,c#也加载成功,不错不错。然后试着互相加解密,也ok,openssl帮了大忙了,谢谢那篇文章!主要用到的生成证书语句有:

私钥生成:openssl genrsa -out rsa_private_key.pem 1024

公钥生成:openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem

私钥格式转换(pksc8):openssl pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM –nocrypt

然后通过以下java语句完成密钥格式输出:

byte[] pribyte=(new BASE64Decoder()).decodeBuffer("私钥证书内容");
System.out.println("\n******Java format privatekey:******\n"+byteArr2HexString(pribyte));
byte[] pubbyte=(new BASE64Decoder()).decodeBuffer("公钥证书内容");
System.out.println("\n******Java format publickey:******\n"+byteArr2HexString(pubbyte));
String prikey=privatekeyinfoToXMLRSAPriKey(pribyte);
System.out.println("\n******C# format privatekey:******\n"+prikey);
String pubkey=privatekeyinfoToXMLRSAPubKey(pribyte);
System.out.println("\n******C# format publickey:******\n"+pubkey);

大功告成!

通过这个事情,有个经验教训,要想解决一个问题,有时候不能一个手段走到底,正着不行,反着来试试,或者跳出这个圈子,从第三者身上想想。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值