如何通过IKVM将.NET Core与Java实现无缝对接体验?
摘要:前言 与第三方对接最麻烦的是语言不同,因语言不同内置实现相关标准加密算法还是略微有所差异,对接单点登录场景再寻常不过,由于时间紧迫且对接方使用Java,所以留给我对接开发和联调的时间本就不多,于是乎,在熬夜发版后,继而开始提前研究对接方所提
前言
与第三方对接最麻烦的是语言不同,因语言不同内置实现相关标准加密算法还是略微有所差异,对接单点登录场景再寻常不过,由于时间紧迫且对接方使用Java,所以留给我对接开发和联调的时间本就不多,于是乎,在熬夜发版后,继而开始提前研究对接方所提供的加密方式大致处理
方案一(C#实现)
数据对接加密算法采用RSA SHA1 1024位、同时呢,在Java中对于1024或其他位数,对密文有长度限制,所以利用了分段加密,密文长度为117,解密长度为128,如此通用处理方式,网上肯定是可以搜索到的,截取加密部分片段,如下:
public static byte[] encryptByPublicKey(byte[] data, String publicKey) throws Exception {
byte[] keyBytes = Base64.getDecoder().decode(publicKey);
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key publicK = keyFactory.generatePublic(x509KeySpec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, publicK);
int inputLen = data.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
while (inputLen - offSet > 0) {
if (inputLen - offSet > 117) {
cache = cipher.doFinal(data, offSet, 117);
} else {
cache = cipher.doFinal(data, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * 117;
}
byte[] encryptedData = out.toByteArray();
out.close();
return encryptedData;
}
当然对于密钥在从证书中导出来肯定是二进制的,那么各个对接方最后转换为字符串方式有多种,比如base64、再比如转换为16进制等等,大同小异,这里就不展开了
了解完Java完整代码实现,我们需要对相关业务参数利用对接方所提供的公钥进行加密从而形成签名,以此请求时,将我们本地生成的公钥传递过去,在响应后进行验签,然后通过私钥解密
好了,讲到这里,我们假设已经本地生成证书,然后我们导出RSA公钥和私钥,伪代码如下:
var certificate = new X509Certificate2("pfx_path", "password", X509KeyStorageFlags.Exportable);
var rsa = certificate.GetRSAPrivateKey();
var privateKey = rsa.ExportRSAPrivateKey();
var publicKey = rsa.ExportRSAPublicKey();
那么我们如何利用对接方公钥进行加密呢?接下来在.NET Core中实现就需要解决上述加密算法出现的两个问题
1. Java中可以通过RSA密钥(公钥或私钥)字符串转换为RSA密钥类,.NET Core提供了?
2. 获取到RSA密钥类,调用对应实例doFinal方法进行分段加密,那么是否可以通过.NET Core中的RSA加密方法,也分段加
