HarmonyOS 鸿蒙Next中国密SM2解密报错,错误码17630001如何解决

HarmonyOS 鸿蒙Next中国密SM2解密报错,错误码17630001如何解决

【问题现象】

采用国密SM2加密,对加密出来的密文做解密操作报错,错误码17630001。

加密实现代码如下:

export class SM2Util {

  private pubKeyStr =
    '4c7945d9c844fa33dd6b9037c0ee6bb2dd5d6cf57a758192f339964be6bbb26dd7d5818cf3ad89d28be29a37f2293c90e3a8dbdfd22d326c504a9c7e7f6b5e41'
  private priKeyStr = 'fa2d69db54fa99a24303f27b285712e500afedd8797e02cb4b170ff5827c8688'

  /**
   * 加密
   * @param str
   * @param pubKeyStr
   * @returns
   */
  async encSM2C1C2C3(str: string, pubKeyStr = this.pubKeyStr) {
    // 将128位公钥字符串转为PubKey
    let pubKey = await this.convertStrToPubKey(pubKeyStr)
    let res = await this.encryptMessagePromise(pubKey, str)
    let spec: cryptoFramework.SM2CipherTextSpec = cryptoFramework.SM2CryptoUtil.getCipherTextSpec(res, 'C1C3C2')
    let C1 = spec.xCoordinate.toString(16) + spec.yCoordinate.toString(16)
    let C2 = buffer.from(spec.cipherTextData).toString('hex')
    let C3 = buffer.from(spec.hashData).toString('hex')
    return '04' + C1 + C2 + C3
  }

  /**
   * 将128位公钥字符串转为PubKey
   * @param keyStr 128位公钥字符串
   * @returns PubKey
   */
  private async convertStrToPubKey(pubKeyStr: string): Promise<cryptoFramework.PubKey> {
    // let pubKeyStr = keyStr.startsWith("04") ? keyStr.slice(2) : keyStr
    let pkPart1 = pubKeyStr.slice(0, pubKeyStr.length / 2)
    let pkPart2 = pubKeyStr.slice(pubKeyStr.length / 2)
    let pk: cryptoFramework.Point = {
      x: BigInt("0x" + pkPart1),
      y: BigInt("0x" + pkPart2),
    }
    let pubKeySpec: cryptoFramework.ECCPubKeySpec = {
      params: cryptoFramework.ECCKeyUtil.genECCCommonParamsSpec('NID_sm2'),
      pk: pk,
      algName: "SM2",
      specType: cryptoFramework.AsyKeySpecType.PUBLIC_KEY_SPEC
    }
    let keypairGenerator = cryptoFramework.createAsyKeyGeneratorBySpec(pubKeySpec)
    return await keypairGenerator.generatePubKey()
  }

  /**
   * 生成Cipher实例,获取加密后的数据。
   * @param publicKey
   * @param plainText
   * @returns
   */
  private async encryptMessagePromise(publicKey: cryptoFramework.PubKey, plainText: string) {
    let cipher = cryptoFramework.createCipher('SM2_256|SM3')
    await cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, publicKey, null)
    let encryptData = await cipher.doFinal({ data: this.stringToUint8Array(plainText) })
    return encryptData
  }

  // 字符串转成字节流
  private stringToUint8Array(str: string) {
    return new Uint8Array(buffer.from(str, 'utf-8').buffer)
  }
}

【背景知识】

【定位思路】

根据错误码,查询相关信息,可能是加解密算法框架与三方算法库交互时出现错误。但是基于这个还是无法定位具体错误地方。考虑是否是传给三方算法库的参数有问题,最终发现入参的长度有问题,如下:

点击放大

加密出来的密文长度为单数,不符合SM2规格,所以解密的时候报错。

【解决方案】

国密算法的底层实现是OpenSSL,为了防止数据在拼接的时候被截取到,在返回OpenSSL数据时是直接透传返回的,中间不作任何操作来保证安全性。而OpenSSL底层返回的数据规范是在高位是的情况下默认不显示,针对这种情况需要业务自己实现,即判断返回的密文长度是否为固定的64位长度,不满足的话对高位进行补0即可。

代码示例如下:

async encSM2C1C2C3(str: string, pubKeyStr = this.pubKeyStr) {
    let pubKey = await this.convertStrToPubKey(pubKeyStr)
    let res = await this.encryptMessagePromise(pubKey, str)
    let spec: cryptoFramework.SM2CipherTextSpec = cryptoFramework.SM2CryptoUtil.getCipherTextSpec(res, 'C1C3C2')
    let C1x = spec.xCoordinate.toString(16)
    let C1y = spec.yCoordinate.toString(16)
    if (C1x.length != 64) {
      C1x = '0' + C1x
    }
    if (C1y.length != 64) {
      C1y = '0' + C1y
    }
    let C2 = buffer.from(spec.cipherTextData).toString('hex')
    let C3 = buffer.from(spec.hashData).toString('hex')
    return '04' + C1x + C1y + C2 + C3
 }

更多关于HarmonyOS 鸿蒙Next中国密SM2解密报错,错误码17630001如何解决的实战教程也可以访问 https://www.itying.com/category-93-b0.html

1 回复

更多关于HarmonyOS 鸿蒙Next中国密SM2解密报错,错误码17630001如何解决的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS鸿蒙Next中使用中国密SM2解密时,报错17630001通常与密钥格式或数据输入不匹配有关

SM2解密要求密钥和数据符合特定格式,错误码17630001表示解密过程中遇到格式问题。

首先,确保使用的私钥是有效的SM2私钥,且格式正确。SM2私钥通常为DER或PEM格式,需符合国密标准。其次,检查待解密的数据是否为有效的SM2加密数据,数据格式需与加密时一致。

如果密钥和数据格式无误,检查解密函数的参数是否正确传递。确保密钥、密文和其他参数(如IV或填充模式)正确设置。

最后,确认使用的鸿蒙版本和SM2库是否支持当前的解密操作。某些版本可能存在兼容性问题,建议查阅相关文档或更新到最新版本。

若问题仍未解决,可尝试使用其他SM2工具或库进行解密,以排除环境或实现问题。

回到顶部