HarmonyOS鸿蒙Next中使用SM2密钥对签名验签失败如何解决

HarmonyOS鸿蒙Next中使用SM2密钥对签名验签失败如何解决

【问题现象】

使用HarmonyOS的SM2签名的字符串,在Android端进行验签,无法通过。

HarmonyOS端base64之后的签名结果:
MEUCIAYuGY8ZtvJEMn5d81rF1e8TFcGNWKmZ+/YK0VsSreVnAiEAr94jJmpI5nvJPUhFYnddAlF071kFwbJpN0q5++HDa8w=
// Android端验签失败
var byte2 = Base64.decode("MEUCIAYuGY8ZtvJEMn5d81rF1e8TFcGNWKmZ+/YK0VsSreVnAiEAr94jJmpI5nvJPUhFYnddAlF071kFwbJpN0q5++HDa8w=", 2)
val vs = SM2Utils.verifySign(   // 验签失败
  joininstidStr.toByteArray(charset("utf-8")),
  Util.hexToByte(BuildConfig.SM_PUBKEY),
  StringUtil.hexStringToBytes(strForSignSha1),
  StringUtil.hexStringToBytes(StringTool.bytesToHexString(byte2) )
)

【定位思路】

因为HarmonyOS签名后的结果与Android签名后的结果有差异,调用uint8ArrayToHexStr转化后,HarmonyOS和Android的签名结果一致。

【背景知识】

SM2数字签名算法,是基于椭圆曲线的签名验签算法。

以字符串参数完成SM2签名验签,具体的“字符串参数”由“非对称密钥类型”和“摘要”使用符号“|”拼接而成,用于在创建非对称签名验签实例时,指定非对称签名验签算法规格。

参考材料

【解决方案】

签名后需要用uint8ArrayToHexStr方法将其转换为十六进制,再传入d2i_SM2_SignText方法进行数据预处理,最后返回预处理后的数据。

数据转十六进制

// Uint8Array转十六进制
function uint8ArrayToHexStr(data: Uint8Array): string {
  let hexString = "";
  let i: number;
  for (i = 0; i < data.length; i++) {
    let char = ('00' + data[i].toString(16)).slice(-2);
    hexString += char;
  }
  return hexString;
}

签名数据预处理

/*
 * 返回预处理后的数据
 **/
d2i_SM2_SignText(standard_data: string): string {
  let randNum: string = "";
  let signText: string = "";
  let message = standard_data.slice("30".length, standard_data.length);
  let sequence_lenHex: string = this.getLenHex(message);
  message = message.slice(sequence_lenHex.length, message.length);
  
  try {
    let randNum_len: string = message.slice(0, 4);
    if (randNum_len == "0220") {
      randNum = message.slice(4, 4 + 64);
      message = message.slice(4 + 64, message.length);
    } else {
      randNum = message.slice(6, 6 + 64);
      message = message.slice(6 + 64, message.length);
    }
  
    let signText_len: string = message.slice(0, 4);
    if (signText_len == "0220") {
      signText = message.slice(4, 4 + 64);
    } else {
      signText = message.slice(6, 6 + 64);
    }
  } catch (e) {
    hilog.error(0x1, "d2i_SM2_SignText", "SignText format is err");
  }
  return randNum + signText;
}
  
// 辅助函数:提取长度域的Hex字符串
getLenHex(data: string): string {
  let byte: number = Number.parseInt("0x" + data.slice(0, 2));
  let len_size: number = byte > 127 ? byte - 0x80 + 1 : 1;
  return data.slice(0, len_size * 2);
}

更多关于HarmonyOS鸿蒙Next中使用SM2密钥对签名验签失败如何解决的实战教程也可以访问 https://www.itying.com/category-93-b0.html

1 回复

更多关于HarmonyOS鸿蒙Next中使用SM2密钥对签名验签失败如何解决的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS鸿蒙Next中使用SM2密钥对进行签名和验签时,如果遇到失败,可能是以下原因之一:

  1. 密钥对不匹配:确保使用的公钥和私钥是同一对。如果密钥对不匹配,验签将失败。

  2. 数据格式问题:检查待签名数据的格式是否正确。SM2签名算法对输入数据格式有特定要求,确保数据符合规范。

  3. 算法参数配置错误:SM2算法需要正确配置参数,如椭圆曲线参数、哈希算法等。确认这些参数配置正确无误。

  4. 编码问题:签名和验签过程中可能涉及数据的编码和解码。确保在签名和验签时使用相同的编码方式,如Base64或Hex。

  5. 库版本兼容性:检查使用的鸿蒙SDK或相关库的版本是否支持SM2算法。某些旧版本可能不支持或存在bug。

  6. 硬件支持:如果使用硬件安全模块(HSM)或安全芯片进行签名和验签,确保硬件支持SM2算法,并且驱动程序配置正确。

  7. 调试日志:查看调试日志,获取更多错误信息。日志中可能包含具体的失败原因,如参数错误、内存不足等。

  8. 示例代码参考:参考鸿蒙官方提供的SM2签名和验签示例代码,确保实现逻辑与官方推荐一致。

通过以上步骤排查问题,可以有效解决HarmonyOS鸿蒙Next中使用SM2密钥对签名验签失败的情况。

回到顶部