HarmonyOS 鸿蒙Next 国密SM2解密报错,错误码17630001如何解决
HarmonyOS 鸿蒙Next 国密SM2解密报错,错误码17630001如何解决
【问题现象】
采用国密SM2加密,对加密出来的密文做解密操作报错,错误码。
加密实现代码如下:
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算法规格:SM2为非对称加密算法,加密长度需要在固定长度进行。
- 使用SM2非对称密钥加解密开发指导。
【定位思路】
根据错误码,查询相关信息,可能是加解密算法框架与三方算法库交互时出现错误。但是基于这个还是无法定位具体错误地方。考虑是否是传给三方算法库的参数有问题,最终发现入参的长度有问题,如下:
加密出来的密文长度为单数,不符合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,这通常指示了一个特定的解密问题。错误码本身并未在公开文档中详细列出,但基于一般经验和HarmonyOS的加密框架(CryptoFramework)的使用,可以推断这可能涉及到密钥格式、密文格式不匹配或加密解密过程中的内部错误。
要解决这个问题,可以尝试以下步骤:
- 检查密钥格式:确保用于解密的私钥格式正确,且与加密时使用的公钥相匹配。特别是注意密钥是否已正确转换为HarmonyOS所需的格式。
- 验证密文格式:确认密文是否按照ASN.1标准进行了序列化。如果不是,需要先将密文转换为正确的格式。
- 更新加密框架:确保你使用的CryptoFramework是最新版本,以避免已知的bug或兼容性问题。
如果以上步骤无法解决问题,建议联系HarmonyOS的官方技术支持,或访问HarmonyOS的开发者论坛寻求帮助。如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html 。