1e41f4b71Sopenharmony_ci# Key Derivation (C/C++)
2e41f4b71Sopenharmony_ci
3e41f4b71Sopenharmony_ci
4e41f4b71Sopenharmony_ciThis topic walks you through on how to derive a 256-bit key using HKDF. For details about the scenarios and supported algorithms, see [Supported Algorithms](huks-key-generation-overview.md#supported-algorithms).
5e41f4b71Sopenharmony_ci
6e41f4b71Sopenharmony_ci## Add the dynamic library in the CMake script.
7e41f4b71Sopenharmony_ci```txt
8e41f4b71Sopenharmony_ci   target_link_libraries(entry PUBLIC libhuks_ndk.z.so)
9e41f4b71Sopenharmony_ci```
10e41f4b71Sopenharmony_ci
11e41f4b71Sopenharmony_ci## How to Develop
12e41f4b71Sopenharmony_ci
13e41f4b71Sopenharmony_ci**Key Generation**
14e41f4b71Sopenharmony_ci
15e41f4b71Sopenharmony_ci1. Set the key alias.
16e41f4b71Sopenharmony_ci
17e41f4b71Sopenharmony_ci2. Initialize the key property set. You can set **OH_HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG** (optional) to specify how the key derived from this key is managed.
18e41f4b71Sopenharmony_ci
19e41f4b71Sopenharmony_ci    - If this tag is set to **OH_HUKS_STORAGE_ONLY_USED_IN_HUKS**, the derived key is managed by HUKS. That is, the derived key is always in a secure environment throughout its lifecycle.
20e41f4b71Sopenharmony_ci
21e41f4b71Sopenharmony_ci    - If this tag is set to **OH_HUKS_STORAGE_KEY_EXPORT_ALLOWED**, the derived key will be returned to the caller for management. That is, the service side ensures the key security.
22e41f4b71Sopenharmony_ci
23e41f4b71Sopenharmony_ci    - If this tag is not set, the derived key can be either managed by HUKS or returned to the caller for management. The key protection mode can be set in the subsequent key derivation on the service side.
24e41f4b71Sopenharmony_ci
25e41f4b71Sopenharmony_ci3. Use **OH_Huks_GenerateKeyItem** to generate a key. For details, see [Key Generation](huks-key-generation-overview.md).
26e41f4b71Sopenharmony_ci
27e41f4b71Sopenharmony_ciAlternatively, you can [import a key](huks-key-import-overview.md).
28e41f4b71Sopenharmony_ci
29e41f4b71Sopenharmony_ci**Key Derivation**
30e41f4b71Sopenharmony_ci
31e41f4b71Sopenharmony_ci1. Obtain the key alias and set the **HuksOptions** parameter.
32e41f4b71Sopenharmony_ci
33e41f4b71Sopenharmony_ci   You can set **OH_HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG** to specify how the derived key is managed.
34e41f4b71Sopenharmony_ci
35e41f4b71Sopenharmony_ci    | Key Generation| Key Derivation| Specifications|
36e41f4b71Sopenharmony_ci    | -------- | -------- | -------- |
37e41f4b71Sopenharmony_ci    | OH_HUKS_STORAGE_ONLY_USED_IN_HUKS | OH_HUKS_STORAGE_ONLY_USED_IN_HUKS | The key is managed by HUKS.|
38e41f4b71Sopenharmony_ci    | OH_HUKS_STORAGE_KEY_EXPORT_ALLOWED | OH_HUKS_STORAGE_KEY_EXPORT_ALLOWED | The key is returned to the caller for management.|
39e41f4b71Sopenharmony_ci    | The tag is not set.| OH_HUKS_STORAGE_ONLY_USED_IN_HUKS | The key is managed by HUKS.|
40e41f4b71Sopenharmony_ci    | The tag is not set.| OH_HUKS_STORAGE_KEY_EXPORT_ALLOWED | The key is returned to the caller for management.|
41e41f4b71Sopenharmony_ci    | The tag is not set.| The tag is not set.| The key is returned to the caller for management.|
42e41f4b71Sopenharmony_ci
43e41f4b71Sopenharmony_ci    >**NOTE**<br>The tag value set in key derivation should not conflict with the tag value set in key generation. The above table lists only valid settings.
44e41f4b71Sopenharmony_ci
45e41f4b71Sopenharmony_ci2. Use [OH_Huks_InitSession](../../reference/apis-universal-keystore-kit/_huks_key_api.md#oh_huks_initsession) to initialize a key session. The session handle is returned after the initialization.
46e41f4b71Sopenharmony_ci
47e41f4b71Sopenharmony_ci3. Use [OH_Huks_UpdateSession](../../reference/apis-universal-keystore-kit/_huks_key_api.md#oh_huks_updatesession)n to process data.
48e41f4b71Sopenharmony_ci
49e41f4b71Sopenharmony_ci4. Use [OH_Huks_FinishSession](../../reference/apis-universal-keystore-kit/_huks_key_api.md#oh_huks_finishsession) to derive a key.
50e41f4b71Sopenharmony_ci
51e41f4b71Sopenharmony_ci**Key Deletion**
52e41f4b71Sopenharmony_ci
53e41f4b71Sopenharmony_ciUse **OH_Huks_DeleteKeyItem** to delete the key that is not required. For details, see [Deleting a Key](huks-delete-key-ndk.md).
54e41f4b71Sopenharmony_ci
55e41f4b71Sopenharmony_ci```c++
56e41f4b71Sopenharmony_ci#include "huks/native_huks_api.h"
57e41f4b71Sopenharmony_ci#include "huks/native_huks_param.h"
58e41f4b71Sopenharmony_ci#include <string.h>
59e41f4b71Sopenharmony_ciOH_Huks_Result InitParamSet(
60e41f4b71Sopenharmony_ci    struct OH_Huks_ParamSet **paramSet,
61e41f4b71Sopenharmony_ci    const struct OH_Huks_Param *params,
62e41f4b71Sopenharmony_ci    uint32_t paramCount)
63e41f4b71Sopenharmony_ci{
64e41f4b71Sopenharmony_ci    OH_Huks_Result ret = OH_Huks_InitParamSet(paramSet);
65e41f4b71Sopenharmony_ci    if (ret.errorCode != OH_HUKS_SUCCESS) {
66e41f4b71Sopenharmony_ci        return ret;
67e41f4b71Sopenharmony_ci    }
68e41f4b71Sopenharmony_ci    ret = OH_Huks_AddParams(*paramSet, params, paramCount);
69e41f4b71Sopenharmony_ci    if (ret.errorCode != OH_HUKS_SUCCESS) {
70e41f4b71Sopenharmony_ci        OH_Huks_FreeParamSet(paramSet);
71e41f4b71Sopenharmony_ci        return ret;
72e41f4b71Sopenharmony_ci    }
73e41f4b71Sopenharmony_ci    ret = OH_Huks_BuildParamSet(paramSet);
74e41f4b71Sopenharmony_ci    if (ret.errorCode != OH_HUKS_SUCCESS) {
75e41f4b71Sopenharmony_ci        OH_Huks_FreeParamSet(paramSet);
76e41f4b71Sopenharmony_ci        return ret;
77e41f4b71Sopenharmony_ci    }
78e41f4b71Sopenharmony_ci    return ret;
79e41f4b71Sopenharmony_ci}
80e41f4b71Sopenharmony_cistatic const uint32_t DERIVE_KEY_SIZE_32 = 32;
81e41f4b71Sopenharmony_cistatic struct OH_Huks_Blob g_deriveKeyAlias = {
82e41f4b71Sopenharmony_ci    (uint32_t)strlen("test_derive"),
83e41f4b71Sopenharmony_ci    (uint8_t *)"test_derive"
84e41f4b71Sopenharmony_ci};
85e41f4b71Sopenharmony_cistatic struct OH_Huks_Param g_genDeriveParams[] = {
86e41f4b71Sopenharmony_ci    {
87e41f4b71Sopenharmony_ci        .tag =  OH_HUKS_TAG_ALGORITHM,
88e41f4b71Sopenharmony_ci        .uint32Param = OH_HUKS_ALG_AES
89e41f4b71Sopenharmony_ci    }, {
90e41f4b71Sopenharmony_ci        .tag =  OH_HUKS_TAG_PURPOSE,
91e41f4b71Sopenharmony_ci        .uint32Param = OH_HUKS_KEY_PURPOSE_DERIVE
92e41f4b71Sopenharmony_ci    }, {
93e41f4b71Sopenharmony_ci        .tag =  OH_HUKS_TAG_DIGEST,
94e41f4b71Sopenharmony_ci        .uint32Param = OH_HUKS_DIGEST_SHA256
95e41f4b71Sopenharmony_ci    }, {
96e41f4b71Sopenharmony_ci        .tag =  OH_HUKS_TAG_KEY_SIZE,
97e41f4b71Sopenharmony_ci        .uint32Param = OH_HUKS_AES_KEY_SIZE_256
98e41f4b71Sopenharmony_ci    }
99e41f4b71Sopenharmony_ci};
100e41f4b71Sopenharmony_cistatic struct OH_Huks_Param g_hkdfParams[] = {
101e41f4b71Sopenharmony_ci    {
102e41f4b71Sopenharmony_ci        .tag =  OH_HUKS_TAG_ALGORITHM,
103e41f4b71Sopenharmony_ci        .uint32Param = OH_HUKS_ALG_HKDF
104e41f4b71Sopenharmony_ci    }, {
105e41f4b71Sopenharmony_ci        .tag =  OH_HUKS_TAG_PURPOSE,
106e41f4b71Sopenharmony_ci        .uint32Param = OH_HUKS_KEY_PURPOSE_DERIVE
107e41f4b71Sopenharmony_ci    }, {
108e41f4b71Sopenharmony_ci        .tag =  OH_HUKS_TAG_DIGEST,
109e41f4b71Sopenharmony_ci        .uint32Param = OH_HUKS_DIGEST_SHA256
110e41f4b71Sopenharmony_ci    }, {
111e41f4b71Sopenharmony_ci        .tag =  OH_HUKS_TAG_DERIVE_KEY_SIZE,
112e41f4b71Sopenharmony_ci        .uint32Param = DERIVE_KEY_SIZE_32
113e41f4b71Sopenharmony_ci    }
114e41f4b71Sopenharmony_ci};
115e41f4b71Sopenharmony_cistatic struct OH_Huks_Param g_hkdfFinishParams[] = {
116e41f4b71Sopenharmony_ci    {
117e41f4b71Sopenharmony_ci        .tag =  OH_HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG,
118e41f4b71Sopenharmony_ci        .uint32Param = OH_HUKS_STORAGE_ONLY_USED_IN_HUKS
119e41f4b71Sopenharmony_ci    }, {
120e41f4b71Sopenharmony_ci        .tag =  OH_HUKS_TAG_KEY_ALIAS,
121e41f4b71Sopenharmony_ci        .blob = g_deriveKeyAlias
122e41f4b71Sopenharmony_ci    }, {
123e41f4b71Sopenharmony_ci        .tag =  OH_HUKS_TAG_ALGORITHM,
124e41f4b71Sopenharmony_ci        .uint32Param = OH_HUKS_ALG_HKDF
125e41f4b71Sopenharmony_ci    }, {
126e41f4b71Sopenharmony_ci        .tag =  OH_HUKS_TAG_KEY_SIZE,
127e41f4b71Sopenharmony_ci        .uint32Param = DERIVE_KEY_SIZE_32
128e41f4b71Sopenharmony_ci    }, {
129e41f4b71Sopenharmony_ci        .tag =  OH_HUKS_TAG_PURPOSE,
130e41f4b71Sopenharmony_ci        .uint32Param = OH_HUKS_KEY_PURPOSE_DERIVE
131e41f4b71Sopenharmony_ci    }, {
132e41f4b71Sopenharmony_ci        .tag =  OH_HUKS_TAG_DIGEST,
133e41f4b71Sopenharmony_ci        .uint32Param = OH_HUKS_DIGEST_SHA256
134e41f4b71Sopenharmony_ci    }
135e41f4b71Sopenharmony_ci};
136e41f4b71Sopenharmony_cistatic const uint32_t COMMON_SIZE = 2048;
137e41f4b71Sopenharmony_cistatic const char *g_deriveInData = "Hks_HKDF_Derive_Test_00000000000000000000000000000000000000000000000000000000000"
138e41f4b71Sopenharmony_ci                                    "00000000000000000000000000000000000000000000000000000000000000000000000000000000"
139e41f4b71Sopenharmony_ci                                    "0000000000000000000000000000000000000000000000000000000000000000000000000_string";
140e41f4b71Sopenharmony_cistatic napi_value DeriveKey(napi_env env, napi_callback_info info)
141e41f4b71Sopenharmony_ci{
142e41f4b71Sopenharmony_ci    struct OH_Huks_Blob genAlias = {
143e41f4b71Sopenharmony_ci        (uint32_t)strlen("test_signVerify"),
144e41f4b71Sopenharmony_ci        (uint8_t *)"test_signVerify"
145e41f4b71Sopenharmony_ci    };
146e41f4b71Sopenharmony_ci    struct OH_Huks_Blob inData = {
147e41f4b71Sopenharmony_ci        (uint32_t)strlen(g_deriveInData),
148e41f4b71Sopenharmony_ci        (uint8_t *)g_deriveInData
149e41f4b71Sopenharmony_ci    };
150e41f4b71Sopenharmony_ci    struct OH_Huks_ParamSet *genParamSet = nullptr;
151e41f4b71Sopenharmony_ci    struct OH_Huks_ParamSet *hkdfParamSet = nullptr;
152e41f4b71Sopenharmony_ci    struct OH_Huks_ParamSet *hkdfFinishParamSet = nullptr;
153e41f4b71Sopenharmony_ci    OH_Huks_Result ohResult;
154e41f4b71Sopenharmony_ci    do {
155e41f4b71Sopenharmony_ci        ohResult = InitParamSet(&genParamSet, g_genDeriveParams, sizeof(g_genDeriveParams) / sizeof(OH_Huks_Param));
156e41f4b71Sopenharmony_ci        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
157e41f4b71Sopenharmony_ci            break;
158e41f4b71Sopenharmony_ci        }
159e41f4b71Sopenharmony_ci
160e41f4b71Sopenharmony_ci        ohResult = InitParamSet(&hkdfParamSet, g_hkdfParams, sizeof(g_hkdfParams) / sizeof(OH_Huks_Param));
161e41f4b71Sopenharmony_ci        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
162e41f4b71Sopenharmony_ci           break;
163e41f4b71Sopenharmony_ci        }
164e41f4b71Sopenharmony_ci
165e41f4b71Sopenharmony_ci        // finish paramset
166e41f4b71Sopenharmony_ci        ohResult = InitParamSet(&hkdfFinishParamSet, g_hkdfFinishParams, sizeof(g_hkdfFinishParams) / sizeof(OH_Huks_Param));
167e41f4b71Sopenharmony_ci        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
168e41f4b71Sopenharmony_ci            break;
169e41f4b71Sopenharmony_ci        }
170e41f4b71Sopenharmony_ci
171e41f4b71Sopenharmony_ci        /* 1. Generate Key */
172e41f4b71Sopenharmony_ci        ohResult = OH_Huks_GenerateKeyItem(&genAlias, genParamSet, nullptr);
173e41f4b71Sopenharmony_ci        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
174e41f4b71Sopenharmony_ci            break;
175e41f4b71Sopenharmony_ci        }
176e41f4b71Sopenharmony_ci        /* 2. Derive */
177e41f4b71Sopenharmony_ci        // Init
178e41f4b71Sopenharmony_ci        uint8_t handleD[sizeof(uint64_t)] = {0};
179e41f4b71Sopenharmony_ci        struct OH_Huks_Blob handleDerive = { sizeof(uint64_t), handleD };
180e41f4b71Sopenharmony_ci        ohResult = OH_Huks_InitSession(&genAlias, hkdfParamSet, &handleDerive, nullptr);
181e41f4b71Sopenharmony_ci        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
182e41f4b71Sopenharmony_ci            break;
183e41f4b71Sopenharmony_ci        }
184e41f4b71Sopenharmony_ci        // Update
185e41f4b71Sopenharmony_ci        uint8_t tmpOut[COMMON_SIZE] = {0};
186e41f4b71Sopenharmony_ci        struct OH_Huks_Blob outData = { COMMON_SIZE, tmpOut };
187e41f4b71Sopenharmony_ci        ohResult = OH_Huks_UpdateSession(&handleDerive, hkdfParamSet, &inData, &outData);
188e41f4b71Sopenharmony_ci        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
189e41f4b71Sopenharmony_ci            break;
190e41f4b71Sopenharmony_ci        }
191e41f4b71Sopenharmony_ci        // Finish
192e41f4b71Sopenharmony_ci        uint8_t outDataD[COMMON_SIZE] = {0};
193e41f4b71Sopenharmony_ci        struct OH_Huks_Blob outDataDerive = { COMMON_SIZE, outDataD };
194e41f4b71Sopenharmony_ci        ohResult = OH_Huks_FinishSession(&handleDerive, hkdfFinishParamSet, &inData, &outDataDerive);
195e41f4b71Sopenharmony_ci    } while (0);
196e41f4b71Sopenharmony_ci    (void)OH_Huks_DeleteKeyItem(&genAlias, nullptr);
197e41f4b71Sopenharmony_ci    (void)OH_Huks_DeleteKeyItem(&g_deriveKeyAlias, nullptr);
198e41f4b71Sopenharmony_ci    OH_Huks_FreeParamSet(&genParamSet);
199e41f4b71Sopenharmony_ci    OH_Huks_FreeParamSet(&hkdfParamSet);
200e41f4b71Sopenharmony_ci    OH_Huks_FreeParamSet(&hkdfFinishParamSet);
201e41f4b71Sopenharmony_ci
202e41f4b71Sopenharmony_ci    napi_value ret;
203e41f4b71Sopenharmony_ci    napi_create_int32(env, ohResult.errorCode, &ret);
204e41f4b71Sopenharmony_ci    return ret;
205e41f4b71Sopenharmony_ci}
206e41f4b71Sopenharmony_ci```
207