HarmonyOS Developer 通用密钥库开发指导
通用密钥库开发概述
简介
通用密钥库系统(HarmonyOS Universal KeyStore,以下简称HUKS)是HarmonyOS提供的系统级的密钥管理系统服务,提供密钥的全生命周期管理能力,包括密钥生成、密钥存储、密钥使用、密钥销毁等功能,以及对存储在HUKS中的密钥提供合法性证明。
HUKS基于系统安全能力,为业务提供密钥全生命周期的安全管理,业务无需自己实现,利用HUKS的系统能力,就能确保业务密钥的安全。
以下目录文档主要介绍了HUKS在典型场景下的用法、原理以及支持的密码算法规格。
基本概念
在使用HUKS开发之前,建议了解以下基本概念:
- HUKS Core
HUKS核心组件,承载HUKS的核心功能,包括密钥的密码学运算、明文密钥的加解密、密钥访问控制等。一般运行在设备的安全环境中(如TEE、安全芯片等,不同的厂商有所不同),保证密钥明文不出HUKS Core。 - 密钥会话
应用通过指定密钥别名,给当前操作的密钥建立一个会话,HUKS为每个会话生成一个全局唯一的句柄值来索引该会话。它的作用是缓存密钥使用期间的信息,包括操作数据、密钥信息、访问控制属性等。密钥操作一般需要经过建立会话、传入数据和参数、结束会话(中止会话)三个阶段。
实现原理
HUKS的核心安全设计包括以下几点:
- 密钥不出安全环境
HUKS的核心特点是密钥全生命周期明文不出HUKS Core,在有硬件条件的设备上,如有TEE(Trusted Execution Environment)或安全芯片的设备,HUKS Core运行在硬件安全环境中。能确保即使REE(Rich Execution Environment)环境被攻破,密钥明文也不会泄露。 - 系统级安全加密存储
基于设备根密钥加密业务密钥,在有条件的设备上,叠加用户口令加密保护密钥。 - 严格的访问控制
只有合法的业务才有权访问密钥,同时支持用户身份认证访问控制以支持业务的高安敏感场景下安全访问密钥的诉求。 - 密钥的合法性证明
可为业务提供硬件厂商级别的密钥的合法性证明,证明密钥没有被篡改,并确实存在于有硬件保护的HUKS Core中,以及拥有正确的密钥属性。
此外,密钥会话是HUKS中承载密钥使用的基础,它的主要作用是初始化密钥信息、缓存业务数据等。对数据的密码学运算和对密钥密文的加解密都是在HUKS Core中进行,以此保证密钥明文和运算过程的安全。
图1 HUKS运行机制
约束与限制
- 基于别名的访问
由于密钥材料不出HUKS的限制,应用只能以别名的方式访问密钥材料,而且密钥的别名必须保证应用内唯一(否则已存在的同别名密钥会被覆盖),长度不能超过64个字节。 - 数据分片大小限制
所有数据需要经过IPC通道传输到HUKS,受IPC缓冲区大小限制,建议对总大小超过100K的数据进行分片传输,且分片大小不超过100K。 - 指定必选参数
在生成密钥或导入密钥时,必须指定密码算法、密钥大小和使用目的参数,其他参数可选(如工作模式、填充模式、散列算法等),但是在使用密钥时必须传入密码算法相关的完整的参数。 - 密钥材料格式
导入/导出密钥时(包括密钥对、公钥、私钥),密钥材料的数据格式必须满足HUKS要求的格式,具体各个密码算法密钥材料见密钥材料格式。
通用密钥库开发指导
生成新密钥
HUKS提供为业务安全随机生成密钥的能力。通过HUKS生成的密钥,密钥的全生命周期明文不会出安全环境,能保证任何人都无法接触获取到密钥的明文。即使生成密钥的业务自身,后续也只能通过HUKS提供的接口请求执行密钥操作,获取操作结果,但无法接触到密钥自身。
开发步骤
生成密钥时使用huks.generateKeyItem方法,传入keyAlias作为密钥别名,传入options包含该密钥的属性集,传入callback用于回调异步结果。关于接口的具体信息,可在API参考文档中查看。
- 确定密钥别名;
- 初始化密钥属性集:通过HuksParam封装密钥属性,搭配Array组成密钥属性集,并赋值给HuksOptions(properties字段),其中必须包含HuksKeyAlg,HuksKeySize,HuksKeyPurpose属性;
- 将密钥别名与密钥参数集作为参数传入,生成密钥。
说明
存储的 keyAlias 密钥别名最大为64字节
代码示例:
/*
* 以下以生成AES密钥的Callback操作使用为例
*/
import huks from '@ohos.security.huks';
/*
* 确定密钥别名和封装密钥属性参数集
*/
let keyAlias = 'aes_key';
let properties = new Array();
properties[0] = {
tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
value: huks.HuksKeyAlg.HUKS_ALG_AES
}
properties[1] = {
tag: huks.HuksTag.HUKS_TAG_PURPOSE,
value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT | huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT
}
properties[2] = {
tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256
}
properties[3] = {
tag: huks.HuksTag.HUKS_TAG_PADDING,
value: huks.HuksKeyPadding.HUKS_PADDING_NONE
}
properties[4] = {
tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE,
value: huks.HuksCipherMode.HUKS_MODE_CBC
};
let huksOptions = {
properties: properties,
inData: new Uint8Array(new Array())
}
/*
* 生成密钥
*/
function generateKeyItem(keyAlias: string, huksOptions: huks.HuksOptions) {
return new Promise((resolve, reject) => {
try {
huks.generateKeyItem(keyAlias, huksOptions, function (error, data) {
if (error) {
reject(error);
} else {
resolve(data);
}
});
} catch (error) {
throw (error);
}
});
}
async function publicGenKeyFunc(keyAlias: string, huksOptions: huks.HuksOptions) {
console.info(`enter callback generateKeyItem`);
try {
await generateKeyItem(keyAlias, huksOptions)
.then((data) => {
console.info(`callback: generateKeyItem success, data = ${JSON.stringify(data)}`);
})
.catch(error => {
console.error(`callback: generateKeyItem failed, code: ${error.code}, msg: ${error.message}`);
});
} catch (error) {
console.error(`callback: generateKeyItem input arg invalid, code: ${error.code}, msg: ${error.message}`);
}
}
async function TestGenKey() {
await publicGenKeyFunc(keyAlias, huksOptions);
}
导入外部密钥
如果密钥是在HUKS外部生成(比如应用间协商生成、服务器端生成),应用可以将密钥导入到HUKS托管。HUKS支持直接将密钥明文导入到HUKS,但是明文导入会导致密钥暴露在REE内存中,一般适用于轻量级设备或低安业务。对于高安敏感业务,HUKS还提供了安全导入密钥的能力,允许业务自己生成密钥,并通过与处于安全环境中的HUKS建立端到端的加密传输通道,将密钥安全加密导入到HUKS中,确保导入传入过程中密钥不被泄露。
与生成密钥一样,密钥一旦导入到HUKS中,密钥的生命周期明文不出安全环境,同样能保证任何人都无法接触获取到密钥的明文。
明文导入
导入明文密钥时使用huks.importKeyItem(keyAlias,options,callback)方法,传入keyAlias作为密钥别名,传入options,其中必须包含密钥材料和密钥属性集,传入callback用于回调异步结果。关于接口的具体信息,可在API参考文档中查看。
- 确定密钥别名;
- 封装密钥材料和密钥属性集:密钥材料须符合HUKS密钥材料格式并以Uint8Array形式赋值给HuksOptions的inData字段;另外,通过HuksParam封装密钥属性,搭配Array组成密钥属性集赋值给properties字段,属性集中必须包含HuksKeyAlg,HuksKeySize,HuksKeyPurpose属性;
- 导入密钥。
代码示例:
/*
* 以导入AES256密钥为例
*/
/* 密钥 */
let plainTextSize32 = new Uint8Array([
0xfb, 0x8b, 0x9f, 0x12, 0xa0, 0x83, 0x19, 0xbe, 0x6a, 0x6f, 0x63, 0x2a, 0x7c, 0x86, 0xba, 0xca,
0x64, 0x0b, 0x88, 0x96, 0xe2, 0xfa, 0x77, 0xbc, 0x71, 0xe3, 0x0f, 0x0f, 0x9e, 0x3c, 0xe5, 0xf9
]);
/*
* 确定密钥别名
*/
let keyAlias = 'AES256Alias_sample';
/*
* 封装密钥属性集和密钥材料
*/
let properties = new Array();
properties[0] = {
tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
value: huks.HuksKeyAlg.HUKS_ALG_AES
};
properties[1] = {
tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256
};
properties[2] = {
tag: huks.HuksTag.HUKS_TAG_PURPOSE,
value:
huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT | huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT
};
let options = {
properties: properties,
inData: plainTextSize32
};
/*
* 导入密钥
*/
try {
huks.importKeyItem(keyAlias, options, function (error, data) {
if (error) {
console.error(`callback: importKeyItem failed, code: ${error.code}, msg: ${error.message}`);
} else {
console.info(`callback: importKeyItem success`);
}
});
} catch (error) {
console.error(`callback: importKeyItem input arg invalid, code: ${error.code}, msg: ${error.message}`);
}
调测验证
验证时查询密钥是否存在,如密钥存在即表示生成密钥成功。
代码示例:
import huks from '@ohos.security.huks';
let keyAlias = 'AES256Alias_sample';
let isKeyExist;
let keyProperties = new Array();
keyProperties[0] = {
tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
value: huks.HuksKeyAlg.HUKS_ALG_AES,
}
let huksOptions = {
properties: keyProperties, // 非空填充
inData: new Uint8Array(new Array()) // 非空填充
}
try {
huks.isKeyItemExist(keyAlias, huksOptions, function (error, data) {
if (error) {
console.error(`callback: isKeyItemExist failed, code: ${error.code}, msg: ${error.message}`);
} else {
if (data !== null && data.valueOf() !== null) {
isKeyExist = data.valueOf();
console.info(`callback: isKeyItemExist success, isKeyExist = ${isKeyExist}`);
}
}
});
} catch (error) {
console.error(`callback: isKeyItemExist input arg invalid, code: ${error.code}, msg: ${error.message}`);
}
加密导入
相比明文导入,加密导入步骤更多,密钥材料更复杂,此章节将展示开发过程中关键的开发流程和密钥材料数据结构。下图是加密导入的基本开发流程。
图2 加密导入开发流程
接口说明
根据开发流程,在导入加密密钥过程中,需要依次调用HUKS的生成密钥、导出公钥、导入加密密钥、删除密钥接口。
接口名 | 描述 |
generateKeyItem(keyAlias: string, options: HuksOptions, callback: AsyncCallback<void>) : void | 生成新密钥 |
exportKeyItem(keyAlias: string, options: HuksOptions, callback: AsyncCallback<HuksReturnResult>) : void | 导出密钥对的公钥 |
importWrappedKeyItem(keyAlias: string, wrappingKeyAlias: string, options: HuksOptions, callback: AsyncCallback<void>) : void | 导入加密密钥 |
deleteKeyItem(keyAlias: string, options: HuksOptions, callback: AsyncCallback<void>) : void | 删除密钥 |
需要注意的是,导出密钥接口返回的公钥明文材料是按照X.509格式封装,导入加密密钥接口中的密钥材料需满足LengthData-Data 的格式封装。具体,应用需要申请一个Uint8Array按照以下表格中的顺序依次封装。
表2 加密密钥材料格式
内容 | 业务公钥长度Lpk2 | 业务公钥pk2 | k2加密参数AAD2长度LAAD2 | k2加密参数AAD2 | k2加密参数Nonce2长度LNonce2 | k2加密参数Nonce2 |
长度 | 4字节 | Lpk2字节 | 4字节 | LAAD2字节 | 4字节 | LNonce2字节 |
内容 | k2加密参数AEAD2长度LAEAD2 | k2加密参数AEAD2 | k3密文长度Lk3_enc | k3密文k3_enc | k3加密参数AAD3长度LAAD3 | k3加密参数AAD3 |
长度 | 4字节 | LAEAD2字节 | 4字节 | Lk3_enc字节 | 4字节 | LAAD3字节 |
内容 | k3加密参数Nonce3长度LNonce3 | k3加密参数Nonce3 | k3加密参数AEAD3长度LAEAD3 | k3加密参数AEAD3 | 密钥明文材料长度 的长度Lk1'_size | 密钥明文材料长度k1'_size |
长度 | 4字节 | LNonce3字节 | 4字节 | LAEAD3字节 | 4字节 | Lk1'_size字节 |
内容 | k1'密文长度Lk1'_enc | k1'密文k1'_enc |
|
|
|
|
长度 | 4字节 | Lk1'_enc字节 |
|
|
|
|
开发步骤
这里主要展示涉及调用HUKS的开发样例(使用ECDH密钥协商套件),部分在业务本地执行的步骤不在这里展示详细样例。
- 转换成HUKS格式的密钥材料
- 生成加密导入用途的密钥
- 导出公钥材料
- 封装加密导入密钥材料
- 导入封装的加密密钥材料
- 删除用于加密导入的密钥
代码示例:
/*
* 以下以SM2密钥的Callback操作验证为例
*/
import huks from '@ohos.security.huks';
/*
* 确定密钥别名
*/
let importAlias = "importAlias";
let wrapAlias = "wrappingKeyAlias";
let exportKey;
/*
* 加密导入用途的密钥材料原文:转换成HUKS ECC-P-256密钥对格式的密钥材料
*/
let inputEccPair = new Uint8Array([
0x02, 0x00, 0x00, 0x00, // 密钥算法:huks.HuksKeyAlg.HUKS_ALG_ECC = 2
0x00, 0x01, 0x00, 0x00, // 密钥大小(比特):256
0x20, 0x00, 0x00, 0x00, // 坐标x长度(字节):32
0x20, 0x00, 0x00, 0x00, // 坐标y长度(字节):32
0x20, 0x00, 0x00, 0x00, // 坐标z长度(字节):32
// 坐标x
0xa5, 0xb8, 0xa3, 0x78, 0x1d, 0x6d, 0x76, 0xe0, 0xb3, 0xf5, 0x6f, 0x43, 0x9d, 0xcf, 0x60, 0xf6,
0x0b, 0x3f, 0x64, 0x45, 0xa8, 0x3f, 0x1a, 0x96, 0xf1, 0xa1, 0xa4, 0x5d, 0x3e, 0x2c, 0x3f, 0x13,
// 坐标y
0xd7, 0x81, 0xf7, 0x2a, 0xb5, 0x8d, 0x19, 0x3d, 0x9b, 0x96, 0xc7, 0x6a, 0x10, 0xf0, 0xaa, 0xbc,
0x91, 0x6f, 0x4d, 0xa7, 0x09, 0xb3, 0x57, 0x88, 0x19, 0x6f, 0x00, 0x4b, 0xad, 0xee, 0x34, 0x35,
// 坐标z
0xfb, 0x8b, 0x9f, 0x12, 0xa0, 0x83, 0x19, 0xbe, 0x6a, 0x6f, 0x63, 0x2a, 0x7c, 0x86, 0xba, 0xca,
0x64, 0x0b, 0x88, 0x96, 0xe2, 0xfa, 0x77, 0xbc, 0x71, 0xe3, 0x0f, 0x0f, 0x9e, 0x3c, 0xe5, 0xf9
]);
/*
* 封装密钥属性参数集
*/
// 生成加密导入用途的密钥的属性集
let properties = new Array();
properties[0] = {
tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
value: huks.HuksKeyAlg.HUKS_ALG_ECC
};
properties[1] = {
tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
value: huks.HuksKeySize.HUKS_ECC_KEY_SIZE_256
};
properties[2] = {
tag: huks.HuksTag.HUKS_TAG_PURPOSE,
value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_UNWRAP
};
properties[3] = {
tag: huks.HuksTag.HUKS_TAG_DIGEST,
value: huks.HuksKeyDigest.HUKS_DIGEST_SHA256
};
properties[4] = {
tag: huks.HuksTag.HUKS_TAG_IMPORT_KEY_TYPE,
value: huks.HuksImportKeyType.HUKS_KEY_TYPE_KEY_PAIR,
};
let huksOptions = {
properties: properties,
inData: inputEccPair
};
// 待导入密钥的属性集:AES256
let importProperties = new Array();
importProperties[0] = {
tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
value: huks.HuksKeyAlg.HUKS_ALG_AES
};
importProperties[1] = {
tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256
};
importProperties[2] = {
tag: huks.HuksTag.HUKS_TAG_PURPOSE,
value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT | huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT
};
importProperties[3] = {
tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE,
value: huks.HuksCipherMode.HUKS_MODE_CBC
};
importProperties[4] = {
tag: huks.HuksTag.HUKS_TAG_PADDING,
value: huks.HuksKeyPadding.HUKS_PADDING_NONE
};
importProperties[5] = {
tag: huks.HuksTag.HUKS_TAG_UNWRAP_ALGORITHM_SUITE,
value: huks.HuksUnwrapSuite.HUKS_UNWRAP_SUITE_ECDH_AES_256_GCM_NOPADDING // 使用“ECDH+AES256GCM”加密导入套件
};
let importOptions = {
properties: importProperties,
inData: new Uint8Array(new Array())
};
// 导出加密导入用途的公钥
function exportKeyItem(keyAlias:string, huksOptions:huks.HuksOptions, throwObject) : Promise<huks.HuksReturnResult> {
return new Promise((resolve, reject) => {
try {
huks.exportKeyItem(keyAlias, huksOptions, function (error, data) {
if (error) {
reject(error);
} else {
resolve(data);
}
});
} catch (error) {
throwObject.isThrow = true;
throw(error);
}
});
}
async function publicExportKeyFunc(keyAlias:string, huksOptions:huks.HuksOptions) {
console.info(`enter callback export`);
let throwObject = {isThrow: false};
try {
await exportKeyItem(keyAlias, huksOptions, throwObject)
.then ((data) => {
console.info(`callback: exportKeyItem success, data = ${JSON.stringify(data)}`);
exportKey = data.outData;
})
.catch(error => {
if (throwObject.isThrow) {
throw(error);
} else {
console.error(`callback: exportKeyItem failed, code: ${error.code}, msg: ${error.message}`);
}
});
} catch (error) {
console.error(`callback: exportKeyItem input arg invalid, code: ${error.code}, msg: ${error.message}`);
}
}
// 此处用导入密钥来模拟“生成加密导入用途的密钥”
function importKeyItem(keyAlias:string, huksOptions:huks.HuksOptions, throwObject) {
return new Promise((resolve, reject) => {
try {
huks.importKeyItem(keyAlias, huksOptions, function (error, data) {
if (error) {
reject(error);
} else {
resolve(data);
}
});
} catch (error) {
throwObject.isThrow = true;
throw(error);
}
});
}
async function publicImportKeyFunc(keyAlias:string, huksOptions:huks.HuksOptions) {
console.info(`enter promise importKeyItem`);
let throwObject = {isThrow: false};
try {
await importKeyItem(keyAlias, huksOptions, throwObject)
.then ((data) => {
console.info(`callback: importKeyItem success, data = ${JSON.stringify(data)}`);
})
.catch(error => {
if (throwObject.isThrow) {
throw(error);
} else {
console.error(`callback: importKeyItem failed, code: ${error.code}, msg: ${error.message}`);
}
});
} catch (error) {
console.error(`callback: importKeyItem input arg invalid, code: ${error.code}, msg: ${error.message}`);
}
}
// 执行加密导入
async function publicImportWrappedKey(keyAlias:string, wrappingKeyAlias:string, huksOptions:huks.HuksOptions) {
console.info(`enter callback importWrappedKeyItem`);
var throwObject = {isThrow: false};
try {
await importWrappedKeyItem(keyAlias, wrappingKeyAlias, huksOptions, throwObject)
.then ((data) => {
console.info(`callback: importWrappedKeyItem success, data = ${JSON.stringify(data)}`);
})
.catch(error => {
if (throwObject.isThrow) {
throw(error);
} else {
console.error(`callback: importWrappedKeyItem failed, code: ${error.code}, msg: ${error.message}`);
}
});
} catch (error) {
console.error(`callback: importWrappedKeyItem input arg invalid, code: ${error.code}, msg: ${error.message}`);
}
}
function importWrappedKeyItem(keyAlias:string, wrappingKeyAlias:string, huksOptions:huks.HuksOptions, throwObject) {
return new Promise((resolve, reject) => {
try {
huks.importWrappedKeyItem(keyAlias, wrappingKeyAlias, huksOptions, function (error, data) {
if (error) {
reject(error);
} else {
resolve(data);
}
});
} catch (error) {
throwObject.isThrow = true;
throw(error);
}
});
}
// 删除加密导入用途的密钥
function deleteKeyItem(keyAlias:string, huksOptions:huks.HuksOptions, throwObject) {
return new Promise((resolve, reject) => {
try {
huks.deleteKeyItem(keyAlias, huksOptions, function (error, data) {
if (error) {
reject(error);
} else {
resolve(data);
}
});
} catch (error) {
throwObject.isThrow = true;
throw(error);
}
});
}
async function publicDeleteKeyFunc(keyAlias:string, huksOptions:huks.HuksOptions) {
console.info(`enter callback deleteKeyItem`);
let throwObject = {isThrow: false};
try {
await deleteKeyItem(keyAlias, huksOptions, throwObject)
.then ((data) => {
console.info(`callback: deleteKeyItem key success, data = ${JSON.stringify(data)}`);
})
.catch(error => {
if (throwObject.isThrow) {
throw(error);
} else {
console.error(`callback: deleteKeyItem failed, code: ${error.code}, msg: ${error.message}`);
}
});
} catch (error) {
console.error(`callback: deletKeeyItem input arg invalid, code: ${error.code}, msg: ${error.message}`);
}
}
async function ImportWrappedKeyNormalTest() {
console.info(`enter ImportWrapKey test`);
/*
* 生成加密导入用途的密钥(此处使用导入进行模拟)
*/
await publicImportKeyFunc(wrapAlias, huksOptions);
/*
* 导出加密导入用途密钥的公钥材料
*/
await publicExportKeyFunc(wrapAlias, huksOptions);
/*----------------------------------------------------------------------------------------------
* 此处省略业务本地生成ECC密钥对、业务本地ECDH密钥协商、业务本地生成密钥加密密钥K3、业务本地加密K1'和K3的流程
*----------------------------------------------------------------------------------------------*/
/* 封装加密导入密钥材料:参考加密导入
* 拼接importOptions.inData字段,满足以下格式:
* PK2长度(4字节) + PK2的数据 + AAD2的长度(4字节) + AAD2的数据 +
* Nonce2的长度(4字节)+ Nonce2的数据 + AEAD2的长度(4字节) + AEAD2的数据 +
* K3密文的长度(4字节) + K3密文的数据 + AAD3的长度(4字节) + AAD3的数据 +
* Nonce3的长度(4字节) + Nonce3的数据 + AEAD3的长度(4字节) + AEAD3的数据 +
* K1'_size的长度(4字节) + K1'_size + K1'_enc的长度(4字节) + K1'_enc的数据
*/
let inputKey = new Uint8Array([
0x5b, 0x00, 0x00, 0x00, // ECC-P-256 公钥长度(X.509规范DER格式):91
// ECC-P-256 公钥
0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a,
0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0xa5, 0xb8, 0xa3, 0x78, 0x1d,
0x6d, 0x76, 0xe0, 0xb3, 0xf5, 0x6f, 0x43, 0x9d, 0xcf, 0x60, 0xf6, 0x0b, 0x3f, 0x64, 0x45, 0xa8,
0x3f, 0x1a, 0x96, 0xf1, 0xa1, 0xa4, 0x5d, 0x3e, 0x2c, 0x3f, 0x13, 0xd7, 0x81, 0xf7, 0x2a, 0xb5,
0x8d, 0x19, 0x3d, 0x9b, 0x96, 0xc7, 0x6a, 0x10, 0xf0, 0xaa, 0xbc, 0x91, 0x6f, 0x4d, 0xa7, 0x09,
0xb3, 0x57, 0x88, 0x19, 0x6f, 0x00, 0x4b, 0xad, 0xee, 0x34, 0x35,
0x10, 0x00, 0x00, 0x00, // AAD2长度:16
// AAD2
0x61, 0x62, 0x61, 0x62, 0x61, 0x62, 0x61, 0x62, 0x61, 0x62, 0x61, 0x62, 0x61, 0x62, 0x61, 0x00,
0x0c, 0x00, 0x00, 0x00, // Nonce2长度:16
// Nonce2
0x68, 0x61, 0x68, 0x61, 0x68, 0x61, 0x68, 0x61, 0x68, 0x61, 0x68, 0x00,
0x10, 0x00, 0x00, 0x00, // AEAD2长度:16
// AEAD2
0x85, 0xfe, 0xff, 0x5b, 0x47, 0x30, 0xbe, 0x10, 0xea, 0x3c, 0x30, 0x94, 0x8a, 0x99, 0xc4, 0x86,
0x20, 0x00, 0x00, 0x00, // K3密文长度:32
// K3密文
0xb4, 0xa9, 0x31, 0x5f, 0x28, 0x39, 0x53, 0x12, 0xa0, 0xfd, 0x8c, 0x9e, 0xfd, 0x36, 0xb8, 0xcb,
0x73, 0xb3, 0x08, 0xce, 0x16, 0xc9, 0x3b, 0xea, 0xd5, 0xca, 0x41, 0x85, 0xb8, 0x25, 0x7d, 0x1b,
0x10, 0x00, 0x00, 0x00, // AAD3长度:16
// AAD3
0x61, 0x62, 0x61, 0x62, 0x61, 0x62, 0x61, 0x62, 0x61, 0x62, 0x61, 0x62, 0x61, 0x62, 0x61, 0x00,
0x0c, 0x00, 0x00, 0x00, // Nonce3长度:16
// Nonce3
0x68, 0x61, 0x68, 0x61, 0x68, 0x61, 0x68, 0x61, 0x68, 0x61, 0x68, 0x00,
0x10, 0x00, 0x00, 0x00, // AEAD3长度:16
// AEAD3
0x23, 0xe2, 0xdb, 0xb5, 0x2e, 0xa7, 0xbb, 0x2d, 0xc5, 0x57, 0x05, 0xd8, 0x9d, 0x0e, 0xcf, 0x62,
0x04, 0x00, 0x00, 0x00, // “密钥明文材料长度”的长度(字节):4
// 密钥明文材料的长度:32字节
0x20, 0x00, 0x00, 0x00,
0x20, 0x00, 0x00, 0x00, // 待导入密钥密文长度(字节):32
// 待导入密钥密文
0xf4, 0x17, 0xbb, 0x90, 0x88, 0x62, 0x3d, 0x6e, 0xd8, 0x5f, 0x03, 0x51, 0x7f, 0xf5, 0x8b, 0x97,
0x8a, 0x41, 0x33, 0x64, 0xf5, 0x6f, 0x61, 0x16, 0xf9, 0x3c, 0x7a, 0x0b, 0xee, 0x3d, 0x92, 0xbb,
]);
importOptions.inData = inputKey;
/*
* 导入封装的加密密钥材料
*/
await publicImportWrappedKey(importAlias, wrapAlias, importOptions);
/*
* 删除用于加密导入的密钥
*/
await publicDeleteKeyFunc(wrapAlias, huksOptions);
}
调测验证
验证时查询密钥是否存在,如密钥存在即表示生成密钥成功。
代码示例:
import huks from '@ohos.security.huks';
/*
* 确定密钥别名和封装密钥属性参数集
*/
let keyAlias = 'importAlias';
let isKeyExist;
let keyProperties = new Array();
keyProperties[0] = {
tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
value: huks.HuksKeyAlg.HUKS_ALG_AES,
}
let huksOptions = {
properties: keyProperties, // 非空填充
inData: new Uint8Array(new Array()) // 非空填充
}
try {
huks.isKeyItemExist(keyAlias, huksOptions, function (error, data) {
if (error) {
console.error(`callback: isKeyItemExist failed, code: ${error.code}, msg: ${error.message}`);
} else {
if (data !== null && data.valueOf() !== null) {
isKeyExist = data.valueOf();
console.info(`callback: isKeyItemExist success, isKeyExist = ${isKeyExist}`);
}
}
});
} catch (error) {
console.error(`callback: isKeyItemExist input arg invalid, code: ${error.code}, msg: ${error.message}`);
}
常见密钥操作
场景概述
为了实现对数据机密性、完整性等保护,在生成/导入密钥后,需要对数据进行密钥操作,比如加密解密、签名验签、密钥协商、密钥派生等,本章节提供了常用的密钥操作的示例。本章节提供的示例都没有设置二次身份访问控制,如设置了密钥访问控制请参考密钥访问控制用法。
通用开发流程
HUKS基于密钥会话来操作数据,使用密钥时基于以下流程:
- 初始化密钥会话huks.initSession():传入密钥别名和密钥操作参数,初始化一个密钥会话并获取会话句柄。其中密钥操作参数中必须包含对应密码算法所必须的参数,包括密码算法、密钥大小、密钥目的、工作模式、填充模式、散列模式、IV、Nonce、AAD等。如果密钥设置了访问控制属性,还需要其他参数具体密钥访问控制。此步骤必选!
- 分段操作数据huks.updateSession():如数据过大(超过100K)或密码算法的要求需要对数据进行分段操作,反之可跳过此步。此步骤可选!
- 结束密钥会话huks.finishSession():操作最后一段数据并结束密钥会话,如过程中发生错误或不需要此次密钥操作数据,必须取消会话huks.abortSession()。此步骤必选!
加密解密
/*
* 以下以SM4 128密钥的Callback操作使用为例
*/
import huks from '@ohos.security.huks';
/*
* 确定密钥别名和封装密钥属性参数集
*/
let srcKeyAlias = 'sm4_Key';
let IV = '0000000000000000';
let cipherInData = 'Hks_SM4_Cipher_Test_101010101010101010110_string';
let encryptUpdateResult = new Array();
let handle;
let updateResult = new Array();
let finishOutData;
/* 集成生成密钥参数集 & 加密参数集 */
let properties = new Array();
properties[0] = {
tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
value: huks.HuksKeyAlg.HUKS_ALG_SM4,
}
properties[1] = {
tag: huks.HuksTag.HUKS_TAG_PURPOSE,
value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT | huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT,
}
properties[2] = {
tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
value: huks.HuksKeySize.HUKS_SM4_KEY_SIZE_128,
}
properties[3] = {
tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE,
value: huks.HuksCipherMode.HUKS_MODE_CBC,
}
properties[4] = {
tag: huks.HuksTag.HUKS_TAG_PADDING,
value: huks.HuksKeyPadding.HUKS_PADDING_NONE,
}
let huksOptions = {
properties: properties,
inData: new Uint8Array(new Array())
}
let propertiesEncrypt = new Array();
propertiesEncrypt[0] = {
tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
value: huks.HuksKeyAlg.HUKS_ALG_SM4,
}
propertiesEncrypt[1] = {
tag: huks.HuksTag.HUKS_TAG_PURPOSE,
value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT,
}
propertiesEncrypt[2] = {
tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
value: huks.HuksKeySize.HUKS_SM4_KEY_SIZE_128,
}
propertiesEncrypt[3] = {
tag: huks.HuksTag.HUKS_TAG_PADDING,
value: huks.HuksKeyPadding.HUKS_PADDING_NONE,
}
propertiesEncrypt[4] = {
tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE,
value: huks.HuksCipherMode.HUKS_MODE_CBC,
}
propertiesEncrypt[5] = {
tag: huks.HuksTag.HUKS_TAG_IV,
value: StringToUint8Array(IV),
}
let encryptOptions = {
properties: propertiesEncrypt,
inData: new Uint8Array(new Array())
}
/* 修改加密参数集为解密参数集 */
propertiesEncrypt.splice(1, 1, {
tag: huks.HuksTag.HUKS_TAG_PURPOSE,
value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT,
});
let decryptOptions = {
properties: propertiesEncrypt,
inData: new Uint8Array(new Array())
}
function StringToUint8Array(str) {
let arr = [];
for (let i = 0, j = str.length; i < j; ++i) {
arr.push(str.charCodeAt(i));
}
return new Uint8Array(arr);
}
function Uint8ArrayToString(fileData) {
let dataString = '';
for (let i = 0; i < fileData.length; i++) {
dataString += String.fromCharCode(fileData[i]);
}
return dataString;
}
function generateKeyItem(keyAlias:string, huksOptions:huks.HuksOptions, throwObject) {
return new Promise((resolve, reject) => {
try {
huks.generateKeyItem(keyAlias, huksOptions, function (error, data) {
if (error) {
reject(error);
} else {
resolve(data);
}
});
} catch (error) {
throwObject.isThrow = true;
throw(error);
}
});
}
async function publicGenKeyFunc(keyAlias:string, huksOptions:huks.HuksOptions) {
console.info(`enter callback generateKeyItem`);
let throwObject = {isThrow: false};
try {
await generateKeyItem(keyAlias, huksOptions, throwObject)
.then((data) => {
console.info(`callback: generateKeyItem success, data = ${JSON.stringify(data)}`);
})
.catch(error => {
if (throwObject.isThrow) {
throw(error);
} else {
console.error(`callback: generateKeyItem failed, code: ${error.code}, msg: ${error.message}`);
}
});
} catch (error) {
console.error(`callback: generateKeyItem input arg invalid, code: ${error.code}, msg: ${error.message}`);
}
}
function initSession(keyAlias:string, huksOptions:huks.HuksOptions, throwObject) : Promise<huks.HuksSessionHandle> {
return new Promise((resolve, reject) => {
try {
huks.initSession(keyAlias, huksOptions, function (error, data) {
if (error) {
reject(error);
} else {
resolve(data);
}
});
} catch (error) {
throwObject.isThrow = true;
throw(error);
}
});
}
async function publicInitFunc(keyAlias:string, huksOptions:huks.HuksOptions) {
console.info(`enter callback doInit`);
let throwObject = {isThrow: false};
try {
await initSession(keyAlias, huksOptions, throwObject)
.then ((data) => {
console.info(`callback: doInit success, data = ${JSON.stringify(data)}`);
handle = data.handle;
})
.catch((error) => {
if (throwObject.isThrow) {
throw(error);
} else {
console.error(`callback: doInit failed, code: ${error.code}, msg: ${error.message}`);
}
});
} catch (error) {
console.error(`callback: doInit input arg invalid, code: ${error.code}, msg: ${error.message}`);
}
}
function updateSession(handle:number, huksOptions:huks.HuksOptions, throwObject) : Promise<huks.HuksReturnResult> {
return new Promise((resolve, reject) => {
try {
huks.updateSession(handle, huksOptions, function (error, data) {
if (error) {
reject(error);
} else {
resolve(data);
}
});
} catch (error) {
throwObject.isThrow = true;
throw(error);
}
});
}
async function publicUpdateFunc(handle:number, huksOptions:huks.HuksOptions) {
console.info(`enter callback doUpdate`);
let throwObject = {isThrow: false};
try {
await updateSession(handle, huksOptions, throwObject)
.then ((data) => {
console.info(`callback: doUpdate success, data = ${JSON.stringify(data)}`);
})
.catch(error => {
if (throwObject.isThrow) {
throw(error);
} else {
console.error(`callback: doUpdate failed, code: ${error.code}, msg: ${error.message}`);
}
});
} catch (error) {
console.error(`callback: doUpdate input arg invalid, code: ${error.code}, msg: ${error.message}`);
}
}
function finishSession(handle:number, huksOptions:huks.HuksOptions, throwObject) : Promise<huks.HuksReturnResult> {
return new Promise((resolve, reject) => {
try {
huks.finishSession(handle, huksOptions, function (error, data) {
if (error) {
reject(error);
} else {
resolve(data);
}
});
} catch (error) {
throwObject.isThrow = true;
throw(error);
}
});
}
async function publicFinishFunc(handle:number, huksOptions:huks.HuksOptions) {
console.info(`enter callback doFinish`);
let throwObject = {isThrow: false};
try {
await finishSession(handle, huksOptions, throwObject)
.then ((data) => {
finishOutData = data.outData;
console.info(`callback: doFinish success, data = ${JSON.stringify(data)}`);
})
.catch(error => {
if (throwObject.isThrow) {
throw(error);
} else {
console.error(`callback: doFinish failed, code: ${error.code}, msg: ${error.message}`);
}
});
} catch (error) {
console.error(`callback: doFinish input arg invalid, code: ${error.code}, msg: ${error.message}`);
}
}
function deleteKeyItem(keyAlias:string, huksOptions:huks.HuksOptions, throwObject) {
return new Promise((resolve, reject) => {
try {
huks.deleteKeyItem(keyAlias, huksOptions, function (error, data) {
if (error) {
reject(error);
} else {
resolve(data);
}
});
} catch (error) {
throwObject.isThrow = true;
throw(error);
}
});
}
async function publicDeleteKeyFunc(keyAlias:string, huksOptions:huks.HuksOptions) {
console.info(`enter callback deleteKeyItem`);
let throwObject = {isThrow: false};
try {
await deleteKeyItem(keyAlias, huksOptions, throwObject)
.then ((data) => {
console.info(`callback: deleteKeyItem key success, data = ${JSON.stringify(data)}`);
})
.catch(error => {
if (throwObject.isThrow) {
throw(error);
} else {
console.error(`callback: deleteKeyItem failed, code: ${error.code}, msg: ${error.message}`);
}
});
} catch (error) {
console.error(`callback: deletKeeyItem input arg invalid, code: ${error.code}, msg: ${error.message}`);
}
}
async function testSm4Cipher() {
/* 生成密钥 */
await publicGenKeyFunc(srcKeyAlias, huksOptions);
/* 进行密钥加密操作 */
await publicInitFunc(srcKeyAlias, encryptOptions);
encryptOptions.inData = StringToUint8Array(cipherInData);
await publicUpdateFunc(handle, encryptOptions);
encryptUpdateResult = updateResult;
encryptOptions.inData = new Uint8Array(new Array());
await publicFinishFunc(handle, encryptOptions);
if (finishOutData === cipherInData) {
console.info('test finish encrypt err ');
} else {
console.info('test finish encrypt success');
}
/* 进行解密操作 */
await publicInitFunc(srcKeyAlias, decryptOptions);
decryptOptions.inData = new Uint8Array(encryptUpdateResult);
await publicUpdateFunc(handle, decryptOptions);
decryptOptions.inData = new Uint8Array(new Array());
await publicFinishFunc(handle, decryptOptions);
if (finishOutData === cipherInData) {
console.info('test finish decrypt success ');
} else {
console.info('test finish decrypt err');
}
await publicDeleteKeyFunc(srcKeyAlias, huksOptions);
}
签名验签
/*
* 以下以SM2密钥的Callback操作使用为例
*/
import huks from '@ohos.security.huks';
/*
* 确定密钥别名和封装密钥属性参数集
*/
let generateKeyAlias = 'sm2_Key';
let importKeyAlias = 'importKeyAlias';
let signVerifyInData = 'signVerifyInDataForTest';
let handle;
let exportKey;
let finishOutData;
/* 集成生成密钥参数集 */
let generateKeyProperties = new Array();
generateKeyProperties[0] = {
tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
value: huks.HuksKeyAlg.HUKS_ALG_SM2,
}
generateKeyProperties[1] = {
tag: huks.HuksTag.HUKS_TAG_PURPOSE,
value:
huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_SIGN |
huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_VERIFY,
}
generateKeyProperties[2] = {
tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
value: huks.HuksKeySize.HUKS_SM2_KEY_SIZE_256,
}
generateKeyProperties[3] = {
tag: huks.HuksTag.HUKS_TAG_DIGEST,
value: huks.HuksKeyDigest.HUKS_DIGEST_SM3,
}
let genrateKeyOptions = {
properties: generateKeyProperties,
inData: new Uint8Array(new Array())
}
/* 集成签名参数集 */
let signProperties = new Array();
signProperties[0] = {
tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
value: huks.HuksKeyAlg.HUKS_ALG_SM2,
}
signProperties[1] = {
tag: huks.HuksTag.HUKS_TAG_PURPOSE,
value:
huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_SIGN
}
signProperties[2] = {
tag: huks.HuksTag.HUKS_TAG_DIGEST,
value: huks.HuksKeyDigest.HUKS_DIGEST_SM3,
}
signProperties[3] = {
tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
value: huks.HuksKeySize.HUKS_SM2_KEY_SIZE_256,
}
let signOptions = {
properties: signProperties,
inData: new Uint8Array(new Array())
}
/* 集成验签参数集 */
let verifyProperties = new Array();
verifyProperties[0] = {
tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
value: huks.HuksKeyAlg.HUKS_ALG_SM2,
}
verifyProperties[1] = {
tag: huks.HuksTag.HUKS_TAG_PURPOSE,
value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_VERIFY
}
verifyProperties[2] = {
tag: huks.HuksTag.HUKS_TAG_DIGEST,
value: huks.HuksKeyDigest.HUKS_DIGEST_SM3,
}
verifyProperties[3] = {
tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
value: huks.HuksKeySize.HUKS_SM2_KEY_SIZE_256,
}
let verifyOptions = {
properties: verifyProperties,
inData: new Uint8Array(new Array())
}
function StringToUint8Array(str) {
let arr = [];
for (let i = 0, j = str.length; i < j; ++i) {
arr.push(str.charCodeAt(i));
}
return new Uint8Array(arr);
}
function generateKeyItem(keyAlias:string, huksOptions:huks.HuksOptions, throwObject) {
return new Promise((resolve, reject) => {
try {
huks.generateKeyItem(keyAlias, huksOptions, function (error, data) {
if (error) {
reject(error);
} else {
resolve(data);
}
});
} catch (error) {
throwObject.isThrow = true;
throw(error);
}
});
}
async function publicGenKeyFunc(keyAlias:string, huksOptions:huks.HuksOptions) {
console.info(`enter callback generateKeyItem`);
let throwObject = {isThrow: false};
try {
await generateKeyItem(keyAlias, huksOptions, throwObject)
.then((data) => {
console.info(`callback: generateKeyItem success, data = ${JSON.stringify(data)}`);
})
.catch(error => {
if (throwObject.isThrow) {
throw(error);
} else {
console.error(`callback: generateKeyItem failed, code: ${error.code}, msg: ${error.message}`);
}
});
} catch (error) {
console.error(`callback: generateKeyItem input arg invalid, code: ${error.code}, msg: ${error.message}`);
}
}
function initSession(keyAlias:string, huksOptions:huks.HuksOptions, throwObject) : Promise<huks.HuksSessionHandle> {
return new Promise((resolve, reject) => {
try {
huks.initSession(keyAlias, huksOptions, function (error, data) {
if (error) {
reject(error);
} else {
resolve(data);
}
});
} catch (error) {
throwObject.isThrow = true;
throw(error);
}
});
}
async function publicInitFunc(keyAlias:string, huksOptions:huks.HuksOptions) {
console.info(`enter callback doInit`);
let throwObject = {isThrow: false};
try {
await initSession(keyAlias, huksOptions, throwObject)
.then ((data) => {
console.info(`callback: doInit success, data = ${JSON.stringify(data)}`);
handle = data.handle;
})
.catch((error) => {
if (throwObject.isThrow) {
throw(error);
} else {
console.error(`callback: doInit failed, code: ${error.code}, msg: ${error.message}`);
}
});
} catch (error) {
console.error(`callback: doInit input arg invalid, code: ${error.code}, msg: ${error.message}`);
}
}
function updateSession(handle:number, huksOptions:huks.HuksOptions, throwObject) : Promise<huks.HuksReturnResult> {
return new Promise((resolve, reject) => {
try {
huks.updateSession(handle, huksOptions, function (error, data) {
if (error) {
reject(error);
} else {
resolve(data);
}
});
} catch (error) {
throwObject.isThrow = true;
throw(error);
}
});
}
async function publicUpdateFunc(handle:number, huksOptions:huks.HuksOptions) {
console.info(`enter callback doUpdate`);
let throwObject = {isThrow: false};
try {
await updateSession(handle, huksOptions, throwObject)
.then ((data) => {
console.info(`callback: doUpdate success, data = ${JSON.stringify(data)}`);
})
.catch(error => {
if (throwObject.isThrow) {
throw(error);
} else {
console.error(`callback: doUpdate failed, code: ${error.code}, msg: ${error.message}`);
}
});
} catch (error) {
console.error(`callback: doUpdate input arg invalid, code: ${error.code}, msg: ${error.message}`);
}
}
function finishSession(handle:number, huksOptions:huks.HuksOptions, throwObject) : Promise<huks.HuksReturnResult> {
return new Promise((resolve, reject) => {
try {
huks.finishSession(handle, huksOptions, function (error, data) {
if (error) {
reject(error);
} else {
resolve(data);
}
});
} catch (error) {
throwObject.isThrow = true;
throw(error);
}
});
}
async function publicFinishFunc(handle:number, huksOptions:huks.HuksOptions) {
console.info(`enter callback doFinish`);
let throwObject = {isThrow: false};
try {
await finishSession(handle, huksOptions, throwObject)
.then ((data) => {
finishOutData = data.outData;
console.info(`callback: doFinish success, data = ${JSON.stringify(data)}`);
})
.catch(error => {
if (throwObject.isThrow) {
throw(error);
} else {
console.error(`callback: doFinish failed, code: ${error.code}, msg: ${error.message}`);
}
});
} catch (error) {
console.error(`callback: doFinish input arg invalid, code: ${error.code}, msg: ${error.message}`);
}
}
function exportKeyItem(keyAlias:string, huksOptions:huks.HuksOptions, throwObject) : Promise<huks.HuksReturnResult> {
return new Promise((resolve, reject) => {
try {
huks.exportKeyItem(keyAlias, huksOptions, function (error, data) {
if (error) {
reject(error);
} else {
resolve(data);
}
});
} catch (error) {
throwObject.isThrow = true;
throw(error);
}
});
}
async function publicExportKeyFunc(keyAlias:string, huksOptions:huks.HuksOptions) {
console.info(`enter callback export`);
let throwObject = {isThrow: false};
try {
await exportKeyItem(keyAlias, huksOptions, throwObject)
.then ((data) => {
console.info(`callback: exportKeyItem success, data = ${JSON.stringify(data)}`);
exportKey = data.outData;
})
.catch(error => {
if (throwObject.isThrow) {
throw(error);
} else {
console.error(`callback: exportKeyItem failed, code: ${error.code}, msg: ${error.message}`);
}
});
} catch (error) {
console.error(`callback: exportKeyItem input arg invalid, code: ${error.code}, msg: ${error.message}`);
}
}
function importKeyItem(keyAlias:string, huksOptions:huks.HuksOptions, throwObject) {
return new Promise((resolve, reject) => {
try {
huks.importKeyItem(keyAlias, huksOptions, function (error, data) {
if (error) {
reject(error);
} else {
resolve(data);
}
});
} catch (error) {
throwObject.isThrow = true;
throw(error);
}
});
}
async function publicImportKeyFunc(keyAlias:string, huksOptions:huks.HuksOptions) {
console.info(`enter promise importKeyItem`);
let throwObject = {isThrow: false};
try {
await importKeyItem(keyAlias, huksOptions, throwObject)
.then ((data) => {
console.info(`callback: importKeyItem success, data = ${JSON.stringify(data)}`);
})
.catch(error => {
if (throwObject.isThrow) {
throw(error);
} else {
console.error(`callback: importKeyItem failed, code: ${error.code}, msg: ${error.message}`);
}
});
} catch (error) {
console.error(`callback: importKeyItem input arg invalid, code: ${error.code}, msg: ${error.message}`);
}
}
function deleteKeyItem(keyAlias:string, huksOptions:huks.HuksOptions, throwObject) {
return new Promise((resolve, reject) => {
try {
huks.deleteKeyItem(keyAlias, huksOptions, function (error, data) {
if (error) {
reject(error);
} else {
resolve(data);
}
});
} catch (error) {
throwObject.isThrow = true;
throw(error);
}
});
}
async function publicDeleteKeyFunc(keyAlias:string, huksOptions:huks.HuksOptions) {
console.info(`enter callback deleteKeyItem`);
let throwObject = {isThrow: false};
try {
await deleteKeyItem(keyAlias, huksOptions, throwObject)
.then ((data) => {
console.info(`callback: deleteKeyItem key success, data = ${JSON.stringify(data)}`);
})
.catch(error => {
if (throwObject.isThrow) {
throw(error);
} else {
console.error(`callback: deleteKeyItem failed, code: ${error.code}, msg: ${error.message}`);
}
});
} catch (error) {
console.error(`callback: deletKeeyItem input arg invalid, code: ${error.code}, msg: ${error.message}`);
}
}
async function testSm2SignVerify() {
/* 生成密钥 */
await publicGenKeyFunc(generateKeyAlias, genrateKeyOptions);
/* 签名 */
let signHandle;
let signFinishOutData;
await publicInitFunc(generateKeyAlias, signOptions);
signHandle = handle;
signOptions.inData = StringToUint8Array(signVerifyInData)
await publicUpdateFunc(signHandle, signOptions);
signOptions.inData = new Uint8Array(new Array());
await publicFinishFunc(signHandle, signOptions);
signFinishOutData = finishOutData;
/* 导出密钥 */
await publicExportKeyFunc(generateKeyAlias, genrateKeyOptions);
/* 导入密钥 */
verifyOptions.inData = exportKey;
await publicImportKeyFunc(importKeyAlias, verifyOptions);
/* 验证签名 */
let verifyHandle;
await publicInitFunc(importKeyAlias, verifyOptions);
verifyHandle = handle;
verifyOptions.inData = StringToUint8Array(signVerifyInData)
await publicUpdateFunc(verifyHandle, verifyOptions);
verifyOptions.inData = signFinishOutData;
await publicFinishFunc(verifyHandle, verifyOptions);
await publicDeleteKeyFunc(generateKeyAlias, genrateKeyOptions);
await publicDeleteKeyFunc(importKeyAlias, genrateKeyOptions);
}
密钥协商
/*
* 以下以X25519 256 TEMP密钥的Callback操作使用为例
*/
import huks from '@ohos.security.huks';
/*
* 确定密钥别名和封装密钥属性参数集
*/
let srcKeyAliasFirst = "AgreeX25519KeyFirstAlias";
let srcKeyAliasSecond = "AgreeX25519KeySecondAlias";
let agreeX25519InData = 'AgreeX25519TestIndata';
let finishOutData;
let handle;
let exportKey;
let exportKeyFrist;
let exportKeySecond;
/* 集成生成密钥参数集 */
let properties = new Array();
properties[0] = {
tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
value: huks.HuksKeyAlg.HUKS_ALG_X25519,
}
properties[1] = {
tag: huks.HuksTag.HUKS_TAG_PURPOSE,
value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_AGREE,
}
properties[2] = {
tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
value: huks.HuksKeySize.HUKS_CURVE25519_KEY_SIZE_256,
}
properties[3] = {
tag: huks.HuksTag.HUKS_TAG_DIGEST,
value: huks.HuksKeyDigest.HUKS_DIGEST_NONE,
}
properties[4] = {
tag: huks.HuksTag.HUKS_TAG_PADDING,
value: huks.HuksKeyPadding.HUKS_PADDING_NONE,
}
properties[5] = {
tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE,
value: huks.HuksCipherMode.HUKS_MODE_CBC,
}
let HuksOptions = {
properties: properties,
inData: new Uint8Array(new Array())
}
/* 集成第一个协商参数集 */
let finishProperties = new Array();
finishProperties[0] = {
tag: huks.HuksTag.HUKS_TAG_KEY_STORAGE_FLAG,
value: huks.HuksKeyStorageType.HUKS_STORAGE_TEMP,
}
finishProperties[1] = {
tag: huks.HuksTag.HUKS_TAG_IS_KEY_ALIAS,
value: true
}
finishProperties[2] = {
tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
value: huks.HuksKeyAlg.HUKS_ALG_AES,
}
finishProperties[3] = {
tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256,
}
finishProperties[4] = {
tag: huks.HuksTag.HUKS_TAG_PURPOSE,
value:
huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT |
huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT,
}
finishProperties[5] = {
tag: huks.HuksTag.HUKS_TAG_DIGEST,
value: huks.HuksKeyDigest.HUKS_DIGEST_NONE,
}
finishProperties[6] = {
tag: huks.HuksTag.HUKS_TAG_KEY_ALIAS,
value: StringToUint8Array(srcKeyAliasFirst+ 'final'),
}
finishProperties[7] = {
tag: huks.HuksTag.HUKS_TAG_PADDING,
value: huks.HuksKeyPadding.HUKS_PADDING_NONE,
}
finishProperties[8] = {
tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE,
value: huks.HuksCipherMode.HUKS_MODE_CBC,
}
let finishOptionsFrist = {
properties: finishProperties,
inData: StringToUint8Array(agreeX25519InData)
}
/* 集成第二个协商参数集 */
let finishOptionsSecond = {
properties: finishProperties,
inData: StringToUint8Array(agreeX25519InData)
}
finishOptionsSecond.properties.splice(6, 1, {
tag: huks.HuksTag.HUKS_TAG_KEY_ALIAS,
value: StringToUint8Array(srcKeyAliasSecond + 'final'),
})
function StringToUint8Array(str) {
let arr = [];
for (let i = 0, j = str.length; i < j; ++i) {
arr.push(str.charCodeAt(i));
}
return new Uint8Array(arr);
}
function generateKeyItem(keyAlias:string, huksOptions:huks.HuksOptions, throwObject) {
return new Promise((resolve, reject) => {
try {
huks.generateKeyItem(keyAlias, huksOptions, function (error, data) {
if (error) {
reject(error);
} else {
resolve(data);
}
});
} catch (error) {
throwObject.isThrow = true;
throw(error);
}
});
}
async function publicGenKeyFunc(keyAlias:string, huksOptions:huks.HuksOptions) {
console.info(`enter callback generateKeyItem`);
let throwObject = {isThrow: false};
try {
await generateKeyItem(keyAlias, huksOptions, throwObject)
.then((data) => {
console.info(`callback: generateKeyItem success, data = ${JSON.stringify(data)}`);
})
.catch(error => {
if (throwObject.isThrow) {
throw(error);
} else {
console.error(`callback: generateKeyItem failed, code: ${error.code}, msg: ${error.message}`);
}
});
} catch (error) {
console.error(`callback: generateKeyItem input arg invalid, code: ${error.code}, msg: ${error.message}`);
}
}
function initSession(keyAlias:string, huksOptions:huks.HuksOptions, throwObject) : Promise<huks.HuksSessionHandle> {
return new Promise((resolve, reject) => {
try {
huks.initSession(keyAlias, huksOptions, function (error, data) {
if (error) {
reject(error);
} else {
resolve(data);
}
});
} catch (error) {
throwObject.isThrow = true;
throw(error);
}
});
}
async function publicInitFunc(keyAlias:string, huksOptions:huks.HuksOptions) {
console.info(`enter callback doInit`);
let throwObject = {isThrow: false};
try {
await initSession(keyAlias, huksOptions, throwObject)
.then ((data) => {
console.info(`callback: doInit success, data = ${JSON.stringify(data)}`);
handle = data.handle;
})
.catch((error) => {
if (throwObject.isThrow) {
throw(error);
} else {
console.error(`callback: doInit failed, code: ${error.code}, msg: ${error.message}`);
}
});
} catch (error) {
console.error(`callback: doInit input arg invalid, code: ${error.code}, msg: ${error.message}`);
}
}
function updateSession(handle:number, huksOptions:huks.HuksOptions, throwObject) : Promise<huks.HuksReturnResult> {
return new Promise((resolve, reject) => {
try {
huks.updateSession(handle, huksOptions, function (error, data) {
if (error) {
reject(error);
} else {
resolve(data);
}
});
} catch (error) {
throwObject.isThrow = true;
throw(error);
}
});
}
async function publicUpdateFunc(handle:number, huksOptions:huks.HuksOptions) {
console.info(`enter callback doUpdate`);
let throwObject = {isThrow: false};
try {
await updateSession(handle, huksOptions, throwObject)
.then ((data) => {
console.info(`callback: doUpdate success, data = ${JSON.stringify(data)}`);
})
.catch(error => {
if (throwObject.isThrow) {
throw(error);
} else {
console.error(`callback: doUpdate failed, code: ${error.code}, msg: ${error.message}`);
}
});
} catch (error) {
console.error(`callback: doUpdate input arg invalid, code: ${error.code}, msg: ${error.message}`);
}
}
function finishSession(handle:number, huksOptions:huks.HuksOptions, throwObject) : Promise<huks.HuksReturnResult> {
return new Promise((resolve, reject) => {
try {
huks.finishSession(handle, huksOptions, function (error, data) {
if (error) {
reject(error);
} else {
resolve(data);
}
});
} catch (error) {
throwObject.isThrow = true;
throw(error);
}
});
}
async function publicFinishFunc(handle:number, huksOptions:huks.HuksOptions) {
console.info(`enter callback doFinish`);
let throwObject = {isThrow: false};
try {
await finishSession(handle, huksOptions, throwObject)
.then ((data) => {
finishOutData = data.outData;
console.info(`callback: doFinish success, data = ${JSON.stringify(data)}`);
})
.catch(error => {
if (throwObject.isThrow) {
throw(error);
} else {
console.error(`callback: doFinish failed, code: ${error.code}, msg: ${error.message}`);
}
});
} catch (error) {
console.error(`callback: doFinish input arg invalid, code: ${error.code}, msg: ${error.message}`);
}
}
function exportKeyItem(keyAlias:string, huksOptions:huks.HuksOptions, throwObject) : Promise<huks.HuksReturnResult> {
return new Promise((resolve, reject) => {
try {
huks.exportKeyItem(keyAlias, huksOptions, function (error, data) {
if (error) {
reject(error);
} else {
resolve(data);
}
});
} catch (error) {
throwObject.isThrow = true;
throw(error);
}
});
}
async function publicExportKeyFunc(keyAlias:string, huksOptions:huks.HuksOptions) {
console.info(`enter callback export`);
let throwObject = {isThrow: false};
try {
await exportKeyItem(keyAlias, huksOptions, throwObject)
.then ((data) => {
console.info(`callback: exportKeyItem success, data = ${JSON.stringify(data)}`);
exportKey = data.outData;
})
.catch(error => {
if (throwObject.isThrow) {
throw(error);
} else {
console.error(`callback: exportKeyItem failed, code: ${error.code}, msg: ${error.message}`);
}
});
} catch (error) {
console.error(`callback: exportKeyItem input arg invalid, code: ${error.code}, msg: ${error.message}`);
}
}
function deleteKeyItem(keyAlias:string, huksOptions:huks.HuksOptions, throwObject) {
return new Promise((resolve, reject) => {
try {
huks.deleteKeyItem(keyAlias, huksOptions, function (error, data) {
if (error) {
reject(error);
} else {
resolve(data);
}
});
} catch (error) {
throwObject.isThrow = true;
throw(error);
}
});
}
async function publicDeleteKeyFunc(keyAlias:string, huksOptions:huks.HuksOptions) {
console.info(`enter callback deleteKeyItem`);
let throwObject = {isThrow: false};
try {
await deleteKeyItem(keyAlias, huksOptions, throwObject)
.then ((data) => {
console.info(`callback: deleteKeyItem key success, data = ${JSON.stringify(data)}`);
})
.catch(error => {
if (throwObject.isThrow) {
throw(error);
} else {
console.error(`callback: deleteKeyItem failed, code: ${error.code}, msg: ${error.message}`);
}
});
} catch (error) {
console.error(`callback: deletKeeyItem input arg invalid, code: ${error.code}, msg: ${error.message}`);
}
}
async function testAgree() {
/* 1.生成两个密钥并导出 */
await publicGenKeyFunc(srcKeyAliasFirst, HuksOptions);
await publicGenKeyFunc(srcKeyAliasSecond, HuksOptions);
await publicExportKeyFunc(srcKeyAliasFirst, HuksOptions);
exportKeyFrist = exportKey;
await publicExportKeyFunc(srcKeyAliasFirst, HuksOptions);
exportKeySecond = exportKey;
/* 对第一个密钥进行协商 */
await publicInitFunc(srcKeyAliasFirst, HuksOptions);
HuksOptions.inData = exportKeySecond;
await publicUpdateFunc(handle, HuksOptions);
await publicFinishFunc(handle, finishOptionsFrist);
/* 对第二个密钥进行协商 */
await publicInitFunc(srcKeyAliasSecond, HuksOptions);
HuksOptions.inData = exportKeyFrist;
await publicUpdateFunc(handle, HuksOptions);
await publicFinishFunc(handle, finishOptionsSecond);
await publicDeleteKeyFunc(srcKeyAliasFirst, HuksOptions);
await publicDeleteKeyFunc(srcKeyAliasSecond, HuksOptions);
}
密钥派生
/*
* 以下以PBKDF2密钥的Promise操作使用为例
*/
import huks from '@ohos.security.huks';
/*
* 确定密钥别名和封装密钥属性参数集
*/
let srcKeyAlias = "pbkdf2_Key";
let deriveHkdfInData = "derivePbkdf2TestIndata";
let handle;
let finishOutData;
let HuksKeyDeriveKeySize = 32;
let salt = '0000000000000000';
/* 集成生成密钥参数集 */
let properties = new Array();
properties[0] = {
tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
value: huks.HuksKeyAlg.HUKS_ALG_AES,
}
properties[1] = {
tag: huks.HuksTag.HUKS_TAG_PURPOSE,
value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DERIVE,
}
properties[2] = {
tag: huks.HuksTag.HUKS_TAG_DIGEST,
value: huks.HuksKeyDigest.HUKS_DIGEST_SHA256,
}
properties[3] = {
tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256,
}
let huksOptions = {
properties: properties,
inData: new Uint8Array(new Array())
}
/* 集成init时密钥参数集 */
let initProperties = new Array();
initProperties[0] = {
tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
value: huks.HuksKeyAlg.HUKS_ALG_PBKDF2,
}
initProperties[1] = {
tag: huks.HuksTag.HUKS_TAG_PURPOSE,
value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DERIVE,
}
initProperties[2] = {
tag: huks.HuksTag.HUKS_TAG_DIGEST,
value: huks.HuksKeyDigest.HUKS_DIGEST_SHA256,
}
initProperties[3] = {
tag: huks.HuksTag.HUKS_TAG_DERIVE_KEY_SIZE,
value: HuksKeyDeriveKeySize,
}
initProperties[4] = {
tag: huks.HuksTag.HUKS_TAG_ITERATION,
value: 1000,
}
initProperties[5] = {
tag: huks.HuksTag.HUKS_TAG_SALT,
value: StringToUint8Array(salt),
}
let initOptions = {
properties: initProperties,
inData: new Uint8Array(new Array())
}
/* 集成finish时密钥参数集 */
let finishProperties = new Array();
finishProperties[0] = {
tag: huks.HuksTag.HUKS_TAG_KEY_STORAGE_FLAG,
value: huks.HuksKeyStorageType.HUKS_STORAGE_PERSISTENT,
}
finishProperties[1] = {
tag: huks.HuksTag.HUKS_TAG_IS_KEY_ALIAS,
value: true,
}
finishProperties[2] = {
tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
value: huks.HuksKeyAlg.HUKS_ALG_AES,
}
finishProperties[3] = {
tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256,
}
finishProperties[4] = {
tag: huks.HuksTag.HUKS_TAG_PURPOSE,
value:
huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT |
huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT,
}
finishProperties[5] = {
tag: huks.HuksTag.HUKS_TAG_DIGEST,
value: huks.HuksKeyDigest.HUKS_DIGEST_NONE,
}
finishProperties[6] = {
tag: huks.HuksTag.HUKS_TAG_KEY_ALIAS,
value: StringToUint8Array(srcKeyAlias),
}
finishProperties[7] = {
tag: huks.HuksTag.HUKS_TAG_PADDING,
value: huks.HuksKeyPadding.HUKS_PADDING_NONE,
}
finishProperties[8] = {
tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE,
value: huks.HuksCipherMode.HUKS_MODE_CBC,
}
let finishOptions = {
properties: finishProperties,
inData: new Uint8Array(new Array())
}
function StringToUint8Array(str) {
let arr = [];
for (let i = 0, j = str.length; i < j; ++i) {
arr.push(str.charCodeAt(i));
}
return new Uint8Array(arr);
}
function generateKeyItem(keyAlias:string, huksOptions:huks.HuksOptions, throwObject) {
return new Promise((resolve, reject) => {
try {
huks.generateKeyItem(keyAlias, huksOptions, function (error, data) {
if (error) {
reject(error);
} else {
resolve(data);
}
});
} catch (error) {
throwObject.isThrow = true;
throw(error);
}
});
}
async function publicGenKeyFunc(keyAlias:string, huksOptions:huks.HuksOptions) {
console.info(`enter callback generateKeyItem`);
let throwObject = {isThrow: false};
try {
await generateKeyItem(keyAlias, huksOptions, throwObject)
.then((data) => {
console.info(`callback: generateKeyItem success, data = ${JSON.stringify(data)}`);
})
.catch(error => {
if (throwObject.isThrow) {
throw(error);
} else {
console.error(`callback: generateKeyItem failed, code: ${error.code}, msg: ${error.message}`);
}
});
} catch (error) {
console.error(`callback: generateKeyItem input arg invalid, code: ${error.code}, msg: ${error.message}`);
}
}
function initSession(keyAlias:string, huksOptions:huks.HuksOptions, throwObject) : Promise<huks.HuksSessionHandle> {
return new Promise((resolve, reject) => {
try {
huks.initSession(keyAlias, huksOptions, function (error, data) {
if (error) {
reject(error);
} else {
resolve(data);
}
});
} catch (error) {
throwObject.isThrow = true;
throw(error);
}
});
}
async function publicInitFunc(keyAlias:string, huksOptions:huks.HuksOptions) {
console.info(`enter callback doInit`);
let throwObject = {isThrow: false};
try {
await initSession(keyAlias, huksOptions, throwObject)
.then ((data) => {
console.info(`callback: doInit success, data = ${JSON.stringify(data)}`);
handle = data.handle;
})
.catch((error) => {
if (throwObject.isThrow) {
throw(error);
} else {
console.error(`callback: doInit failed, code: ${error.code}, msg: ${error.message}`);
}
});
} catch (error) {
console.error(`callback: doInit input arg invalid, code: ${error.code}, msg: ${error.message}`);
}
}
function updateSession(handle:number, huksOptions:huks.HuksOptions, throwObject) : Promise<huks.HuksReturnResult> {
return new Promise((resolve, reject) => {
try {
huks.updateSession(handle, huksOptions, function (error, data) {
if (error) {
reject(error);
} else {
resolve(data);
}
});
} catch (error) {
throwObject.isThrow = true;
throw(error);
}
});
}
async function publicUpdateFunc(handle:number, huksOptions:huks.HuksOptions) {
console.info(`enter callback doUpdate`);
let throwObject = {isThrow: false};
try {
await updateSession(handle, huksOptions, throwObject)
.then ((data) => {
console.info(`callback: doUpdate success, data = ${JSON.stringify(data)}`);
})
.catch(error => {
if (throwObject.isThrow) {
throw(error);
} else {
console.error(`callback: doUpdate failed, code: ${error.code}, msg: ${error.message}`);
}
});
} catch (error) {
console.error(`callback: doUpdate input arg invalid, code: ${error.code}, msg: ${error.message}`);
}
}
function finishSession(handle:number, huksOptions:huks.HuksOptions, throwObject) : Promise<huks.HuksReturnResult> {
return new Promise((resolve, reject) => {
try {
huks.finishSession(handle, huksOptions, function (error, data) {
if (error) {
reject(error);
} else {
resolve(data);
}
});
} catch (error) {
throwObject.isThrow = true;
throw(error);
}
});
}
async function publicFinishFunc(handle:number, huksOptions:huks.HuksOptions) {
console.info(`enter callback doFinish`);
let throwObject = {isThrow: false};
try {
await finishSession(handle, huksOptions, throwObject)
.then ((data) => {
finishOutData = data.outData;
console.info(`callback: doFinish success, data = ${JSON.stringify(data)}`);
})
.catch(error => {
if (throwObject.isThrow) {
throw(error);
} else {
console.error(`callback: doFinish failed, code: ${error.code}, msg: ${error.message}`);
}
});
} catch (error) {
console.error(`callback: doFinish input arg invalid, code: ${error.code}, msg: ${error.message}`);
}
}
function deleteKeyItem(keyAlias:string, huksOptions:huks.HuksOptions, throwObject) {
return new Promise((resolve, reject) => {
try {
huks.deleteKeyItem(keyAlias, huksOptions, function (error, data) {
if (error) {
reject(error);
} else {
resolve(data);
}
});
} catch (error) {
throwObject.isThrow = true;
throw(error);
}
});
}
async function publicDeleteKeyFunc(keyAlias:string, huksOptions:huks.HuksOptions) {
console.info(`enter callback deleteKeyItem`);
let throwObject = {isThrow: false};
try {
await deleteKeyItem(keyAlias, huksOptions, throwObject)
.then ((data) => {
console.info(`callback: deleteKeyItem key success, data = ${JSON.stringify(data)}`);
})
.catch(error => {
if (throwObject.isThrow) {
throw(error);
} else {
console.error(`callback: deleteKeyItem failed, code: ${error.code}, msg: ${error.message}`);
}
});
} catch (error) {
console.error(`callback: deletKeeyItem input arg invalid, code: ${error.code}, msg: ${error.message}`);
}
}
async function testDerive() {
/* 生成密钥 */
await publicGenKeyFunc(srcKeyAlias, huksOptions);
/* 进行派生操作 */
await publicInitFunc(srcKeyAlias, initOptions);
initOptions.inData = StringToUint8Array(deriveHkdfInData);
await publicUpdateFunc(handle, initOptions);
await publicFinishFunc(handle, finishOptions);
await publicDeleteKeyFunc(srcKeyAlias, huksOptions);
}