openharmony 鸿蒙 crypto-compute-hmac-ndk

2026-08-25 浏览 (1)

Generating an HMAC (C/C++)

A hash-based message authentication code (HMAC) uses a specified digest algorithm to generate a MAC based on the key and message shared by communicating parties. The MAC is used to check the integrity of transmitted packets. The HMAC adds key input on the basis of the message digest algorithm to ensure information correctness. The generated MAC has a fixed length.

How to Develop

In the update API call, you can pass in full data or pass in data by segment. The same data will produce the same result no matter how the data is passed. Use the appropriate method based on the data size.

The following provides examples with different data passing methods.

Generating an HMAC by Passing In Full Data

  1. Call OH_CryptoSymKeyGenerator_Create and OH_CryptoSymKeyGenerator_Generate to generate a symmetric key (symKey) with the key algorithm being HMAC.

  2. Call OH_CryptoMac_Create and specify the string parameter HMAC to create a MAC generator with the HMAC algorithm.

  3. Call OH_CryptoMac_SetParam and specify CRYPTO_MAC_DIGEST_NAME_STR to set the digest algorithm name.

  4. Call OH_CryptoMac_Init and specify the shared symmetric key (symKey) to initialize the MAC object.

  5. Call OH_CryptoMac_Update to pass in the data.

  6. Call OH_CryptoMac_Final to obtain the MAC generation result.

  7. Call OH_CryptoMac_GetLength to obtain the length of the MAC, in bytes.

#include "CryptoArchitectureKit/crypto_architecture_kit.h"
#include <stdio.h>
#include <string.h>

static OH_CryptoSymKey *GenerateHmacKey(const char *algoName)
{
    OH_CryptoSymKeyGenerator *keyGen = nullptr;
    OH_Crypto_ErrCode ret = OH_CryptoSymKeyGenerator_Create(algoName, &keyGen);
    if (ret != CRYPTO_SUCCESS) {
        return nullptr;
    }
    OH_CryptoSymKey *keyCtx = nullptr;
    ret = OH_CryptoSymKeyGenerator_Generate(keyGen, &keyCtx);
    OH_CryptoSymKeyGenerator_Destroy(keyGen);
    if (ret != CRYPTO_SUCCESS) {
        return nullptr;
    }
    return keyCtx;
}

static OH_Crypto_ErrCode doTestHmacOnce()
{
    // Generate an HMAC key, using SM3 as the digest algorithm.
    OH_CryptoSymKey *keyCtx = GenerateHmacKey("HMAC|SM3");
    if (keyCtx == nullptr) {
        return CRYPTO_OPERTION_ERROR;
    }

    // Create an HMAC generator.
    OH_CryptoMac *ctx = nullptr;
    OH_Crypto_ErrCode ret = OH_CryptoMac_Create("HMAC", &ctx);
    if (ret != CRYPTO_SUCCESS) {
        OH_CryptoSymKey_Destroy(keyCtx);
        return ret;
    }

    // Set the digest algorithm name to SM3.
    const char *digestName = "SM3";
    Crypto_DataBlob digestNameData = {
        .data = reinterpret_cast<uint8_t *>(const_cast<char *>(digestName)),
        .len = strlen(digestName)
    };
    ret = OH_CryptoMac_SetParam(ctx, CRYPTO_MAC_DIGEST_NAME_STR, &digestNameData);
    if (ret != CRYPTO_SUCCESS) {
        OH_CryptoMac_Destroy(ctx);
        OH_CryptoSymKey_Destroy(keyCtx);
        return ret;
    }

    // Initialize the HMAC object.
    ret = OH_CryptoMac_Init(ctx, keyCtx);
    if (ret != CRYPTO_SUCCESS) {
        OH_CryptoMac_Destroy(ctx);
        OH_CryptoSymKey_Destroy(keyCtx);
        return ret;
    }

    // Pass in full data.
    const char *message = "hmacTestMessage";
    Crypto_DataBlob input = {
        .data = reinterpret_cast<uint8_t *>(const_cast<char *>(message)),
        .len = strlen(message)
    };
    ret = OH_CryptoMac_Update(ctx, &input);
    if (ret != CRYPTO_SUCCESS) {
        OH_CryptoMac_Destroy(ctx);
        OH_CryptoSymKey_Destroy(keyCtx);
        return ret;
    }

    // Finalize HMAC generation and obtain the result.
    Crypto_DataBlob out = {0};
    ret = OH_CryptoMac_Final(ctx, &out);
    if (ret != CRYPTO_SUCCESS) {
        OH_CryptoMac_Destroy(ctx);
        OH_CryptoSymKey_Destroy(keyCtx);
        return ret;
    }

    // Obtain the length of the HMAC value.
    uint32_t macLen = 0;
    ret = OH_CryptoMac_GetLength(ctx, &macLen);
    if (ret != CRYPTO_SUCCESS) {
        OH_Crypto_FreeDataBlob(&out);
        OH_CryptoMac_Destroy(ctx);
        OH_CryptoSymKey_Destroy(keyCtx);
        return ret;
    }

    printf("HMAC calculation success, length: %u\n", macLen);

    // Free resources.
    OH_Crypto_FreeDataBlob(&out);
    OH_CryptoMac_Destroy(ctx);
    OH_CryptoSymKey_Destroy(keyCtx);
    return CRYPTO_SUCCESS;
}

Generating an HMAC by Passing in Data by Segment

Unlike the first method, this one requires calling OH_CryptoMac_Update multiple times to process segmented data.

#include "CryptoArchitectureKit/crypto_architecture_kit.h"
#include <stdio.h>
#include <string.h>

static OH_CryptoSymKey *GenerateHmacKey(const char *algoName)
{
    OH_CryptoSymKeyGenerator *keyGen = nullptr;
    OH_Crypto_ErrCode ret = OH_CryptoSymKeyGenerator_Create(algoName, &keyGen);
    if (ret != CRYPTO_SUCCESS) {
        return nullptr;
    }
    OH_CryptoSymKey *keyCtx = nullptr;
    ret = OH_CryptoSymKeyGenerator_Generate(keyGen, &keyCtx);
    OH_CryptoSymKeyGenerator_Destroy(keyGen);
    if (ret != CRYPTO_SUCCESS) {
        return nullptr;
    }
    return keyCtx;
}

static OH_Crypto_ErrCode doTestHmacBySegments()
{
    // Generate an HMAC key, using SM3 as the digest algorithm.
    OH_CryptoSymKey *keyCtx = GenerateHmacKey("HMAC|SM3");
    if (keyCtx == nullptr) {
        return CRYPTO_OPERTION_ERROR;
    }

    // Create an HMAC generator.
    OH_CryptoMac *ctx = nullptr;
    OH_Crypto_ErrCode ret = OH_CryptoMac_Create("HMAC", &ctx);
    if (ret != CRYPTO_SUCCESS) {
        OH_CryptoSymKey_Destroy(keyCtx);
        return ret;
    }

    // Set the digest algorithm name to SM3.
    const char *digestName = "SM3";
    Crypto_DataBlob digestNameData = {
        .data = reinterpret_cast<uint8_t *>(const_cast<char *>(digestName)),
        .len = strlen(digestName)
    };
    ret = OH_CryptoMac_SetParam(ctx, CRYPTO_MAC_DIGEST_NAME_STR, &digestNameData);
    if (ret != CRYPTO_SUCCESS) {
        OH_CryptoMac_Destroy(ctx);
        OH_CryptoSymKey_Destroy(keyCtx);
        return ret;
    }

    // Initialize the HMAC object.
    ret = OH_CryptoMac_Init(ctx, keyCtx);
    if (ret != CRYPTO_SUCCESS) {
        OH_CryptoMac_Destroy(ctx);
        OH_CryptoSymKey_Destroy(keyCtx);
        return ret;
    }

    // Pass in data by segment.
    const char *message = "aaaaa.....bbbbb.....ccccc.....ddddd.....eee";
    size_t messageLen = strlen(message);
    size_t segmentSize = 20; // Divide the data into segments of 20 bytes each.

    for (size_t i = 0; i < messageLen; i += segmentSize) {
        size_t currentSize = (i + segmentSize <= messageLen) ? segmentSize : (messageLen - i);
        Crypto_DataBlob segment = {
            .data = reinterpret_cast<uint8_t *>(const_cast<char *>(message + i)),
            .len = currentSize
        };
        ret = OH_CryptoMac_Update(ctx, &segment);
        if (ret != CRYPTO_SUCCESS) {
            OH_CryptoMac_Destroy(ctx);
            OH_CryptoSymKey_Destroy(keyCtx);
            return ret;
        }
    }

    // Finalize HMAC generation and obtain the result.
    Crypto_DataBlob out = {0};
    ret = OH_CryptoMac_Final(ctx, &out);
    if (ret != CRYPTO_SUCCESS) {
        OH_CryptoMac_Destroy(ctx);
        OH_CryptoSymKey_Destroy(keyCtx);
        return ret;
    }

    // Obtain the length of the HMAC value.
    uint32_t macLen = 0;
    ret = OH_CryptoMac_GetLength(ctx, &macLen);
    if (ret != CRYPTO_SUCCESS) {
        OH_Crypto_FreeDataBlob(&out);
        OH_CryptoMac_Destroy(ctx);
        OH_CryptoSymKey_Destroy(keyCtx);
        return ret;
    }

    printf("HMAC calculation success, length: %u\n", macLen);

    // Free resources.
    OH_Crypto_FreeDataBlob(&out);
    OH_CryptoMac_Destroy(ctx);
    OH_CryptoSymKey_Destroy(keyCtx);
    return CRYPTO_SUCCESS;
}

你可能感兴趣的鸿蒙文章

openharmony 鸿蒙 crypto-rsa-asym-encrypt-decrypt-pkcs1-ndk

openharmony 鸿蒙 crypto-key-agreement-using-ecdh

openharmony 鸿蒙 crypto-aes-sym-encrypt-decrypt-gcm-ndk

openharmony 鸿蒙 crypto-sm4-sym-encrypt-decrypt-gcm-ndk

openharmony 鸿蒙 crypto-sm2-sign-sig-verify-pkcs1-ndk

openharmony 鸿蒙 crypto-key-derivation-using-scrypt-ndk

openharmony 鸿蒙 crypto-sym-encrypt-decrypt-spec

openharmony 鸿蒙 crypto-rsa-sign-sig-verify-pkcs1-by-segment

openharmony 鸿蒙 crypto-sm4-sym-encrypt-decrypt-cbc

openharmony 鸿蒙 crypto-prikey-to-get-pubkey-ndk

  • 所属分类: 后端技术
  • 本文标签: 软件 鸿蒙
  • 版权声明: 本文链接 https://seaxiang.com/blog/YN0ZjcBC