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密钥协商算法流程如下:

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

1 回复

更多关于HarmonyOS鸿蒙Next中如何解决DH公钥在服务端协商报参数不兼容的问题的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS鸿蒙Next中,解决DH公钥在服务端协商报参数不兼容的问题,可以按照以下步骤进行:

  1. 检查密钥参数:确保客户端和服务端使用的DH参数(如素数p和生成元g)完全一致。不一致的参数会导致协商失败。

  2. 验证密钥长度:确认客户端和服务端使用的密钥长度相同。不同的密钥长度会导致协商失败。

  3. 检查算法实现:确保客户端和服务端使用的DH算法实现一致。不同的实现可能导致参数不兼容。

  4. 更新SDK版本:确保使用的HarmonyOS SDK版本是最新的,以避免已知的兼容性问题。

  5. 调试日志:启用调试日志,查看详细的错误信息,帮助定位问题。

  6. 使用标准库:确保使用HarmonyOS提供的标准库进行DH密钥协商,避免使用第三方库可能带来的兼容性问题。

  7. 检查网络传输:确保密钥参数在传输过程中没有被篡改或损坏。

通过以上步骤,可以有效解决DH公钥在服务端协商报参数不兼容的问题。

回到顶部