• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 密钥派生(ArkTS)
2
3<!--Kit: Universal Keystore Kit-->
4<!--Subsystem: Security-->
5<!--Owner: @wutiantian-gitee-->
6<!--Designer: @HighLowWorld-->
7<!--Tester: @wxy1234564846-->
8<!--Adviser: @zengyawen-->
9
10以HKDF256密钥为例,完成密钥派生。具体的场景介绍及支持的算法规格,请参考[密钥生成支持的算法](huks-key-generation-overview.md#支持的算法)。
11
12## 开发步骤
13
14**生成密钥**
15
161. 指定密钥别名,密钥别名命名规范参考[密钥生成介绍及算法规格](huks-key-generation-overview.md)。
17
182. 初始化密钥属性集,可指定参数HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG(可选),用于标识基于该密钥派生出的密钥是否由HUKS管理。
19
20    - 当TAG设置为HUKS_STORAGE_ONLY_USED_IN_HUKS时,表示基于该密钥派生出的密钥,由HUKS管理,可保证派生密钥全生命周期不出安全环境。
21
22    - 当TAG设置为HUKS_STORAGE_KEY_EXPORT_ALLOWED时,表示基于该密钥派生出的密钥,返回给调用方管理,由业务自行保证密钥安全。
23
24    - 若业务未设置TAG的具体值,表示基于该密钥派生出的密钥,即可由HUKS管理,也可返回给调用方管理,业务可在后续派生时再选择使用何种方式保护密钥。
25
263. 调用[generateKeyItem](../../reference/apis-universal-keystore-kit/js-apis-huks.md#huksgeneratekeyitem9)生成密钥,具体请参考[密钥生成](huks-key-generation-overview.md)。
27
28除此之外,开发者也可以参考[密钥导入](huks-key-import-overview.md),导入已有的密钥。
29
30**密钥派生**
31
321. 获取密钥别名,指定对应的属性参数HuksOptions。
33
34    可指定参数HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG(可选),用于标识派生得到的密钥是否由HUKS管理。
35
36    | 生成 | 派生 | 规格 |
37    | -------- | -------- | -------- |
38    | HUKS_STORAGE_ONLY_USED_IN_HUKS | HUKS_STORAGE_ONLY_USED_IN_HUKS | 密钥由HUKS管理 |
39    | HUKS_STORAGE_KEY_EXPORT_ALLOWED | HUKS_STORAGE_KEY_EXPORT_ALLOWED | 密钥返回给调用方管理 |
40    | 未指定TAG具体值 | HUKS_STORAGE_ONLY_USED_IN_HUKS | 密钥由HUKS管理 |
41    | 未指定TAG具体值 | HUKS_STORAGE_KEY_EXPORT_ALLOWED | 密钥返回给调用方管理 |
42    | 未指定TAG具体值 | 未指定TAG具体值 | 密钥返回给调用方管理 |
43
44    注:派生时指定的TAG值,不可与生成时指定的TAG值冲突。表格中仅列举有效的指定方式。
45
46
472. 调用[initSession](../../reference/apis-universal-keystore-kit/js-apis-huks.md#huksinitsession9)初始化密钥会话,并获取会话的句柄handle。
48
493. 调用[updateSession](../../reference/apis-universal-keystore-kit/js-apis-huks.md#huksupdatesession9)更新密钥会话。
50
514. 调用[finishSession](../../reference/apis-universal-keystore-kit/js-apis-huks.md#huksfinishsession9)结束密钥会话,完成派生。
52
53**删除密钥**
54
55当密钥废弃不用时,需要调用[deleteKeyItem](../../reference/apis-universal-keystore-kit/js-apis-huks.md#huksdeletekeyitem9)删除密钥,具体请参考[密钥删除](huks-delete-key-arkts.md)。
56
57## 开发案例
58
59### HKDF
60```ts
61/*
62 * 以下以HKDF密钥的Promise操作使用为例
63 */
64import { huks } from '@kit.UniversalKeystoreKit';
65import { BusinessError } from "@kit.BasicServicesKit";
66
67function StringToUint8Array(str: string) {
68  let arr: number[] = new Array();
69  for (let i = 0, j = str.length; i < j; ++i) {
70    arr.push(str.charCodeAt(i));
71  }
72  return new Uint8Array(arr);
73}
74
75function Uint8ArrayToString(fileData: Uint8Array) {
76  let dataString = '';
77  for (let i = 0; i < fileData.length; i++) {
78    dataString += String.fromCharCode(fileData[i]);
79  }
80  return dataString;
81}
82
83/*
84 * 确定密钥别名和封装密钥属性参数集
85 */
86let srcKeyAlias = "hkdf_Key";
87let deriveHkdfInData = "deriveHkdfTestIndata";
88let handle: number;
89let HuksKeyDeriveKeySize = 32;
90/* 集成生成密钥参数集 */
91let properties: Array<huks.HuksParam> = [{
92    tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
93    value: huks.HuksKeyAlg.HUKS_ALG_AES,
94  }, {
95    tag: huks.HuksTag.HUKS_TAG_PURPOSE,
96    value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DERIVE,
97  }, {
98    tag: huks.HuksTag.HUKS_TAG_DIGEST,
99    value: huks.HuksKeyDigest.HUKS_DIGEST_SHA256,
100  }, {
101    tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
102    value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256,
103  }, {
104    tag: huks.HuksTag.HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG,
105    value: huks.HuksKeyStorageType.HUKS_STORAGE_ONLY_USED_IN_HUKS,
106  }
107];
108
109let huksOptions: huks.HuksOptions = {
110  properties: properties,
111  inData: new Uint8Array(new Array())
112}
113/* 集成init时密钥参数集 */
114let initProperties: Array<huks.HuksParam> = [{
115    tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
116    value: huks.HuksKeyAlg.HUKS_ALG_HKDF,
117  }, {
118    tag: huks.HuksTag.HUKS_TAG_PURPOSE,
119    value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DERIVE,
120  }, {
121    tag: huks.HuksTag.HUKS_TAG_DIGEST,
122    value: huks.HuksKeyDigest.HUKS_DIGEST_SHA256,
123  }, {
124    tag: huks.HuksTag.HUKS_TAG_DERIVE_KEY_SIZE,
125    value: HuksKeyDeriveKeySize,
126  }
127];
128
129let initOptions: huks.HuksOptions = {
130  properties: initProperties,
131  inData: new Uint8Array(new Array())
132}
133/* 集成finish时密钥参数集 */
134let finishProperties: Array<huks.HuksParam> = [{
135    tag: huks.HuksTag.HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG,
136    value: huks.HuksKeyStorageType.HUKS_STORAGE_ONLY_USED_IN_HUKS,
137  }, {
138    tag: huks.HuksTag.HUKS_TAG_IS_KEY_ALIAS,
139    value: true,
140  }, {
141    tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
142    value: huks.HuksKeyAlg.HUKS_ALG_AES,
143  }, {
144    tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
145    value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256,
146  }, {
147    tag: huks.HuksTag.HUKS_TAG_PURPOSE,
148    value:
149    huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT |
150    huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT,
151  }, {
152    tag: huks.HuksTag.HUKS_TAG_DIGEST,
153    value: huks.HuksKeyDigest.HUKS_DIGEST_NONE,
154  }, {
155    tag: huks.HuksTag.HUKS_TAG_KEY_ALIAS,
156    value: StringToUint8Array(srcKeyAlias),
157  }, {
158    tag: huks.HuksTag.HUKS_TAG_PADDING,
159    value: huks.HuksKeyPadding.HUKS_PADDING_NONE,
160  }, {
161    tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE,
162    value: huks.HuksCipherMode.HUKS_MODE_ECB,
163  }
164];
165let finishOptions: huks.HuksOptions = {
166  properties: finishProperties,
167  inData: new Uint8Array(new Array())
168}
169
170async function generateKeyItem(keyAlias: string, huksOptions: huks.HuksOptions) {
171  console.info(`promise: enter generateKeyItem`);
172  try {
173    await huks.generateKeyItem(keyAlias, huksOptions)
174      .then(() => {
175        console.info(`promise: generateKeyItem success`);
176      }).catch((error: BusinessError) => {
177        console.error(`promise: generateKeyItem failed, errCode : ${error.code}, errMsg : ${error.message}`);
178      })
179  } catch (error) {
180    console.error(`promise: generateKeyItem input arg invalid`);
181  }
182}
183
184async function initSession(keyAlias: string, huksOptions: huks.HuksOptions) {
185  console.info(`promise: enter initSession`);
186  try {
187    await huks.initSession(keyAlias, huksOptions)
188      .then((data) => {
189        handle = data.handle;
190        console.info(`promise: initSession success`);
191      }).catch((error: BusinessError) => {
192        console.error(`promise: initSession failed, errCode : ${error.code}, errMsg : ${error.message}`);
193      })
194  } catch (error) {
195    console.error(`promise: initSession input arg invalid`);
196  }
197}
198
199async function updateSession(handle: number, huksOptions: huks.HuksOptions) {
200  console.info(`promise: enter updateSession`);
201  try {
202    await huks.updateSession(handle, huksOptions)
203      .then((data) => {
204        let outData = data.outData as Uint8Array;
205        console.info(`promise: updateSession success, data = ${Uint8ArrayToString(outData)}`);
206      }).catch((error: BusinessError) => {
207        console.error(`promise: updateSession failed, errCode : ${error.code}, errMsg : ${error.message}`);
208      })
209  } catch (error) {
210    console.error(`promise: updateSession input arg invalid`);
211  }
212}
213
214async function finishSession(handle: number, huksOptions: huks.HuksOptions) {
215  console.info(`promise: enter finishSession`);
216  try {
217    await huks.finishSession(handle, huksOptions)
218      .then((data) => {
219        let outData = data.outData as Uint8Array;
220        console.info(`promise: finishSession success, data = ${Uint8ArrayToString(outData)}`);
221      }).catch((error: BusinessError) => {
222        console.error(`promise: finishSession failed, errCode : ${error.code}, errMsg : ${error.message}`);
223      })
224  } catch (error) {
225    console.error(`promise: finishSession input arg invalid`);
226  }
227}
228
229async function deleteKeyItem(keyAlias: string, huksOptions: huks.HuksOptions) {
230  console.info(`promise: enter deleteKeyItem`);
231  try {
232    await huks.deleteKeyItem(keyAlias, huksOptions)
233      .then(() => {
234        console.info(`promise: deleteKeyItem success`);
235      }).catch((error: BusinessError) => {
236        console.error(`promise: deleteKeyItem failed, errCode : ${error.code}, errMsg : ${error.message}`);
237      })
238  } catch (error) {
239    console.error(`promise: deleteKeyItem input arg invalid`);
240  }
241}
242
243async function testDerive() {
244  /* 生成密钥 */
245  await generateKeyItem(srcKeyAlias, huksOptions);
246  /* 进行派生操作 */
247  await initSession(srcKeyAlias, initOptions);
248  initOptions.inData = StringToUint8Array(deriveHkdfInData);
249  await updateSession(handle, initOptions);
250  await finishSession(handle, finishOptions);
251  await deleteKeyItem(srcKeyAlias, huksOptions);
252}
253```
254### PBKDF2
255
256```ts
257/*
258 * 以下以PBKDF2密钥的Promise操作使用为例
259 */
260import { huks } from '@kit.UniversalKeystoreKit';
261import { BusinessError } from "@kit.BasicServicesKit";
262
263function StringToUint8Array(str: string) {
264  let arr: number[] = new Array();
265  for (let i = 0, j = str.length; i < j; ++i) {
266    arr.push(str.charCodeAt(i));
267  }
268  return new Uint8Array(arr);
269}
270
271function Uint8ArrayToString(fileData: Uint8Array) {
272  let dataString = '';
273  for (let i = 0; i < fileData.length; i++) {
274    dataString += String.fromCharCode(fileData[i]);
275  }
276  return dataString;
277}
278
279/*
280 * 确定密钥别名和封装密钥属性参数集
281 */
282let srcKeyAlias = "pbkdf2_Key";
283let salt = "mySalt";
284let iterationCount = 10000;
285let derivedKeySize = 32;
286let handle: number;
287let finishOutData: Uint8Array;
288
289/* 集成生成密钥参数集 */
290let properties: Array<huks.HuksParam> = [{
291    tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
292    value: huks.HuksKeyAlg.HUKS_ALG_AES,
293  }, {
294    tag: huks.HuksTag.HUKS_TAG_PURPOSE,
295    value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DERIVE,
296  }, {
297    tag: huks.HuksTag.HUKS_TAG_DIGEST,
298    value: huks.HuksKeyDigest.HUKS_DIGEST_SHA256,
299  }, {
300    tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
301    value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256,
302  }, {
303    tag: huks.HuksTag.HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG,
304    value: huks.HuksKeyStorageType.HUKS_STORAGE_ONLY_USED_IN_HUKS,
305  }
306];
307
308let huksOptions: huks.HuksOptions = {
309  properties: properties,
310  inData: new Uint8Array(new Array())
311}
312
313/* 集成init时密钥参数集 */
314let initProperties: Array<huks.HuksParam> = [{
315    tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
316    value: huks.HuksKeyAlg.HUKS_ALG_PBKDF2,
317  }, {
318    tag: huks.HuksTag.HUKS_TAG_PURPOSE,
319    value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DERIVE,
320  }, {
321    tag: huks.HuksTag.HUKS_TAG_DIGEST,
322    value: huks.HuksKeyDigest.HUKS_DIGEST_SHA256,
323  }, {
324    tag: huks.HuksTag.HUKS_TAG_DERIVE_KEY_SIZE,
325    value: derivedKeySize,
326  }, {
327    tag: huks.HuksTag.HUKS_TAG_ITERATION,
328    value: iterationCount,
329  }, {
330    tag: huks.HuksTag.HUKS_TAG_SALT,
331    value: StringToUint8Array(salt),
332  }
333];
334
335let initOptions: huks.HuksOptions = {
336  properties: initProperties,
337  inData: new Uint8Array(new Array())
338}
339
340/* 集成finish时密钥参数集 */
341let finishProperties: Array<huks.HuksParam> = [{
342    tag: huks.HuksTag.HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG,
343    value: huks.HuksKeyStorageType.HUKS_STORAGE_ONLY_USED_IN_HUKS,
344  }, {
345    tag: huks.HuksTag.HUKS_TAG_IS_KEY_ALIAS,
346    value: true,
347  }, {
348    tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
349    value: huks.HuksKeyAlg.HUKS_ALG_AES,
350  }, {
351    tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
352    value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256,
353  }, {
354    tag: huks.HuksTag.HUKS_TAG_PURPOSE,
355    value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT | huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT,
356  }, {
357    tag: huks.HuksTag.HUKS_TAG_DIGEST,
358    value: huks.HuksKeyDigest.HUKS_DIGEST_NONE,
359  }, {
360    tag: huks.HuksTag.HUKS_TAG_KEY_ALIAS,
361    value: StringToUint8Array(srcKeyAlias),
362  }, {
363    tag: huks.HuksTag.HUKS_TAG_PADDING,
364    value: huks.HuksKeyPadding.HUKS_PADDING_NONE,
365  }, {
366    tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE,
367    value: huks.HuksCipherMode.HUKS_MODE_ECB,
368  }
369];
370
371let finishOptions: huks.HuksOptions = {
372  properties: finishProperties,
373  inData: new Uint8Array(new Array())
374}
375
376async function generateKeyItem(keyAlias: string, huksOptions: huks.HuksOptions) {
377  console.info(`promise: enter generateKeyItem`);
378  try {
379    await huks.generateKeyItem(keyAlias, huksOptions)
380      .then(() => {
381        console.info(`promise: generateKeyItem success`);
382      }).catch((error: BusinessError) => {
383        console.error(`promise: generateKeyItem failed, errCode : ${error.code}, errMsg : ${error.message}`);
384      })
385  } catch (error) {
386    console.error(`promise: generateKeyItem input arg invalid`);
387  }
388}
389
390async function initSession(keyAlias: string, huksOptions: huks.HuksOptions) {
391  console.info(`promise: enter initSession`);
392  try {
393    await huks.initSession(keyAlias, huksOptions)
394      .then((data) => {
395        handle = data.handle;
396        console.info(`promise: initSession success`);
397      }).catch((error: BusinessError) => {
398        console.error(`promise: initSession failed, errCode : ${error.code}, errMsg : ${error.message}`);
399      })
400  } catch (error) {
401    console.error(`promise: initSession input arg invalid`);
402  }
403}
404
405async function updateSession(handle: number, huksOptions: huks.HuksOptions) {
406  console.info(`promise: enter updateSession`);
407  try {
408    await huks.updateSession(handle, huksOptions)
409      .then((data) => {
410        let outData = data.outData as Uint8Array;
411        console.info(`promise: updateSession success, data = ${Uint8ArrayToString(outData)}`);
412      }).catch((error: BusinessError) => {
413        console.error(`promise: updateSession failed, errCode : ${error.code}, errMsg : ${error.message}`);
414      })
415  } catch (error) {
416    console.error(`promise: updateSession input arg invalid`);
417  }
418}
419
420async function finishSession(handle: number, huksOptions: huks.HuksOptions) {
421  console.info(`promise: enter finishSession`);
422  try {
423    await huks.finishSession(handle, huksOptions)
424      .then((data) => {
425        let outData = data.outData as Uint8Array;
426        console.info(`promise: finishSession success, data = ${Uint8ArrayToString(outData)}`);
427      }).catch((error: BusinessError) => {
428        console.error(`promise: finishSession failed, errCode : ${error.code}, errMsg : ${error.message}`);
429      })
430  } catch (error) {
431    console.error(`promise: finishSession input arg invalid`);
432  }
433}
434
435async function deleteKeyItem(keyAlias: string, huksOptions: huks.HuksOptions) {
436  console.info(`promise: enter deleteKeyItem`);
437  try {
438    await huks.deleteKeyItem(keyAlias, huksOptions)
439      .then(() => {
440        console.info(`promise: deleteKeyItem success`);
441      }).catch((error: BusinessError) => {
442        console.error(`promise: deleteKeyItem failed, errCode : ${error.code}, errMsg : ${error.message}`);
443      })
444  } catch (error) {
445    console.error(`promise: deleteKeyItem input arg invalid`);
446  }
447}
448async function testDerive() {
449  /* 生成密钥 */
450  await generateKeyItem(srcKeyAlias, huksOptions);
451  /* 进行派生操作 */
452  await initSession(srcKeyAlias, initOptions);
453  await updateSession(handle, initOptions);
454  await finishSession(handle, finishOptions);
455  await deleteKeyItem(srcKeyAlias, huksOptions);
456}
457```