# 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. Specify the key alias. For details about the naming rules, see [Key Generation Overview and Algorithm Specifications](huks-key-generation-overview.md). 2. Initialize the key property set. 3. Use [OH_Huks_GenerateKeyItem](../../reference/apis-universal-keystore-kit/capi-native-huks-api-h.md#oh_huks_generatekeyitem) to generate a key. For details, see [Key Generation Overview and Algorithm Specifications](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/capi-native-huks-param-h.md#oh_huks_initparamset) to set algorithm parameters. 4. Use [OH_Huks_InitSession](../../reference/apis-universal-keystore-kit/capi-native-huks-api-h.md#oh_huks_initsession) to initialize a key session and obtain the session handle. 5. Use [OH_Huks_FinishSession](../../reference/apis-universal-keystore-kit/capi-native-huks-api-h.md#oh_huks_finishsession) to end the key session and obtain the signature. **Signature Verification** 1. Obtain the key alias. 2. Obtain the signature to be verified. 3. Use [OH_Huks_InitParamSet](../../reference/apis-universal-keystore-kit/capi-native-huks-param-h.md#oh_huks_initparamset) to [set algorithm parameters](../../reference/apis-universal-keystore-kit/capi-native-huks-param-h.md#oh_huks_initparamset). 4. Use [OH_Huks_InitSession](../../reference/apis-universal-keystore-kit/capi-native-huks-api-h.md#oh_huks_initsession) to initialize a key session and obtain the session handle. 5. Use [OH_Huks_UpdateSession](../../reference/apis-universal-keystore-kit/capi-native-huks-api-h.md#oh_huks_updatesession) to update the key session. 6. Use [OH_Huks_FinishSession](../../reference/apis-universal-keystore-kit/capi-native-huks-api-h.md#oh_huks_finishsession) to end the key session and verify the signature. **Key Deletion** When a key is no longer used, you need to call [OH_Huks_DeleteKeyItem](../../reference/apis-universal-keystore-kit/capi-native-huks-api-h.md#oh_huks_deletekeyitem) to delete the key. 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 "napi/native_api.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; } ```