# Signing and Signature Verification (C/C++) This topic walks you through on how to implement signing and signature verification using the key algorithm RSA2048, MD algorithm SHA384, and padding mode PSS. For details about the scenarios and supported algorithms, see [Supported Algorithms](huks-signing-signature-verification-overview.md#supported-algorithms). ## Add the dynamic library in the CMake script. ```txt target_link_libraries(entry PUBLIC libhuks_ndk.z.so) ``` ## How to Develop **Key Generation** 1. Set the key alias. 2. Initialize the key property set. 3. Use **OH_Huks_GenerateKeyItem** to generate a key. For details, see [Key Generation](huks-key-generation-overview.md). Alternatively, you can [import a key](huks-key-import-overview.md). **Signing** 1. Obtain the key alias. 2. Obtain the plaintext to be signed. 3. Use [OH_Huks_InitParamSet](../../reference/apis-universal-keystore-kit/_huks_param_set_api.md#oh_huks_initparamset) to set algorithm parameters. 4. 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. 5. Use [OH_Huks_FinishSession](../../reference/apis-universal-keystore-kit/_huks_key_api.md#oh_huks_finishsession) to generate a signature. **Signature Verification** 1. Obtain the key alias. 2. Obtain the signature to be verified. 3. Set [algorithm parameters](../../reference/apis-universal-keystore-kit/_huks_param_set_api.md#oh_huks_initparamset). 4. 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. 5. Use [OH_Huks_UpdateSession](../../reference/apis-universal-keystore-kit/_huks_key_api.md#oh_huks_updatesession) to process data. 6. Use [OH_Huks_FinishSession](../../reference/apis-universal-keystore-kit/_huks_key_api.md#oh_huks_finishsession) to finish signature verification. **Key Deletion** Use OH_Huks_DeleteKeyItem to delete the key that is not required. For details, see [Deleting a Key](huks-delete-key-ndk.md). ```c++ #include "huks/native_huks_api.h" #include "huks/native_huks_param.h" #include OH_Huks_Result InitParamSet( struct OH_Huks_ParamSet **paramSet, const struct OH_Huks_Param *params, uint32_t paramCount) { OH_Huks_Result ret = OH_Huks_InitParamSet(paramSet); if (ret.errorCode != OH_HUKS_SUCCESS) { return ret; } ret = OH_Huks_AddParams(*paramSet, params, paramCount); if (ret.errorCode != OH_HUKS_SUCCESS) { OH_Huks_FreeParamSet(paramSet); return ret; } ret = OH_Huks_BuildParamSet(paramSet); if (ret.errorCode != OH_HUKS_SUCCESS) { OH_Huks_FreeParamSet(paramSet); return ret; } return ret; } static struct OH_Huks_Param g_genSignVerifyParamsTest[] = { { .tag = OH_HUKS_TAG_ALGORITHM, .uint32Param = OH_HUKS_ALG_RSA }, { .tag = OH_HUKS_TAG_PURPOSE, .uint32Param = OH_HUKS_KEY_PURPOSE_SIGN | OH_HUKS_KEY_PURPOSE_VERIFY }, { .tag = OH_HUKS_TAG_KEY_SIZE, .uint32Param = OH_HUKS_RSA_KEY_SIZE_2048 }, { .tag = OH_HUKS_TAG_PADDING, .uint32Param = OH_HUKS_PADDING_PSS }, { .tag = OH_HUKS_TAG_DIGEST, .uint32Param = OH_HUKS_DIGEST_SHA384 }, }; static struct OH_Huks_Param g_signParamsTest[] = { { .tag = OH_HUKS_TAG_ALGORITHM, .uint32Param = OH_HUKS_ALG_RSA }, { .tag = OH_HUKS_TAG_PURPOSE, .uint32Param = OH_HUKS_KEY_PURPOSE_SIGN }, { .tag = OH_HUKS_TAG_KEY_SIZE, .uint32Param = OH_HUKS_RSA_KEY_SIZE_2048 }, { .tag = OH_HUKS_TAG_PADDING, .uint32Param = OH_HUKS_PADDING_PSS }, { .tag = OH_HUKS_TAG_DIGEST, .uint32Param = OH_HUKS_DIGEST_SHA384 } }; static struct OH_Huks_Param g_verifyParamsTest[] = { { .tag = OH_HUKS_TAG_ALGORITHM, .uint32Param = OH_HUKS_ALG_RSA }, { .tag = OH_HUKS_TAG_PURPOSE, .uint32Param = OH_HUKS_KEY_PURPOSE_VERIFY }, { .tag = OH_HUKS_TAG_KEY_SIZE, .uint32Param = OH_HUKS_RSA_KEY_SIZE_2048 }, { .tag = OH_HUKS_TAG_PADDING, .uint32Param = OH_HUKS_PADDING_PSS }, { .tag = OH_HUKS_TAG_DIGEST, .uint32Param = OH_HUKS_DIGEST_SHA384 } }; static const uint32_t RSA_COMMON_SIZE = 1024; static const char *g_dataToSign = "Hks_RSA_Sign_Verify_Test_0000000000000000000000000000000000000000000000000000000" "00000000000000000000000000000000000000000000000000000000000000000000000000000000" "0000000000000000000000000000000000000000000000000000000000000000000000000_string"; static napi_value SignVerifyKey(napi_env env, napi_callback_info info) { struct OH_Huks_Blob g_keyAlias = { (uint32_t)strlen("test_signVerify"), (uint8_t *)"test_signVerify" }; struct OH_Huks_Blob inData = { (uint32_t)strlen(g_dataToSign), (uint8_t *)g_dataToSign }; struct OH_Huks_ParamSet *genParamSet = nullptr; struct OH_Huks_ParamSet *signParamSet = nullptr; struct OH_Huks_ParamSet *verifyParamSet = nullptr; OH_Huks_Result ohResult; do { ohResult = InitParamSet(&genParamSet, g_genSignVerifyParamsTest, sizeof(g_genSignVerifyParamsTest) / sizeof(OH_Huks_Param)); if (ohResult.errorCode != OH_HUKS_SUCCESS) { break; } ohResult = InitParamSet(&signParamSet, g_signParamsTest, sizeof(g_signParamsTest) / sizeof(OH_Huks_Param)); if (ohResult.errorCode != OH_HUKS_SUCCESS) { break; } ohResult = InitParamSet(&verifyParamSet, g_verifyParamsTest, sizeof(g_verifyParamsTest) / sizeof(OH_Huks_Param)); if (ohResult.errorCode != OH_HUKS_SUCCESS) { break; } /* 1. Generate Key */ ohResult = OH_Huks_GenerateKeyItem(&g_keyAlias, genParamSet, nullptr); if (ohResult.errorCode != OH_HUKS_SUCCESS) { break; } /* 2. Sign */ // Init uint8_t handleS[sizeof(uint64_t)] = {0}; struct OH_Huks_Blob handleSign = { (uint32_t)sizeof(uint64_t), handleS }; ohResult = OH_Huks_InitSession(&g_keyAlias, signParamSet, &handleSign, nullptr); // Update uint8_t outDataS[RSA_COMMON_SIZE] = {0}; struct OH_Huks_Blob outDataSign = { RSA_COMMON_SIZE, outDataS }; ohResult = OH_Huks_UpdateSession(&handleSign, signParamSet, &inData, &outDataSign); if (ohResult.errorCode != OH_HUKS_SUCCESS) { break; } // Finish struct OH_Huks_Blob finishInData = { 0, NULL }; ohResult = OH_Huks_FinishSession(&handleSign, signParamSet, &finishInData, &outDataSign); /* 3. Verify */ // Init uint8_t handleV[sizeof(uint64_t)] = {0}; struct OH_Huks_Blob handleVerify = { (uint32_t)sizeof(uint64_t), handleV }; ohResult = OH_Huks_InitSession(&g_keyAlias, verifyParamSet, &handleVerify, nullptr); if (ohResult.errorCode != OH_HUKS_SUCCESS) { break; } // Update loop uint8_t temp[] = "out"; struct OH_Huks_Blob verifyOut = { (uint32_t)sizeof(temp), temp }; ohResult = OH_Huks_UpdateSession(&handleVerify, verifyParamSet, &inData, &verifyOut); if (ohResult.errorCode != OH_HUKS_SUCCESS) { break; } // Finish ohResult = OH_Huks_FinishSession(&handleVerify, verifyParamSet, &outDataSign, &verifyOut); if (ohResult.errorCode != OH_HUKS_SUCCESS) { break; } } while (0); (void)OH_Huks_DeleteKeyItem(&g_keyAlias, genParamSet); OH_Huks_FreeParamSet(&genParamSet); OH_Huks_FreeParamSet(&signParamSet); OH_Huks_FreeParamSet(&verifyParamSet); napi_value ret; napi_create_int32(env, ohResult.errorCode, &ret); return ret; } ```