security_huks模块下hks_rkc.c代码评注第四部分

本文深入剖析了security_huks模块下hks_rkc.c文件中关于密钥获取的关键代码,包括hks_rkc_pbkdf2_hmac函数中使用PBKDF2-HMAC算法获取派生密钥,hks_rkc_get_rmk_raw_key函数通过异或运算获取原始密钥,以及hks_rkc_derive_rmk函数派生根主密钥的过程。同时,介绍了写入所有密钥库文件的hks_rkc_write_all_ksf函数。这些内容对于理解密钥管理和安全存储至关重要。

本篇概述

本篇是接着:

在讲解完密钥库文件的检查操作、密钥库文件中材料的生成相关操作和方法后,本篇将继续讲述hks_rkc.c代码中有关密钥获取以及写所有密钥库文件的部分内容。

代码框架

hks_rkc.c
├── get_related_key
│ └── hks_rkc_pbkdf2_hmac
│ └── hks_rkc_get_rmk_raw_key
│ └── hks_rkc_derive_rmk
├── write
│ └── hks_rkc_write_all_ksf

密钥获取部分

1. hks_rkc_pbkdf2_hmac

  • 函数功能:使用pbkdf2_hmac算法获取派生密钥
    root key component - calculate pbkdf2 hmac

  • 参数说明:hash算法、原始密钥、椒盐化、迭代次数、派生密钥
    parameter:
    hash_alg - [in] - hash algorithm.
    raw_key - [in] - raw key.
    salt - [in] - salt.
    iter_num - [in] - the number of iterater.
    dk - [in,out] - derived key.

  • 返回值:成功或错误代码
    return value:
    success or error code

为了掌握hks_rkc_pbkdf2_hmac函数中相关操作内容,我们需要关注一下几个重点内容:

  1. 有关mbedtls的相关定义及操作

  2. PBKDF2-HMAC算法

  3. mbedtls中预定义的mbedtls_pkcs5_pbkdf2_hmac函数

        int mbedtls_pkcs5_pbkdf2_hmac	(	
        mbedtls_md_context_t * 	ctx,
        const unsigned char * 	password,
        size_t 	plen,
        const unsigned char * 	salt,
        size_t 	slen,
        unsigned int 	iteration_count,
        uint32_t 	key_length,
        unsigned char * 	output 
        )		
    

    PKCS#5 PBKDF2 using HMAC.

         Parameters  参数讲解:
         
         ctx				Generic HMAC context				通用HMAC上下文
         password			Password to use when generating key	生成密钥时使用的密码
         plen				Length of password					密钥长度
         salt				Salt to use when generating key		生成密钥使用的盐化量
         slen				Length of salt				 		盐化量长度
         iteration_count	Iteration count						迭代次数
         key_length	Length of generated key in bytes			生成密钥的存储长度
         
         output	Generated key. Must be at least as big as key_length
         输出:生成密钥
         
         Returns 返回值:
         0 on success, or a MBEDTLS_ERR_XXX code if verification fails.
         Definition at line 217 of file pkcs5.c.
    

详细代码及评注如下:

static int32_t hks_rkc_pbkdf2_hmac(uint32_t hash_alg,
    const struct hks_blob *raw_key, const struct hks_blob *salt,
    uint32_t iter_num, struct hks_blob *dk)
{
    //定义摘要算法类型变量
    mbedtls_md_type_t md_type;

    //此处我们只支持SHA256,检查传入参数hash_alg是否为SHA256,这代表了派生根主密钥使用的hash算法
    if (hash_alg == HKS_RKC_RMK_HMAC_SHA256) {
        md_type = MBEDTLS_MD_SHA256;
    } else {
        log_error("the hash algorithm(%u) is unsupported", hash_alg);
        return HKS_ERROR_NOT_SUPPORTED;
    }

    //初始化通用消息摘要上下文
    /* Initialize the generic message-digest context. */
    mbedtls_md_context_t sha_ctx;

    mbedtls_md_init(&sha_ctx);

    //通过hash算法来得到通用消息摘要上下文
    /* Get the generic message-digest context by hash algorithm. */
    const mbedtls_md_info_t *info_sha = mbedtls_md_info_from_type(md_type);

    if (info_sha == NULL) {
        log_error("info sha is invalid");
        return HKS_ERROR_INTERNAL_UNKOWN;
    }

    int32_t rc;

    do {
        //设置通用消息摘要上下文,简单理解成将info_sha的信息设置到sha_ctx通用消息摘要上下文地址下
        /* Setup the generic message-digest context. */
        rc = mbedtls_md_setup(&sha_ctx, info_sha,
            HKS_RKC_RMK_HMAC_FLAG);
        if (rc != HKS_SUCCESS) {
            log_error("setup mbedtls md fail,rc=%d", rc);
            break;
        }

        //利用PBKDF2-HMAC计算原始密钥rk的hash散列结果,结果存入派生密钥dk中
        /* PBKDF2-HMAC */
        rc = mbedtls_pkcs5_pbkdf2_hmac(&sha_ctx, raw_key->data,
            raw_key->size,
            salt->data, salt->size, iter_num, dk->size, dk->data);
        if (rc != HKS_SUCCESS) {
            log_error("mbedtls pbkdf2 hmac fail,rc=%d", rc);
            break;
        }
    } while (0);

    //释放通用信息摘要内容定义的空间
    /* Free the generic message-digest context. */
    mbedtls_md_free(&sha_ctx);
    if (rc != HKS_STATUS_OK)
        return HKS_ERROR_INTERNAL_UNKOWN;

    return HKS_STATUS_OK;
}

2. hks_rkc_get_rmk_raw_key

  • 函数功能:为根主密钥获取原始密钥
    root key component - get the raw key for derive root master key

  • 参数说明:为密钥库文件加载的数据、原始密钥(输出)
    parameter:
    ksf_data - [in] - the data which loaded from keystore file.
    raw_key - [out] - raw key

  • 返回值:成功或错误代码
    return value:
    success or error code

获取思路:用初始化材料与密钥库文件数据中的两个材料做异或,得到的结果即为原始密钥,并将其写入raw_key。
详细代码及评注如下:

static int32_t hks_rkc_get_rmk_raw_key(const struct hks_rkc_ksf_data *ksf_data,
    struct hks_blob *raw_key)
{
    //定义根密钥组件材料并初始化
    uint8_t material3[HKS_RKC_MATERIAL_LEN] = {0};

    //调用函数hks_rkc_get_fixed_material获取修复的材料
    /* Get the fixed material */
    int32_t rc = hks_rkc_get_fixed_material(material3, HKS_RKC_MATERIAL_LEN);

    if (rc != HKS_STATUS_OK)
        return rc;

    //材料之间按位做异或运算,得到的结果即为原始密钥
    /* materials xor */
    uint32_t i = 0;

    for (; i < HKS_RKC_MATERIAL_LEN; i++)
        raw_key->data[i] = (uint8_t)(ksf_data->rk_material1[i] ^
            ksf_data->rk_material2[i] ^ material3[i]);

    //附加硬件标识符,获取硬件唯一标识符存入原始密钥数据后,注意data的前HKS_RKC_MATERIAL_LEN位存的是异或后的材料
    /* append hardware UDID */
    rc = hks_get_hardware_udid(raw_key->data + HKS_RKC_MATERIAL_LEN,
        HKS_HARDWARE_UDID_LEN);
    if (rc != HKS_STATUS_OK)
        return rc;

    return HKS_STATUS_OK;
}

3. hks_rkc_derive_rmk

  • 函数功能:获取派生根主密钥
    root key component - derive root master key

  • 参数说明:为密钥库文件加载的数据、根主密钥(输出)、根主密钥长度
    parameter:
    ksf_data - [in] - the data which loaded from keystore file.
    rmk - [out] - root master key,
    使用后调用者必须清楚 it must be clear by caller after use.
    rmk_len - [in] - the length of root master key,
    它需要是64字节 it should be 64 bytes.

  • 返回值:成功或失败代码
    return value:
    success or error code

函数执行思路:
有密钥库文件数据ksf_data调用函数hks_rkc_get_rmk_raw_key,利用ksf_data中存储的密钥生成材料生成原始密钥raw_key,接着结合盐化量salt,通过调用函数hks_rkc_pbkdf2_hmac,经过pbkdf2_hmac算法生成派生密钥存入dk(derive key)中。
需要注意的是dk的定义为:struct hks_blob dk = { 0, rmk, rmk_len },本质上就是根主密钥rmk。
该函数的详细代码与评注如下:

static int32_t hks_rkc_derive_rmk(const struct hks_rkc_ksf_data *ksf_data,
    uint8_t *rmk, uint32_t rmk_len)
{
    //定义根密钥组件椒盐数据
    uint8_t salt_data[HKS_RKC_SALT_LEN] = {0};
    //将根密钥组件的密钥库文件数据中的根主密钥椒盐量ksf_data->rmk_salt复制到上面定义的椒盐数据变量salt_data中
    int32_t rc = memcpy_s(salt_data, HKS_RKC_SALT_LEN, ksf_data->rmk_salt,
        HKS_RKC_SALT_LEN);

    //判断系统状态是否成功生成了材料
    if (rc != HKS_STATUS_OK) {
        log_error("generate material fail,rc=%d", rc);
        return HKS_ERROR_INTERNAL_UNKOWN;
    }

    //定义并初始化派生密钥、椒盐、原始密钥数据
    struct hks_blob dk = { 0, rmk, rmk_len };//此处一旦dk确认,则rmk和rmk_len也随之确认,派生密钥即根主密钥信息
    struct hks_blob salt = { 0, salt_data, HKS_RKC_SALT_LEN };
    struct hks_blob raw_key;

    //初始化原始密钥raw_key,大小、类型、存储长度
    rc = hks_blob_init(&raw_key, sizeof(uint8_t), HKS_RKC_RAW_KEY_LEN,
        HKS_BLOB_TYPE_RAW);
    if (rc != HKS_STATUS_OK) {
        log_error("init raw key fail,rc=%d", rc);
        return rc;
    }

    do {
        //调用函数hks_rkc_get_rmk_raw_key(为根主密钥获取原始密钥函数)获取原始密钥
        /* get the raw key */
        rc = hks_rkc_get_rmk_raw_key(ksf_data, &raw_key);
        if (rc != HKS_STATUS_OK)
            break;

        //利用根主密钥的原始密钥raw_key结合PBKDF2-HMAC算法(调用函数hks_rkc_pbkdf2_hmac)获取派生根主密钥dk
        /* PBKDF2-HMAC */
        rc = hks_rkc_pbkdf2_hmac(ksf_data->rmk_hash_alg, &raw_key, &salt,
            ksf_data->rmk_iter, &dk);
        if (rc != HKS_STATUS_OK)
            break;
    } while (0);

    //释放空间(摧毁)原始密钥,以保证系统的安全
    hks_blob_destroy(&raw_key);

    return rc;
}

写所有密钥库文件

hks_rkc_write_all_ksf

  • 函数功能:写所有的密钥库文件
    root key component - write all keystore file

  • 参数说明:密钥库文件数据
    parameter:
    ksf_data - [in] - the data of keystore file.

  • 返回值:成功或错误代码
    return value:
    success or error code

此部分与文件服务hks_file.c部分相关,详细代码与评注如下:

static int32_t hks_rkc_write_all_ksf(const struct hks_rkc_ksf_data *ksf_data)
{
    //检查根密钥组件密钥库文件个数是否满足要求
    if (g_hks_rkc_cfg.ksf_attr.num > HKS_RKC_KSF_NUM) {
        log_error("invalid ksf num=%u", g_hks_rkc_cfg.ksf_attr.num);
        return HKS_ERROR_INTERNAL_UNKOWN;
    }

    uint32_t i = 0;
    int32_t rc;
    uint32_t success_num = 0;

    for (; i < g_hks_rkc_cfg.ksf_attr.num; ++i) {
        //跳过密钥库文件名为空的根密钥组件配置
        if (g_hks_rkc_cfg.ksf_attr.name[i] == NULL)
            continue;

        //调用写入密钥库文件函数,将ksf_data的数据写入密钥库文件名为g_hks_rkc_cfg.ksf_attr.name[i]的地址下
        rc = hks_rkc_write_ksf(g_hks_rkc_cfg.ksf_attr.name[i],
            ksf_data);
        //如果写入成功则进行计数
        if (rc != HKS_STATUS_OK)
            continue;
        ++success_num;
    }

    /* 如果所有密钥库文件写入失败,返回错误代码,否则,返回成功代码。
     * If all keystore file were wrotten fail, return error code,
     * otherwise, return success code.
     */
    //也就是说只要成功写入一个文件就返回成功
    if (success_num == 0)
        rc = HKS_ERROR_WRITE_FILE_FAIL;
    else
        rc = HKS_STATUS_OK;

    return rc;
}

本篇小结

本篇继续讲述了hks_rkc.c代码中有关密钥获取以及写所有密钥库文件的相关内容,下面将会继续更新有关密钥的加密以及密钥掩码的生成等相关函数,敬请期待。

<think>好的,我现在要解决用户关于TypeScript中如何让对象字面量符合特定类或接口的类型检查的问题。用户提到了HUKS_TAG_ALGORITHM、HUKS_ALG_RSA和HUKS_DIGEST_SHA256这些标识符,看起来像是某些库或框架中的常量,可能与加密或安全相关。首先,我需要理解用户的具体需求,然后一步步给出解决方案。 首先,用户的问题涉及到对象字面量的类型检查,明确声明接口,以及使用这些特定的常量。我需要回忆TypeScript中对象字面量类型检查的机制。通常,对象字面量在赋值给变量或传递给函数时,会进行“额外属性检查”,如果存在接口中没有定义的属性,会报错。但用户可能需要明确声明对象的结构,使其符合某个接口,尤其是包含特定属性的联合类型或枚举。 接下来,用户提到的HUKS_TAG_ALGORITHM可能是一个标签,而HUKS_ALG_RSA和HUKS_DIGEST_SHA256可能是该标签的可能值。例如,HUKS_TAG_ALGORITHM可能是一个属性名,其值可以是HUKS_ALG_RSA或HUKS_DIGEST_SHA256这样的枚举值。因此,我需要引导用户定义接口,明确这些属性的类型,可能使用联合类型或枚举。 然后,用户需要确保对象字面量符合这个接口。可能需要使用类型断言、变量间接赋值,或者as const断言来保持字面量的精确类型。此外,如果用户使用的库已经定义了这些接口或类型,直接引用它们会更方便,但用户可能需要自己定义。 可能的步骤是: 1. 定义接口,包含必要的属性,如HUKS_TAG_ALGORITHM,其类型为联合类型或枚举。 2. 创建对象字面量时,确保属性名和值符合接口定义。 3. 处理类型检查错误,如使用类型断言或变量赋值绕过额外属性检查。 还需要注意,用户可能需要处理多个属性,例如同时指定算法和摘要类型,因此接口可能需要包含多个属性,每个对应不同的HUKS_TAG。例如: interface HuksParams { [HUKS_TAG_ALGORITHM]: typeof HUKS_ALG_RSA; [HUKS_TAG_DIGEST]: typeof HUKS_DIGEST_SHA256; } 但用户需要确保这些常量是存在的,可能需要先声明它们,如枚举或常量对象。 可能的问题点: - 用户是否正确引用了这些常量,是否需要先定义它们? - 对象字面量是否有多余属性导致类型错误,如何处理? - 是否需要使用类型断言或as const来固定类型? 总结解决方案步骤: 1. 定义相关常量(如枚举或对象)。 2. 创建接口,使用索引签名或明确属性。 3. 声明对象字面量并应用类型检查方法。 现在需要将这些步骤整理成清晰的回答,并生成相关问题。</think>在TypeScript中,让对象字面量符合特定接口或类的类型要求,需通过以下步骤实现: ### 一、定义接口明确结构 若需匹配`HUKS_TAG_ALGORITHM`等加密参数,可先定义接口描述结构: ```typescript interface HuksAlgorithmParams { [HUKS_TAG_ALGORITHM]: number; // 假设HUKS_TAG_ALGORITHM是数值类型标签 [HUKS_TAG_DIGEST]?: number; // 可选属性用问号标记 } ``` > 注:需预先定义常量如`const HUKS_TAG_ALGORITHM = 0x100001`[^1] ### 二、声明对象字面量 #### 直接赋值(严格检查) ```typescript const rsaParams: HuksAlgorithmParams = { [HUKS_TAG_ALGORITHM]: HUKS_ALG_RSA, // 必须包含必选属性 [HUKS_TAG_DIGEST]: HUKS_DIGEST_SHA256 }; ``` > 若多出未定义属性将报错,可通过`as const`冻结类型: ```typescript const params = { [HUKS_TAG_ALGORITHM]: HUKS_ALG_RSA } as const; ``` #### 类型断言(绕过额外检查) ```typescript const params = { [HUKS_TAG_ALGORITHM]: HUKS_ALG_RSA, extraProp: true // 非常规属性 } as HuksAlgorithmParams; ``` ### 三、联合类型约束 若参数存在多种组合,可通过联合类型定义: ```typescript type HuksParams = | { [HUKS_TAG_ALGORITHM]: typeof HUKS_ALG_RSA; [HUKS_TAG_KEY_SIZE]: 2048 } | { [HUKS_TAG_ALGORITHM]: typeof HUKS_ALG_AES; [HUKS_TAG_KEY_MODE]: typeof HUKS_MODE_CBC }; ``` ### 四、实战示例 ```typescript // 先定义常量枚举 enum HuksTag { ALGORITHM = 0x100001, DIGEST = 0x200002 } enum HuksAlg { RSA = 0x0100, AES = 0x0200 } // 定义接口 interface RsaParams { [HuksTag.ALGORITHM]: HuksAlg.RSA; [HuksTag.DIGEST]: number; } // 正确对象 const validRsa: RsaParams = { [HuksTag.ALGORITHM]: HuksAlg.RSA, [HuksTag.DIGEST]: 0x0300 }; // 错误示例(缺少必需属性) const invalidRsa: RsaParams = { [HuksTag.ALGORITHM]: HuksAlg.RSA }; // 报错:缺少DIGEST属性 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值