密鑰協(xié)商(ArkTS)
以協(xié)商密鑰類型為X25519 256,并密鑰僅在HUKS內(nèi)使用為例,完成密鑰協(xié)商。
開發(fā)步驟
生成密鑰
設備A、設備B各自生成一個非對稱密鑰,具體請參考[密鑰生成]或[密鑰導入]。
密鑰生成時,可指定參數(shù)HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG(可選),用于標識基于該密鑰協(xié)商出的密鑰是否由HUKS管理。
- 當TAG設置為HUKS_STORAGE_ONLY_USED_IN_HUKS時,表示基于該密鑰協(xié)商出的密鑰,由HUKS管理,可保證協(xié)商密鑰全生命周期不出安全環(huán)境。
- 當TAG設置為HUKS_STORAGE_KEY_EXPORT_ALLOWED時,表示基于該密鑰協(xié)商出的密鑰,返回給調(diào)用方管理,由業(yè)務自行保證密鑰安全。
- 若業(yè)務未設置TAG的具體值,表示基于該密鑰協(xié)商出的密鑰,即可由HUKS管理,也可返回給調(diào)用方管理,業(yè)務可在后續(xù)協(xié)商時再選擇使用何種方式保護密鑰。
- 開發(fā)前請熟悉鴻蒙開發(fā)指導文檔 :[
gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md
]
導出密鑰
設備A、B導出非對稱密鑰對的公鑰材料。
密鑰協(xié)商
設備A、B分別基于本端私鑰和對端設備的公鑰,協(xié)商出共享密鑰。
密鑰協(xié)商時,可指定參數(shù)HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG(可選),用于標識協(xié)商得到的密鑰是否由HUKS管理。
生成 | 協(xié)商 | 規(guī)格 |
---|---|---|
HUKS_STORAGE_ONLY_USED_IN_HUKS | HUKS_STORAGE_ONLY_USED_IN_HUKS | 密鑰由HUKS管理 |
HUKS_STORAGE_KEY_EXPORT_ALLOWED | HUKS_STORAGE_KEY_EXPORT_ALLOWED | 密鑰返回給調(diào)用方管理 |
未指定TAG具體值 | HUKS_STORAGE_ONLY_USED_IN_HUKS | 密鑰由HUKS管理 |
未指定TAG具體值 | HUKS_STORAGE_KEY_EXPORT_ALLOWED | 密鑰返回給調(diào)用方管理 |
未指定TAG具體值HarmonyOS與OpenHarmony鴻蒙文檔籽料:mau123789是v直接拿 | 未指定TAG具體值 | 密鑰返回給調(diào)用方管理 |
注:協(xié)商時指定的TAG值,不可與生成時指定的TAG值沖突。表格中僅列舉有效的指定方式。
刪除密鑰
當密鑰廢棄不用時,設備A、B均需要刪除密鑰。
下面分別以X25519 與 DH密鑰為例,進行協(xié)商。
/*
*以下以X25519 256密鑰的Promise操作使用為例
*/
import { huks } from '@kit.UniversalKeystoreKit';
/*
* 確定密鑰別名和封裝密鑰屬性參數(shù)集
*/
let srcKeyAliasFirst = "AgreeX25519KeyFirstAlias";
let srcKeyAliasSecond = "AgreeX25519KeySecondAlias";
let agreeX25519InData = 'AgreeX25519TestIndata';
let finishOutData: Uint8Array;
let handle: number;
let exportKey: Uint8Array;
let exportKeyFirst: Uint8Array;
let exportKeySecond: Uint8Array;
/* 集成生成密鑰參數(shù)集 */
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())
}
/* 集成第一個協(xié)商參數(shù)集 */
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)
}
/* 集成第二個協(xié)商參數(shù)集 */
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);
}
});
}
/* 調(diào)用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)}`);
}
}
/*初始化密鑰會話接口,并獲取一個句柄(必選)和挑戰(zhàn)值(可選)*/
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);
}
});
}
/*調(diào)用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)}`);
}
}
/* 分段添加密鑰操作的數(shù)據(jù)并進行相應的密鑰操作,輸出處理數(shù)據(jù) */
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);
}
});
}
/* 調(diào)用updateSession進行協(xié)商操作 */
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)}`);
}
}
/* 結(jié)束密鑰會話并進行相應的密鑰操作,輸出處理數(shù)據(jù) */
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);
}
});
}
/* 調(diào)用finishSession結(jié)束操作 */
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);
}
});
}
/* 調(diào)用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);
}
});
}
/* 調(diào)用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.確定密鑰別名并集成并集成要參數(shù)集 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.對第一個密鑰進行協(xié)商(三段式)*/
await publicInitFunc(srcKeyAliasFirst, HuksOptions);
HuksOptions.inData = exportKeySecond;
await publicUpdateFunc(handle, HuksOptions);
await publicFinishFunc(handle, finishOptionsFirst);
/* 5.對第二個密鑰進行協(xié)商(三段式) */
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密鑰協(xié)商為例
/*
*以下以 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'
/* 調(diào)用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)
/* 開始協(xié)商,協(xié)商生成的密鑰返回給業(yè)務管理 */
await HuksDhAgreeExportTest(aliasAlice, aliasBob, pubKeyAlice, pubKeyBob)
/* 開始協(xié)商,協(xié)商生成的密鑰由HUKS管理 */
await HuksDhAgreeInHuksTest(aliasAlice, aliasBob, pubKeyAlice, pubKeyBob, 'agreedKeyFromAlice', 'agreedKeyFromBob')
await huks.deleteKeyItem(aliasAlice, emptyOptions)
await huks.deleteKeyItem(aliasBob, emptyOptions)
}
審核編輯 黃宇
-
鴻蒙
+關(guān)注
關(guān)注
57文章
2303瀏覽量
42691
發(fā)布評論請先 登錄
相關(guān)推薦
評論