HarmonyOS鸿蒙Next中如何解决DH公钥在服务端协商报参数不兼容的问题
HarmonyOS鸿蒙Next中如何解决DH公钥在服务端协商报参数不兼容的问题
【问题现象】
HarmonyOS使用ArkTs生成的DH公钥,在服务端协商失败,报错Incompatible parameters。
class TestDh {
public static void main(String[] args) throws Exception {
// 生成并初始化DH密钥
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("DH");
keyPairGenerator.initialize(512);
/* 服务端公私钥 */
KeyPair keyPair= keyPairGenerator.generateKeyPair();
DHPublicKey publicKey = (DHPublicKey) keyPair.getPublic();
String serverPuk = Base64.getEncoder().encodeToString(publicKey.getEncoded());
System.out.println("serverPuk服务端公钥 = " + serverPuk);
// HarmonyOS公钥
String pukClient = "替换为HarmonyOS的公钥";
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(pukClient));
// 根据DH算法获取KeyFactory
KeyFactory kf = KeyFactory.getInstance("DH");
// 通过KeyFactory创建公钥
PublicKey receivedPublicKey = kf.generatePublic(keySpec);
// 创建KeyAgreement对象
KeyAgreement keyAgreement = KeyAgreement.getInstance("DH");
// 初始化协议,设置我方密钥
DHPrivateKey privateKey = (DHPrivateKey) keyPair.getPrivate();
keyAgreement.init(privateKey);
// 添加对方的公钥
keyAgreement.doPhase((DHPublicKey)receivedPublicKey, true);
// 生成协商密钥
byte[] sharedSecret = keyAgreement.generateSecret();
// 输出协商的密钥
System.out.println("协商密钥: " + sharedSecret);
}
}
【背景知识】
DH密钥协商算法流程如下:
【定位思路】
1. 检查公钥
从DH算法的生成流程看,最关键的核心是密钥对的生成和交换,首先检查公钥的解析是否正确,核心代码:
// 来自服务端的公钥serverPubString
let serverPubString ='替换下xxx';
const serverPubArray: Uint8Array = new util.Base64Helper().decodeSync(serverPubString);
检查方法:查看serverPubArray的值是否成功生成。
2. 检查公钥
检查密钥生成器的配置参数是否正确,即参数要写成“DH_modp1536”。
let keyGen = cryptoFramework.createAsyKeyGenerator('DH_modp1536');
3. 检查密钥协商传参是否传错
公钥和私钥的前后顺序不能错。
keyAgreement.generateSecret(clientPair.priKey, serverPubKey.pubKey)
通过以上步骤分析,发现服务端代码,密钥位数为512,而HarmonyOS侧提高了安全性,要求最低秘钥长度为1536,导致协商失败。
【解决方案】
将服务端代码密钥长度设置为1536后重新协商。
核心代码:
class TestDh{
public static void main(String[] args) throws Exception {
// 生成并初始化DH密钥
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("DH");
// 这里把密钥生成器的初始化位数改为1536即可
keyPairGenerator.initialize(1536);
/*服务端公私钥*/
KeyPair keyPair= keyPairGenerator.generateKeyPair();
DHPublicKey publicKey = (DHPublicKey) keyPair.getPublic();
//....
}
}
协商成功的截图:
【总结】
DH密钥交换算法,务必按照定位思路中的三个步骤,逐个检查是否合法,如果参数不合法,将出现协商失败的情况。这里提供密钥协商的正确代码:
async function dhCreate() {
// 生成客户端公私钥对
let keyGen = cryptoFramework.createAsyKeyGenerator('DH_modp1536');
let clientPair = await keyGen.generateKeyPair();
let clientPub = clientPair.pubKey.getEncoded()
let base64Helper = new util.Base64Helper();
// 传给服务端的公钥: toServerPuk
let toServerPuk = base64Helper.encodeToStringSync(clientPub.data);
// 来自服务端的公钥serverPubString
let serverPubString = '替换下xxx';
const serverPubArray: Uint8Array = new util.Base64Helper().decodeSync(serverPubString);
try {
let serverPubKey = keyGen.convertKeySync({ data: serverPubArray }, null);
let keyAgreement = cryptoFramework.createKeyAgreement('DH_modp1536');
// 使用服务端的公钥和客户端的私钥进行密钥协商
keyAgreement.generateSecret(clientPair.priKey, serverPubKey.pubKey).then((reslove) => {
let strBase = new util.Base64Helper().encodeToStringSync(reslove.data);
console.log("DH 密钥协商结果:" + strBase)
}).catch((err: BusinessError) => {
console.log('DH generateSecret错误,error = ' + err)
});
} catch (err) {
console.log('DH错误,error = ' + err)
}
}
更多关于HarmonyOS鸿蒙Next中如何解决DH公钥在服务端协商报参数不兼容的问题的实战教程也可以访问 https://www.itying.com/category-93-b0.html
更多关于HarmonyOS鸿蒙Next中如何解决DH公钥在服务端协商报参数不兼容的问题的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
在HarmonyOS鸿蒙Next中,解决DH公钥在服务端协商报参数不兼容的问题,可以按照以下步骤进行:
-
检查密钥参数:确保客户端和服务端使用的DH参数(如素数p和生成元g)完全一致。不一致的参数会导致协商失败。
-
验证密钥长度:确认客户端和服务端使用的密钥长度相同。不同的密钥长度会导致协商失败。
-
检查算法实现:确保客户端和服务端使用的DH算法实现一致。不同的实现可能导致参数不兼容。
-
更新SDK版本:确保使用的HarmonyOS SDK版本是最新的,以避免已知的兼容性问题。
-
调试日志:启用调试日志,查看详细的错误信息,帮助定位问题。
-
使用标准库:确保使用HarmonyOS提供的标准库进行DH密钥协商,避免使用第三方库可能带来的兼容性问题。
-
检查网络传输:确保密钥参数在传输过程中没有被篡改或损坏。
通过以上步骤,可以有效解决DH公钥在服务端协商报参数不兼容的问题。