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