HarmonyOS 鸿蒙Next中SM2密钥协商
HarmonyOS 鸿蒙Next中SM2密钥协商 密钥协商(ArkTS)-开发指导-密钥协商-密钥使用-Universal Keystore Kit(密钥管理服务)-安全-系统 - 华为HarmonyOS开发者
我参考文档写了SM2密钥协商的demo,但是没有输出结果,请问这是什么问题?
09-25 20:01:16.243 33053-33053 A03D00/com.example.dh/JSAPP pid-33053 I Callee constructor is OK string
09-25 20:01:16.243 33053-33053 A03D00/com.example.dh/JSAPP pid-33053 I Ability::constructor callee is object [object Object]
09-25 20:01:16.249 33053-33053 A00000/com.example.dh/testTag pid-33053 I Ability onCreate
09-25 20:01:16.257 33053-33053 A00000/com.example.dh/testTag pid-33053 I Ability onWindowStageCreate
09-25 20:01:16.262 33053-33053 A00000/com.example.dh/testTag pid-33053 I Ability onForeground
09-25 20:01:16.302 33053-33053 A00000/com.example.dh/testTag pid-33053 I Succeeded in loading the content.
import { huks } from '@kit.UniversalKeystoreKit';
// 辅助函数:将字符串转换为 Uint8Array
function StringToUint8Array(str: string) {
let arr: number[] = [];
for (let i = 0, j = str.length; i < j; ++i) {
arr.push(str.charCodeAt(i));
}
return new Uint8Array(arr);
}
// 辅助函数:将 Uint8Array 转换为 BigInt
function Uint8ArrayToBigInt(arr: Uint8Array): bigint {
let i = 0;
const byteMax: bigint = BigInt('0x100');
let result: bigint = BigInt('0');
while (i < arr.length) {
result = result * byteMax;
result = result + BigInt(arr[i]);
i += 1;
}
return result;
}
// SM2 密钥协商基本参数
const sm2Agree: Array<huks.HuksParam> = [
{
tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
value: huks.HuksKeyAlg.HUKS_ALG_SM2, // 使用 SM2 算法
},
{
tag: huks.HuksTag.HUKS_TAG_PURPOSE,
value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_AGREE, // 密钥协商用途
},
];
// SM2 密钥协商参数(256 位密钥)
const sm2Agree256: Array<huks.HuksParam> = [
...sm2Agree,
{
tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
value: huks.HuksKeySize.HUKS_SM2_KEY_SIZE_256, // SM2 256 位密钥
},
];
// SM2 密钥生成选项
const sm2GenOptions: huks.HuksOptions = {
properties: sm2Agree256,
inData: new Uint8Array([]),
};
// 空选项,用于导出密钥等操作
const emptyOptions: huks.HuksOptions = {
properties: [],
inData: new Uint8Array([]),
};
// SM2 密钥协商并导出共享密钥
async function HuksSm2AgreeExportKey(
keyAlias: string,
peerPubKey: huks.HuksReturnResult
): Promise<huks.HuksReturnResult> {
const initHandle = await huks.initSession(keyAlias, sm2GenOptions);
const sm2AgreeUpdatePeerPubKey: huks.HuksOptions = {
properties: [
...sm2Agree256,
{
tag: huks.HuksTag.HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG,
value: huks.HuksKeyStorageType.HUKS_STORAGE_KEY_EXPORT_ALLOWED, // 允许导出共享密钥
},
],
inData: peerPubKey.outData, // 对方的公钥
};
await huks.updateSession(initHandle.handle, sm2AgreeUpdatePeerPubKey);
return await huks.finishSession(initHandle.handle, emptyOptions);
}
// 测试 SM2 密钥协商并导出共享密钥
async function HuksSm2AgreeExportTest(
aliasA: string,
aliasB: string,
pubKeyA: huks.HuksReturnResult,
pubKeyB: huks.HuksReturnResult
) {
const agreedKeyFromAlice = await HuksSm2AgreeExportKey(aliasA, pubKeyB);
console.info(
`ok! agreedKeyFromAlice export is 0x${Uint8ArrayToBigInt(
agreedKeyFromAlice.outData
).toString(16)}`
);
const agreedKeyFromBob = await HuksSm2AgreeExportKey(aliasB, pubKeyA);
console.info(
`ok! agreedKeyFromBob export is 0x${Uint8ArrayToBigInt(
agreedKeyFromBob.outData
).toString(16)}`
);
}
// SM2 密钥协商,共享密钥存储在 HUKS 中
async function HuksSm2AgreeInHuks(
keyAlias: string,
peerPubKey: huks.HuksReturnResult,
aliasAgreedKey: string
): Promise<huks.HuksReturnResult> {
const onlyUsedInHuks: Array<huks.HuksParam> = [
{
tag: huks.HuksTag.HUKS_TAG_KEY_STORAGE_FLAG,
value: huks.HuksKeyStorageType.HUKS_STORAGE_ONLY_USED_IN_HUKS, // 密钥仅在 HUKS 中使用
},
{
tag: huks.HuksTag.HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG,
value: huks.HuksKeyStorageType.HUKS_STORAGE_ONLY_USED_IN_HUKS, // 共享密钥仅在 HUKS 中
},
];
const sm2AgreeInit: huks.HuksOptions = {
properties: [
...sm2Agree,
{
tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
value: huks.HuksKeySize.HUKS_SM4_KEY_SIZE_128, // 使用 SM4 128 位作为协商密钥
},
...onlyUsedInHuks,
],
inData: new Uint8Array([]),
};
const sm2AgreeFinishParams: Array<huks.HuksParam> = [
...onlyUsedInHuks,
{
tag: huks.HuksTag.HUKS_TAG_IS_KEY_ALIAS,
value: true,
},
{
tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
value: huks.HuksKeyAlg.HUKS_ALG_SM4, // 协商密钥用于 SM4 加密
},
{
tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
value: huks.HuksKeySize.HUKS_SM4_KEY_SIZE_128, // SM4 128 位密钥
},
{
tag: huks.HuksTag.HUKS_TAG_PURPOSE,
value:
huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT |
huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT, // 加密和解密用途
},
];
const handle = await huks.initSession(keyAlias, sm2AgreeInit);
const sm2AgreeUpdatePubKey: huks.HuksOptions = {
properties: [...sm2Agree, ...onlyUsedInHuks],
inData: peerPubKey.outData, // 对方的公钥
};
await huks.updateSession(handle.handle, sm2AgreeUpdatePubKey);
const sm2AgreeFinish: huks.HuksOptions = {
properties: [
...sm2AgreeFinishParams,
{
tag: huks.HuksTag.HUKS_TAG_KEY_ALIAS,
value: StringToUint8Array(aliasAgreedKey), // 共享密钥的别名
},
],
inData: new Uint8Array([]),
};
return await huks.finishSession(handle.handle, sm2AgreeFinish);
}
// 测试 SM2 密钥协商,共享密钥存储在 HUKS 中
async function HuksSm2AgreeInHuksTest(
aliasA: string,
aliasB: string,
pubKeyA: huks.HuksReturnResult,
pubKeyB: huks.HuksReturnResult,
aliasAgreedKeyFromA: string,
aliasAgreedKeyFromB: string
) {
const finishAliceResult = await HuksSm2AgreeInHuks(
aliasA,
pubKeyB,
aliasAgreedKeyFromA
);
console.info(
`ok! finishAliceResult in huks is 0x${Uint8ArrayToBigInt(
finishAliceResult.outData
).toString(16)}`
);
const aliceAgreedExist = await huks.isKeyItemExist(
aliasAgreedKeyFromA,
emptyOptions
);
console.info(`ok! aliceAgreedExist in huks is ${aliceAgreedExist}`);
const finishBobResult = await HuksSm2AgreeInHuks(
aliasB,
pubKeyA,
aliasAgreedKeyFromB
);
console.info(
`ok! finishBobResult in huks is 0x${Uint8ArrayToBigInt(
finishBobResult.outData
).toString(16)}`
);
const bobAgreedExist = await huks.isKeyItemExist(
aliasAgreedKeyFromB,
emptyOptions
);
console.info(`ok! bobAgreedExist in huks is ${bobAgreedExist}`);
// 清理协商生成的密钥
await huks.deleteKeyItem(aliasAgreedKeyFromA, emptyOptions);
await huks.deleteKeyItem(aliasAgreedKeyFromB, emptyOptions);
}
// 主测试函数
async function HuksSm2AgreeTest() {
const aliasAlice = 'alice';
const aliasBob = 'bob';
// 生成 Alice 和 Bob 的 SM2 密钥对
await huks.generateKeyItem(aliasAlice, sm2GenOptions);
await huks.generateKeyItem(aliasBob, sm2GenOptions);
// 导出 Alice 和 Bob 的公钥
const pubKeyAlice = await huks.exportKeyItem(aliasAlice, emptyOptions);
const pubKeyBob = await huks.exportKeyItem(aliasBob, emptyOptions);
// 测试 SM2 密钥协商并导出共享密钥
await HuksSm2AgreeExportTest(aliasAlice, aliasBob, pubKeyAlice, pubKeyBob);
// 测试 SM2 密钥协商,共享密钥存储在 HUKS 中
await HuksSm2AgreeInHuksTest(
aliasAlice,
aliasBob,
pubKeyAlice,
pubKeyBob,
'agreedKeyFromAlice',
'agreedKeyFromBob'
);
// 清理密钥
await huks.deleteKeyItem(aliasAlice, emptyOptions);
await huks.deleteKeyItem(aliasBob, emptyOptions);
}
// 运行测试
HuksSm2AgreeTest();
@Entry
@Component
struct Index {
@State message: string = 'Hello World';
build() {
RelativeContainer() {
Text(this.message)
.id('HelloWorld')
.fontSize($r('app.float.page_text_font_size'))
.fontWeight(FontWeight.Bold)
.alignRules({
center: { anchor: '__container__', align: VerticalAlign.Center },
middle: { anchor: '__container__', align: HorizontalAlign.Center }
})
.onClick(() => {
this.message = 'Welcome';
})
}
.height('100%')
.width('100%')
}
}
更多关于HarmonyOS 鸿蒙Next中SM2密钥协商的实战教程也可以访问 https://www.itying.com/category-93-b0.html
【解决方案】
根据密钥协商介绍及算法规格,目前仅支持ECDH,DH,X25519,不支持SM2。
更多关于HarmonyOS 鸿蒙Next中SM2密钥协商的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
顶帖
在HarmonyOS鸿蒙Next中,SM2密钥协商基于国密算法标准,用于安全建立共享密钥。它通过椭圆曲线密码机制实现双方密钥交换,依赖SM2密钥对(公钥和私钥)完成协商过程。系统提供相关API支持密钥生成、协商计算及协议处理,确保端到端通信安全。具体实现需调用鸿蒙密码库接口,遵循GM/T 0003.5标准规范。
根据你提供的代码和日志,问题可能出现在以下几个方面:
-
密钥生成阶段:日志显示应用正常启动,但没有密钥协商相关的输出。首先检查
generateKeyItem
是否成功执行,建议在每个关键操作后添加日志输出,确认密钥对生成是否完成。 -
公钥导出问题:
exportKeyItem
可能返回空数据。确保aliasAlice
和aliasBob
对应的密钥已正确生成,且具有导出权限(HUKS_TAG_EXPORTABLE
标签应设置为true)。 -
密钥协商参数不匹配:在
HuksSm2AgreeExportKey
函数中,sm2AgreeUpdatePeerPubKey
的properties
包含了HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG
,但协商阶段可能不需要此标签。尝试移除该标签,仅保留基础SM2参数。 -
数据类型转换错误:
Uint8ArrayToBigInt
函数在处理空或无效数据时可能抛出异常,导致后续日志无法输出。建议在转换前检查outData
是否非空。 -
异步操作未正确处理:确保所有
huks
API调用均使用await
,避免因异步未完成而跳过关键步骤。
建议先添加详细日志,定位具体失败的操作步骤,再逐步调整参数配置。