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