大家好,本人是oh三方库eftool的作者,针对于最初开始的SM2而言,均采用async/await 方法来操作,广大开发者提问最多的就是可不可以是同步操作,在API12中官方也是听劝的均新增了同步操作,故eftool也紧跟其后,接下来我们进入到eftool的同步加密组件SM2Sync的使用

本示例使用eftool版本为API12的1.2.1-rc.2版本

首选需要引入SM2Sync

 import {
  SM2Sync
} from '@yunkss/eftool'

使用

SM2Sync提供了更加灵活的操作方式
针对于生成秘钥方法,可以传入期望生成秘钥的类型,不传默认生成为base64格式,支持传入basea64/hex
针对于加密后的输出字符串 也支持传入输出字符串类型,支持传入basea64/hex
针对于解密传入的key同样支持传入utf8/base64/hex格式的,其中utf8指的是普通字符串

generateSM2Key 生成秘钥

let key = SM2Sync.generateSM2Key();

this.message = key.getDataRow().publicKey;

生成的返回对象为eftool中的OutDTO对象,key.getDataRow().publicKey获取生成的公钥,key.getDataRow().privateKey获取生成的私钥,此时生成的秘钥为base64格式的

let key = SM2Sync.generateSM2Key('hex');

此时生成的秘钥为hex格式

encode 加密

let encode = SM2Sync.encode('测试SM2的加密~~~~',key.getDataRow().publicKey, 'base64');

this.message = encode.getDataRow();

生成的返回对象为eftool中的OutDTO对象,通过encode.getDataRow()获取加密后的内容,此处的base64表示传入key的类型为base64,支持utf8/base64/hex,加密后的结果不传格式此时默认生成的为base64格式


let encode = SM2Sync.encode('测试SM2的加密~~~~',key.getDataRow().publicKey, 'base64', 'hex');

此时'base64', 'hex'表示传入秘钥key的格式为base64,期望加密后的输出格式为hex,支持hex/base64

decode 解密

let decode = SM2Sync.decode(encode.getDataRow(),key.getDataRow().privateKey, 'base64');

this.message = decode.getDataRow();

生成的返回对象为eftool中的OutDTO对象,通过decode.getDataRow()获取解密后的内容,此处的base64表示传入key的类型为base64,支持utf8/base64/hex,待解密的结果不传格式此时默认为base64格式,支持hex/base64

let decode = SM2Sync.decode(encode.getDataRow(),key.getDataRow().privateKey, 'base64', 'hex');

此时'base64', 'hex'表示传入秘钥key的格式为base64,待解密字符串格式为hex,支持hex/base64

sign 签名

let sign = SM2Sync.sign('测试SM2的加密~~~~',key.getDataRow().privateKey, 'base64');

this.message = sign.getDataRow();

生成的返回对象为eftool中的OutDTO对象,通过sign.getDataRow()获签名的结果,此处的base64表示传入key的类型为base64,支持utf8/base64/hex,签名的结果不传格式此时默认为base64格式,支持hex/base64

verify 验签

let verify = SM2Sync.verify(sign.getDataRow(), '测试SM2的加密~~~~',key.getDataRow().publicKey, 'base64');

this.message = verify.getMsg();

生成的返回对象为eftool中的OutDTO对象,通过verify.getMsg()获取验签的结果,此处的base64表示传入key的类型为base64,支持utf8/base64/hex,待验签的字符串不传格式此时默认为base64格式,支持hex/base64

注意,目前服务器端大多数SM2的秘钥都是04开头标准密文GM/T0003.4格式即C1C3C2格式的,而鸿蒙生成的是ASN1格式,故需要进行格式转换,如下提供了公私钥转换方法

convertSM2PubKey 将服务器端生成的16进制的长度为130位的04开头的C1C3C2格式的SM2公钥转换为前端所需的ASN1格式公钥字符串

//C1C3C2格式的公钥字符串
let pk = '04ba3bc3c5834d9ad1a7d81c4b49cf1209d2f28e4a97c73b75d6561792a2bfafe811e0284692006b0ce1b51f8aadfd65241d80eb979365048253408f5d705ec17b';

//转换后的ASN1格式的字符串
let sm2 = await SM2.convertSM2PubKey(pk);

返回对象为eftool中的OutDTO对象,通过sm2.getDataRow()即可获取到转换后的ASN1格式的公钥,接着进行加密即可,此处需要注意转换后的秘钥格式为hex,加解密的key入参格式记得是hex,否则会导致加解密失败

let encode = SM2Sync.encode('测试SM2的加密~~~~', sm2.getDataRow(), 'hex');

let ddd = encode.getDataRow();

convertSM2PriKey 将服务器端生成的16进制的长度为64位的C1C3C2格式的SM2私钥转换为前端所需的ASN1格式SM2私钥字符串


//C1C3C2格式的私钥字符串
let pik = '7713d336bcbbffb8b7f9cab8db984a5c989a0b07697f569a06d5cd38e1351d07';

//转换后的ASN1格式的字符串
let sm2 = await SM2.convertSM2PriKey(pik);

返回对象为eftool中的OutDTO对象,通过sm2.getDataRow()即可获取到转换后的ASN1格式的私钥,接着进行解密即可,此处需要注意转换后的秘钥格式为hex,加解密的key入参格式记得是hex,否则会导致加解密失败

 let decode = SM2Sync.decode(encode.getDataRow(),sm2.getDataRow().privateKey, 'hex');

this.message = aaaa.getDataRow();

扩展知识

鸿蒙生成的秘钥以及加解密后的字符串均为ASN1格式的,而目前服务器端的SM2大多数为标准密文GM/T0003.4格式即C1C3C2格式的,故需要将双端加密后的数据进行标准转换

SM2Convert SM2ASN1跟C1C3C2转换类

d2i ASN1格式的字符串转换成C1C3C2格式的字符


//模拟生成key
let key = SM2Sync.generateSM2Key();

//加密返回ASN1格式字符串,此处需要注意格式转换时ASN1的字符串格式需要为hex,故加密后生成的加密字符串格式只能为hex
let encode = SM2Sync.encode('测试SM2的加密~~~~',key.getDataRow().publicKey, 'base64','hex');

//创建转换类
let convert = new SM2Convert();

//转换格式
let result = convert.d2i(encode.getDataRow());


返回的result即是转换后的C1C3C2格式的字符串

i2dSM2 C1C3C2格式的字符串转换成ASN1格式的字符

//调用方法
let reConvert = convert.i2dSM2(result);

this.msg = reConvert;

返回的reConvert即是转换后的ASN1格式的字符串,此处需要注意转换后的ASN1的字符串格式也为hex

通过本章内容,我们已经学会了SM2Sync的加解密以及签名验签,包括与服务端的互相转换,下一章节我们将学习国密SM4Sync

如果大家有新的需求,欢迎给eftool提出issueissue提交地址

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐