密鑰協商(ArkTS)
以協商密鑰類型為X25519 256,并密鑰僅在HUKS內使用為例,完成密鑰協商。
開發步驟
生成密鑰
設備A、設備B各自生成一個非對稱密鑰,具體請參考[密鑰生成]或[密鑰導入]。
密鑰生成時,可指定參數HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG(可選),用于標識基于該密鑰協商出的密鑰是否由HUKS管理。
- 當TAG設置為HUKS_STORAGE_ONLY_USED_IN_HUKS時,表示基于該密鑰協商出的密鑰,由HUKS管理,可保證協商密鑰全生命周期不出安全環境。
- 當TAG設置為HUKS_STORAGE_KEY_EXPORT_ALLOWED時,表示基于該密鑰協商出的密鑰,返回給調用方管理,由業務自行保證密鑰安全。
- 若業務未設置TAG的具體值,表示基于該密鑰協商出的密鑰,即可由HUKS管理,也可返回給調用方管理,業務可在后續協商時再選擇使用何種方式保護密鑰。
- 開發前請熟悉鴻蒙開發指導文檔 :[
gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md
]
導出密鑰
設備A、B導出非對稱密鑰對的公鑰材料。
密鑰協商
設備A、B分別基于本端私鑰和對端設備的公鑰,協商出共享密鑰。
密鑰協商時,可指定參數HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG(可選),用于標識協商得到的密鑰是否由HUKS管理。
生成 | 協商 | 規格 |
---|---|---|
HUKS_STORAGE_ONLY_USED_IN_HUKS | HUKS_STORAGE_ONLY_USED_IN_HUKS | 密鑰由HUKS管理 |
HUKS_STORAGE_KEY_EXPORT_ALLOWED | HUKS_STORAGE_KEY_EXPORT_ALLOWED | 密鑰返回給調用方管理 |
未指定TAG具體值 | HUKS_STORAGE_ONLY_USED_IN_HUKS | 密鑰由HUKS管理 |
未指定TAG具體值 | HUKS_STORAGE_KEY_EXPORT_ALLOWED | 密鑰返回給調用方管理 |
未指定TAG具體值HarmonyOS與OpenHarmony鴻蒙文檔籽料:mau123789是v直接拿 | 未指定TAG具體值 | 密鑰返回給調用方管理 |
注:協商時指定的TAG值,不可與生成時指定的TAG值沖突。表格中僅列舉有效的指定方式。
刪除密鑰
當密鑰廢棄不用時,設備A、B均需要刪除密鑰。
下面分別以X25519 與 DH密鑰為例,進行協商。
/*
*以下以X25519 256密鑰的Promise操作使用為例
*/
import { huks } from '@kit.UniversalKeystoreKit';
/*
* 確定密鑰別名和封裝密鑰屬性參數集
*/
let srcKeyAliasFirst = "AgreeX25519KeyFirstAlias";
let srcKeyAliasSecond = "AgreeX25519KeySecondAlias";
let agreeX25519InData = 'AgreeX25519TestIndata';
let finishOutData: Uint8Array;
let handle: number;
let exportKey: Uint8Array;
let exportKeyFirst: Uint8Array;
let exportKeySecond: Uint8Array;
/* 集成生成密鑰參數集 */
let properties: Array< huks.HuksParam > = [{
tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
value: huks.HuksKeyAlg.HUKS_ALG_X25519,
}, {
tag: huks.HuksTag.HUKS_TAG_PURPOSE,
value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_AGREE,
}, {
tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
value: huks.HuksKeySize.HUKS_CURVE25519_KEY_SIZE_256,
}, {
tag: huks.HuksTag.HUKS_TAG_DIGEST,
value: huks.HuksKeyDigest.HUKS_DIGEST_NONE,
}, {
tag: huks.HuksTag.HUKS_TAG_PADDING,
value: huks.HuksKeyPadding.HUKS_PADDING_NONE,
}, {
tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE,
value: huks.HuksCipherMode.HUKS_MODE_CBC,
}, {
tag: huks.HuksTag.HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG,
value: huks.HuksKeyStorageType.HUKS_STORAGE_ONLY_USED_IN_HUKS,
}];
let HuksOptions: huks.HuksOptions = {
properties: properties,
inData: new Uint8Array(new Array())
}
/* 集成第一個協商參數集 */
const finishProperties: Array< huks.HuksParam > = [{
tag: huks.HuksTag.HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG,
value: huks.HuksKeyStorageType.HUKS_STORAGE_ONLY_USED_IN_HUKS,
}, {
tag: huks.HuksTag.HUKS_TAG_IS_KEY_ALIAS,
value: true
}, {
tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
value: huks.HuksKeyAlg.HUKS_ALG_AES,
}, {
tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256,
}, {
tag: huks.HuksTag.HUKS_TAG_PURPOSE,
value:
huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT |
huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT,
}, {
tag: huks.HuksTag.HUKS_TAG_DIGEST,
value: huks.HuksKeyDigest.HUKS_DIGEST_NONE,
}, {
tag: huks.HuksTag.HUKS_TAG_PADDING,
value: huks.HuksKeyPadding.HUKS_PADDING_NONE,
}, {
tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE,
value: huks.HuksCipherMode.HUKS_MODE_ECB,
}];
let finishOptionsFirst: huks.HuksOptions = {
properties: [
...finishProperties, {
tag: huks.HuksTag.HUKS_TAG_KEY_ALIAS,
value: StringToUint8Array(srcKeyAliasFirst + 'final'),
}],
inData: StringToUint8Array(agreeX25519InData)
}
/* 集成第二個協商參數集 */
let finishOptionsSecond: huks.HuksOptions = {
properties: [
...finishProperties, {
tag: huks.HuksTag.HUKS_TAG_KEY_ALIAS,
value: StringToUint8Array(srcKeyAliasSecond + 'final'),
}],
inData: StringToUint8Array(agreeX25519InData)
}
function StringToUint8Array(str: string) {
let arr: number[] = new Array();
for (let i = 0, j = str.length; i < j; ++i) {
arr.push(str.charCodeAt(i));
}
return new Uint8Array(arr);
}
class throwObject {
isThrow: boolean = false
}
/* 生成密鑰 */
function generateKeyItem(keyAlias: string, huksOptions: huks.HuksOptions, throwObject: throwObject) {
return new Promise< void >((resolve, reject) = > {
try {
huks.generateKeyItem(keyAlias, huksOptions, (error, data) = > {
if (error) {
reject(error);
} else {
resolve(data);
}
});
} catch (error) {
throwObject.isThrow = true;
throw (error as Error);
}
});
}
/* 調用generateKeyItem生成密鑰 */
async function publicGenKeyFunc(keyAlias: string, huksOptions: huks.HuksOptions) {
console.info(`enter promise generateKeyItem`);
let throwObject: throwObject = { isThrow: false };
try {
await generateKeyItem(keyAlias, huksOptions, throwObject)
.then((data) = > {
console.info(`promise: generateKeyItem success, data = ${JSON.stringify(data)}`);
})
.catch((error: Error) = > {
if (throwObject.isThrow) {
throw (error as Error);
} else {
console.error(`promise: generateKeyItem failed, ${JSON.stringify(error)}`);
}
});
} catch (error) {
console.error(`promise: generateKeyItem input arg invalid, ${JSON.stringify(error)}`);
}
}
/*初始化密鑰會話接口,并獲取一個句柄(必選)和挑戰值(可選)*/
function initSession(keyAlias: string, huksOptions: huks.HuksOptions, throwObject: throwObject) {
return new Promise< huks.HuksSessionHandle >((resolve, reject) = > {
try {
huks.initSession(keyAlias, huksOptions, (error, data) = > {
if (error) {
reject(error);
} else {
resolve(data);
}
});
} catch (error) {
throwObject.isThrow = true;
throw (error as Error);
}
});
}
/*調用initSession獲取handle*/
async function publicInitFunc(keyAlias: string, huksOptions: huks.HuksOptions) {
console.info(`enter promise doInit`);
let throwObject: throwObject = { isThrow: false };
try {
await initSession(keyAlias, huksOptions, throwObject)
.then((data) = > {
console.info(`promise: doInit success, data = ${JSON.stringify(data)}`);
handle = data.handle;
})
.catch((error: Error) = > {
if (throwObject.isThrow) {
throw (error as Error);
} else {
console.error(`promise: doInit failed, ${JSON.stringify(error)}`);
}
});
} catch (error) {
console.error(`promise: doInit input arg invalid, ${JSON.stringify(error)}`);
}
}
/* 分段添加密鑰操作的數據并進行相應的密鑰操作,輸出處理數據 */
function updateSession(handle: number, huksOptions: huks.HuksOptions, throwObject: throwObject) {
return new Promise< huks.HuksReturnResult >((resolve, reject) = > {
try {
huks.updateSession(handle, huksOptions, (error, data) = > {
if (error) {
reject(error);
} else {
resolve(data);
}
});
} catch (error) {
throwObject.isThrow = true;
throw (error as Error);
}
});
}
/* 調用updateSession進行協商操作 */
async function publicUpdateFunc(handle: number, huksOptions: huks.HuksOptions) {
console.info(`enter promise doUpdate`);
let throwObject: throwObject = { isThrow: false };
try {
await updateSession(handle, huksOptions, throwObject)
.then((data) = > {
console.info(`promise: doUpdate success, data = ${JSON.stringify(data)}`);
})
.catch((error: Error) = > {
if (throwObject.isThrow) {
throw (error as Error);
} else {
console.error(`promise: doUpdate failed, ${JSON.stringify(error)}`);
}
});
} catch (error) {
console.error(`promise: doUpdate input arg invalid, ${JSON.stringify(error)}`);
}
}
/* 結束密鑰會話并進行相應的密鑰操作,輸出處理數據 */
function finishSession(handle: number, huksOptions: huks.HuksOptions, throwObject: throwObject) {
return new Promise< huks.HuksReturnResult >((resolve, reject) = > {
try {
huks.finishSession(handle, huksOptions, (error, data) = > {
if (error) {
reject(error);
} else {
resolve(data);
}
});
} catch (error) {
throwObject.isThrow = true;
throw (error as Error);
}
});
}
/* 調用finishSession結束操作 */
async function publicFinishFunc(handle: number, huksOptions: huks.HuksOptions) {
console.info(`enter promise doFinish`);
let throwObject: throwObject = { isThrow: false };
try {
await finishSession(handle, huksOptions, throwObject)
.then((data) = > {
finishOutData = data.outData as Uint8Array;
console.info(`promise: doFinish success, data = ${JSON.stringify(data)}`);
})
.catch((error: Error) = > {
if (throwObject.isThrow) {
throw (error as Error);
} else {
console.error(`promise: doFinish failed, ${JSON.stringify(error)}`);
}
});
} catch (error) {
console.error(`promise: doFinish input arg invalid, ${JSON.stringify(error)}`);
}
}
/* 導出密鑰 */
function exportKeyItem(keyAlias: string, huksOptions: huks.HuksOptions, throwObject: throwObject) {
return new Promise< huks.HuksReturnResult >((resolve, reject) = > {
try {
huks.exportKeyItem(keyAlias, huksOptions, (error, data) = > {
if (error) {
reject(error);
} else {
resolve(data);
}
});
} catch (error) {
throwObject.isThrow = true;
throw (error as Error);
}
});
}
/* 調用exportKeyItem導出公鑰操作 */
async function publicExportKeyFunc(keyAlias: string, huksOptions: huks.HuksOptions) {
console.info(`enter promise export`);
let throwObject: throwObject = { isThrow: false };
try {
await exportKeyItem(keyAlias, huksOptions, throwObject)
.then((data) = > {
console.info(`promise: exportKeyItem success, data = ${JSON.stringify(data)}`);
exportKey = data.outData as Uint8Array;
})
.catch((error: Error) = > {
if (throwObject.isThrow) {
throw (error as Error);
} else {
console.error(`promise: exportKeyItem failed, ${JSON.stringify(error)}`);
}
});
} catch (error) {
console.error(`promise: exportKeyItem input arg invalid, ${JSON.stringify(error)}`);
}
}
/* 刪除密鑰操作 */
function deleteKeyItem(keyAlias: string, huksOptions: huks.HuksOptions, throwObject: throwObject) {
return new Promise< void >((resolve, reject) = > {
try {
huks.deleteKeyItem(keyAlias, huksOptions, (error, data) = > {
if (error) {
reject(error);
} else {
resolve(data);
}
});
} catch (error) {
throwObject.isThrow = true;
throw (error as Error);
}
});
}
/* 調用deleteKeyItem刪除密鑰操作 */
async function publicDeleteKeyFunc(keyAlias: string, huksOptions: huks.HuksOptions) {
console.info(`enter promise deleteKeyItem`);
let throwObject: throwObject = { isThrow: false };
try {
await deleteKeyItem(keyAlias, huksOptions, throwObject)
.then((data) = > {
console.info(`promise: deleteKeyItem key success, data = ${JSON.stringify(data)}`);
})
.catch((error: Error) = > {
if (throwObject.isThrow) {
throw (error as Error);
} else {
console.error(`promise: deleteKeyItem failed, ${JSON.stringify(error)}`);
}
});
} catch (error) {
console.error(`promise: deleteKeyItem input arg invalid, ${JSON.stringify(error)}`);
}
}
async function testAgree() {
/* 1.確定密鑰別名并集成并集成要參數集 A設備:srcKeyAliasFirst B設備:srcKeyAliasSecond*/
/* 2.設備A生成密鑰 */
await publicGenKeyFunc(srcKeyAliasFirst, HuksOptions);
/* 3.設備B生成密鑰 */
await publicGenKeyFunc(srcKeyAliasSecond, HuksOptions);
/* 4.設備A、B導出非對稱密鑰的公鑰 */
await publicExportKeyFunc(srcKeyAliasFirst, HuksOptions);
exportKeyFirst = exportKey;
await publicExportKeyFunc(srcKeyAliasSecond, HuksOptions);
exportKeySecond = exportKey;
/* 5.對第一個密鑰進行協商(三段式)*/
await publicInitFunc(srcKeyAliasFirst, HuksOptions);
HuksOptions.inData = exportKeySecond;
await publicUpdateFunc(handle, HuksOptions);
await publicFinishFunc(handle, finishOptionsFirst);
/* 5.對第二個密鑰進行協商(三段式) */
await publicInitFunc(srcKeyAliasSecond, HuksOptions);
HuksOptions.inData = exportKeyFirst;
await publicUpdateFunc(handle, HuksOptions);
await publicFinishFunc(handle, finishOptionsSecond);
/* 6.設備A、B刪除密鑰 */
await publicDeleteKeyFunc(srcKeyAliasFirst, HuksOptions);
await publicDeleteKeyFunc(srcKeyAliasSecond, HuksOptions);
}
下面以DH密鑰協商為例
/*
*以下以 DH密鑰的Promise操作使用為例
*/
import { huks } from '@kit.UniversalKeystoreKit'
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)
}
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
}
const dhAgree: Array< huks.HuksParam > = [{
tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
value: huks.HuksKeyAlg.HUKS_ALG_DH,
}, {
tag: huks.HuksTag.HUKS_TAG_PURPOSE,
value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_AGREE,
}]
const dh2048Agree: Array< huks.HuksParam > = [
...dhAgree, {
tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
value: huks.HuksKeySize.HUKS_DH_KEY_SIZE_2048,
}]
const dhGenOptions: huks.HuksOptions = {
properties: dh2048Agree,
inData: new Uint8Array([])
}
const emptyOptions: huks.HuksOptions = {
properties: [],
inData: new Uint8Array([])
}
async function HuksDhAgreeExportKey(keyAlias: string,
peerPubKey: huks.HuksReturnResult): Promise< huks.HuksReturnResult > {
const initHandle = await huks.initSession(keyAlias, dhGenOptions)
const dhAgreeUpdateBobPubKey: huks.HuksOptions = {
properties: [
...dh2048Agree, {
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, dhAgreeUpdateBobPubKey)
return await huks.finishSession(initHandle.handle, emptyOptions)
}
async function HuksDhAgreeExportTest(
aliasA: string, aliasB: string,
pubKeyA: huks.HuksReturnResult, pubKeyB: huks.HuksReturnResult) {
const agreedKeyFromAlice = await HuksDhAgreeExportKey(aliasA, pubKeyB)
console.info(`ok! agreedKeyFromAlice export is 0x${Uint8ArrayToBigInt(agreedKeyFromAlice.outData).toString(16)}`)
const agreedKeyFromBob = await HuksDhAgreeExportKey(aliasB, pubKeyA)
console.info(`ok! agreedKeyFromBob export is 0x${Uint8ArrayToBigInt(agreedKeyFromBob.outData).toString(16)}`)
}
async function HuksDhAgreeInHuks(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,
}, {
tag: huks.HuksTag.HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG,
value: huks.HuksKeyStorageType.HUKS_STORAGE_ONLY_USED_IN_HUKS,
}]
const dhAgreeInit: huks.HuksOptions = {
properties: [
...dhAgree,
{ tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256, },
...onlyUsedInHuks],
inData: new Uint8Array([])
}
const dhAgreeFinishParams: 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_AES },
{ tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256 },
{
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, dhAgreeInit)
const dhAgreeUpdatePubKey: huks.HuksOptions = {
properties: [...dhAgree, ...onlyUsedInHuks],
inData: peerPubKey.outData
}
await huks.updateSession(handle.handle, dhAgreeUpdatePubKey)
const dhAgreeAliceFinnish: huks.HuksOptions = {
properties: [...dhAgreeFinishParams, {
tag: huks.HuksTag.HUKS_TAG_KEY_ALIAS, value: StringToUint8Array(aliasAgreedKey)
}], inData: new Uint8Array([])
}
return await huks.finishSession(handle.handle, dhAgreeAliceFinnish)
}
async function HuksDhAgreeInHuksTest(
aliasA: string, aliasB: string,
pubKeyA: huks.HuksReturnResult, pubKeyB: huks.HuksReturnResult,
aliasAgreedKeyFromA: string, aliasAgreedKeyFromB: string) {
const finishAliceResult = await HuksDhAgreeInHuks(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 HuksDhAgreeInHuks(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)
}
export default async function HuksDhAgreeTest() {
const aliasAlice = 'alice'
const aliasBob = 'bob'
/* 調用generateKeyItem生成別名為alice與bob的兩個密鑰 */
await huks.generateKeyItem(aliasAlice, dhGenOptions)
await huks.generateKeyItem(aliasBob, dhGenOptions)
/* 導出非對稱密鑰alice與bob的的公鑰 */
const pubKeyAlice = await huks.exportKeyItem(aliasAlice, emptyOptions)
const pubKeyBob = await huks.exportKeyItem(aliasBob, emptyOptions)
/* 開始協商,協商生成的密鑰返回給業務管理 */
await HuksDhAgreeExportTest(aliasAlice, aliasBob, pubKeyAlice, pubKeyBob)
/* 開始協商,協商生成的密鑰由HUKS管理 */
await HuksDhAgreeInHuksTest(aliasAlice, aliasBob, pubKeyAlice, pubKeyBob, 'agreedKeyFromAlice', 'agreedKeyFromBob')
await huks.deleteKeyItem(aliasAlice, emptyOptions)
await huks.deleteKeyItem(aliasBob, emptyOptions)
}
審核編輯 黃宇
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。
舉報投訴
-
鴻蒙
+關注
關注
57文章
2339瀏覽量
42811
發布評論請先 登錄
相關推薦
鴻蒙開發:Universal Keystore Kit密鑰管理服務 密鑰導入介紹及算法規格
如果業務在HUKS外部生成密鑰(比如應用間協商生成、服務器端生成),業務可以將密鑰導入到HUKS中由HUKS進行管理。
鴻蒙開發:Universal Keystore Kit 密鑰管理服務 密鑰協商 C、C++
以協商密鑰類型為ECDH,并密鑰僅在HUKS內使用為例,完成密鑰協商。具體的場景介紹及支持的算法規格,請參考[
鴻蒙開發:Universal Keystore Kit 密鑰管理服務 HMAC ArkTS
HMAC是密鑰相關的哈希運算消息認證碼(Hash-based Message Authentication Code),是一種基于Hash函數和密鑰進行消息認證的方法。
鴻蒙開發:Universal Keystore Kit密鑰管理服務 密鑰證明介紹及算法規格
HUKS為密鑰提供合法性證明能力,主要應用于非對稱密鑰的公鑰的證明。
鴻蒙開發:Universal Keystore Kit 密鑰管理服務 獲取密鑰屬性ArkTS
HUKS提供了接口供業務獲取指定密鑰的相關屬性。在獲取指定密鑰屬性前,需要確保已在HUKS中生成或導入持久化存儲的密鑰。
鴻蒙開發:Universal Keystore Kit 密鑰管理服務 獲取密鑰屬性C C++
HUKS提供了接口供業務獲取指定密鑰的相關屬性。在獲取指定密鑰屬性前,需要確保已在HUKS中生成或導入持久化存儲的密鑰。
評論