security_huks/service/huks_service/src/hks_client_service_adapter_lite解读

知识分享

X509

定义:密码学里公钥证书的格式标准

应用:X509证书会应用在包括TLS/SSL的众多Internet协议里,也应用于电子签名等服务中

内容:包含了公钥和各种标识(ip id等),数字签名

结构:
● Certificate 证书

● Version Number版本号

● Serial Number序列号

● ID Signature Algorithm ID签名算法

● Issuer Name颁发者名称

● Validity period 有效期

● Not before起始日期

● Not after截至日期

● Subject Name主题名称

● Subject pbulic Key Info 主题公钥信息

● Public Key Algorithm公钥算法

● Subject Public Key主题公钥

● Issuer Unique Identifier (optional)颁发者唯一标识符(可选)

● Subject Unique Identifier (optional)主题唯一标识符(可选)

● Extensions (optional) 证书的扩展项(可选)

● Certificate Sigature Algorithm证书签名算法

● Certificate Signature证书的签名

总体概述

该部分主要是轻量级的各种类型(RSA ECC Curve25519)密钥的生成和类型的转换

从代码可以看出来轻量级的应用(lite)的密码框架大多使用的是mbedtls的各种接口函数,而一般的应用部署的密钥生成和管理的框架是openSSL

代码解读

1.密钥的生成相关函数

1.1 PkCtxToX509

函数功能:从mbedtls_pk_context中提取出x509Key

函数实现:首先从参数ctx中写pubKey到temBuf中---->小段模式得到X509格式标准的数据

注意!这里do{}while(0)的使用就是避免使用goto破坏代码的结构性

//从mbedtls_pk_context中提取出x509Key
static int32_t PkCtxToX509(mbedtls_pk_context *ctx, struct HksBlob *x509Key)
{
    uint8_t *tmpBuf = (uint8_t *)HksMalloc(MAX_KEY_SIZE);
    if (tmpBuf == NULL) {
        return HKS_ERROR_MALLOC_FAIL;
    }

    int32_t ret = HKS_SUCCESS;
    do {
        //从ctx中写pubKey到tmpBuf中
        int32_t x509Size = mbedtls_pk_write_pubkey_der(ctx, tmpBuf, MAX_KEY_SIZE);
        if (x509Size < HKS_MBEDTLS_SUCCESS) {
            HKS_LOG_E("public key to x509 write der failed! mbedtls ret = 0x%X", x509Size);
            ret = x509Size;
            break;
        }

        uint8_t *x509KeyData = (uint8_t *)HksMalloc(x509Size);
        if (x509KeyData == NULL) {
            HKS_LOG_E("Malloc x509 key data failed!");
            ret = HKS_ERROR_MALLOC_FAIL;
            break;
        }

        //小端模式得到x509Key的数据
        /* mbedtls_pk_write_pubkey_der use little-endian for storage */
        if (memcpy_s(x509KeyData, x509Size, tmpBuf + MAX_KEY_SIZE - x509Size, x509Size) != EOK) {
            HKS_LOG_E("public key to x509 memcpy to x509key failed!");
            HKS_FREE_PTR(x509KeyData);
            ret = HKS_ERROR_BAD_STATE;
            break;
        }

        x509Key->size = x509Size;
        x509Key->data = x509KeyData;
    } while (0);

    HKS_FREE_PTR(tmpBuf);
    return ret;
}

1.2 InitRsaPkCtx

函数功能:进行RSA密钥的生成得到ctx

函数实现:调用mbedtls_pk_setup根据传入的type进行不同类型密钥的生成---->然后读取两个参数N和E---->然后进行RSA密钥的生成

//进行RSA密钥的生成得到ctx
static int32_t InitRsaPkCtx(const struct HksBlob *mod, const struct HksBlob *e, mbedtls_pk_context *ctx)
{
    //公钥的建立
    int32_t ret = mbedtls_pk_setup(ctx, mbedtls_pk_info_from_type(MBEDTLS_PK_RSA));
    if (ret != HKS_MBEDTLS_SUCCESS) {
        HKS_LOG_E("Mbedtls setup pk context failed! mbedtls ret = 0x%X", ret);
        return ret;
    }

    mbedtls_mpi mpiN;
    mbedtls_mpi mpiE;

    mbedtls_mpi_init(&mpiN);
    mbedtls_mpi_init(&mpiE);

    do {
        //读取mod
        ret = mbedtls_mpi_read_binary(&mpiN, mod->data, mod->size);
        if (ret != HKS_MBEDTLS_SUCCESS) {
            HKS_LOG_E("Hks init rsa pk context read N failed! mbedtls ret = 0x%X", ret);
            break;
        }
        //读取e
        ret = mbedtls_mpi_read_binary(&mpiE, e->data, e->size);
        if (ret != HKS_MBEDTLS_SUCCESS) {
            HKS_LOG_E("Hks init rsa pk context read E failed! mbedtls ret = 0x%X", ret);
            break;
        }

        //进行RSA密钥的生成
        mbedtls_rsa_context *rsaCtx = mbedtls_pk_rsa(*ctx);
        ret = mbedtls_rsa_import(rsaCtx, &mpiN, NULL, NULL, NULL, &mpiE);
        if (ret != HKS_MBEDTLS_SUCCESS) {
            HKS_LOG_E("Hks init rsa pk context import rsa context failed! mbedtls ret = 0x%X", ret);
            break;
        }

        ret = mbedtls_rsa_complete(rsaCtx);
        if (ret != HKS_MBEDTLS_SUCCESS) {
            HKS_LOG_E("Hks init rsa pk context complete rsa context failed! mbedtls ret = 0x%X", ret);
        }
    } while (0);

    mbedtls_mpi_free(&mpiN);
    mbedtls_mpi_free(&mpiE);
    return ret;
}

1.3 RsaToX509PublicKey

函数功能:生成RSA密钥并提取其中的X509公钥

函数实现:调用前面写好的函数进行RSA密钥的生成和ctx中X509Key的提取

在这里插入图片描述

1.4 EccToX509PublicKey

函数功能:与RSA算法类似,都是先调用Init函数进行关键参数的生成,然后对其中的ECC密钥转换为X509Key

生成密钥的算法框架都是调用mbedtls框架内的功能函数,详细的介绍会放在后面

//得到ECC公钥
static int32_t InitEccPkCtx(uint32_t keySize, const struct HksBlob *x, const struct HksBlob *y,
    mbedtls_pk_context *ctx)
{
    //根据type生成ECC类型密钥
    int32_t ret = mbedtls_pk_setup(ctx, mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY));
    if (ret != HKS_MBEDTLS_SUCCESS) {
        HKS_LOG_E("Mbedtls setup pk context failed! mbedtls ret = 0x%X", ret);
        return ret;
    }

    //获取groupId
    mbedtls_ecp_group_id grp_id;
    ret = GetEccGroupId(keySize, &grp_id);
    if (ret != HKS_SUCCESS) {
        HKS_LOG_E("Get ecc group id failed! ret = 0x%X", ret);
        return ret;
    }
    //进行ECC公钥的生成得到pubKey
    mbedtls_ecp_keypair *pubKey = mbedtls_pk_ec(*ctx);
    ret = mbedtls_ecp_group_load(&(pubKey->grp), grp_id);
    if (ret != HKS_MBEDTLS_SUCCESS) {
        HKS_LOG_E("Hks init ecc pk context load group failed! mbedtls ret = 0x%X", ret);
        return ret;
    }

    ret = mbedtls_mpi_read_binary(&(pubKey->Q.X), x->data, x->size);
    if (ret != HKS_MBEDTLS_SUCCESS) {
        HKS_LOG_E("Hks init ecc pk context read X failed! mbedtls ret = 0x%X", ret);
        return ret;
    }

    ret = mbedtls_mpi_read_binary(&(pubKey->Q.Y), y->data, y->size);
    if (ret != HKS_MBEDTLS_SUCCESS) {
        HKS_LOG_E("Hks init ecc pk context read Y failed! mbedtls ret = 0x%X", ret);
        return ret;
    }

    /* Z = 1, X and Y are its standard (affine) coordinates */
    ret = mbedtls_mpi_lset(&(pubKey->Q.Z), 1);
    if (ret != HKS_MBEDTLS_SUCCESS) {
        HKS_LOG_E("Hks init ecc pk context set Z failed! mbedtls ret = 0x%X", ret);
        return ret;
    }

    return HKS_SUCCESS;
}

//从ECC生成的密钥得到X509公钥
static int32_t EccToX509PublicKey(uint32_t keySize, const struct HksBlob *x, const struct HksBlob *y,
    struct HksBlob *x509Key)
{
    mbedtls_pk_context ctx;
    mbedtls_pk_init(&ctx);

    int32_t ret;
    do {
        ret = InitEccPkCtx(keySize, x, y, &ctx);
        if (ret != HKS_SUCCESS) {
            break;
        }

        ret = PkCtxToX509(&ctx, x509Key);
        if (ret != HKS_SUCCESS) {
            HKS_LOG_E("Pk context to ecc x509 failed! ret = 0x%X", ret);
        }
    } while (0);

    mbedtls_pk_free(&ctx);
    return ret;
}

1.5 Curve25519ToX509PublicKey

函数功能:数据转移从publicKey转移到X509Key中

在这里插入图片描述

1.6 TranslateToX509PublicKey

函数功能:将上述的三种加密算法得到的公钥转换为X509标准公钥

相当于一个封装的功能函数,封装的意义在于同意调度和参数检查,所以当由支持四种算法中的任何一个宏定义出现时,进行该函数的调用:首先对公钥的内容进行非空检查和size检查---->然后根据算法的不同进行参数的获取与构造(material)---->最后根据keyAlg使用switch-case语句进行密钥的生成和X509标准Key

//将上述的三种加密算法得到的公钥转换为X509标准公钥
int32_t TranslateToX509PublicKey(const struct HksBlob *publicKey, struct HksBlob *x509Key)
{
#if defined(HKS_SUPPORT_RSA_C) || defined(HKS_SUPPORT_ECC_C) || defined(HKS_SUPPORT_X25519_C) || \
    defined(HKS_SUPPORT_ED25519_C)
    if ((publicKey == NULL) || (publicKey->data == NULL) || (publicKey->size == 0) || (x509Key == NULL)) {
        HKS_LOG_E("translate to x509 public key invalid args");
        return HKS_ERROR_INVALID_ARGUMENT;
    }

    if (publicKey->size < sizeof(struct HksPubKeyInfo)) {
        HKS_LOG_E("translate to x509 public key invalid publicKey size");
        return HKS_ERROR_INVALID_ARGUMENT;
    }

    struct HksPubKeyInfo *publicKeyInfo = (struct HksPubKeyInfo *)publicKey->data;
    uint32_t offset = sizeof(struct HksPubKeyInfo);
    //size检查
    if ((publicKey->size - offset) < publicKeyInfo->nOrXSize) {
        HKS_LOG_E("translate to x509 public key invalid nOrXSize size");
        return HKS_ERROR_INVALID_ARGUMENT;
    }

    struct HksBlob material1 = { publicKeyInfo->nOrXSize, publicKey->data + offset };
    offset += publicKeyInfo->nOrXSize;
    if ((publicKey->size - offset) < publicKeyInfo->eOrYSize) {
        HKS_LOG_E("translate to x509 public key invalid eOrYSize size");
        return HKS_ERROR_INVALID_ARGUMENT;
    }

#if defined(HKS_SUPPORT_RSA_C) || defined(HKS_SUPPORT_ECC_C)
    //当使用了RSA或者ECC时需要第二个material参数
    struct HksBlob material2 = { publicKeyInfo->eOrYSize, publicKey->data + offset };
#endif
    //根据keyAlg判断使用哪种方法生成公钥并转换为X509标准公钥
    switch (publicKeyInfo->keyAlg) {
#ifdef HKS_SUPPORT_RSA_C
        case HKS_ALG_RSA:
            return RsaToX509PublicKey(&material1, &material2, x509Key);
#endif
#ifdef HKS_SUPPORT_ECC_C
        case HKS_ALG_ECC:
            return EccToX509PublicKey(publicKeyInfo->keySize, &material1, &material2, x509Key);
#endif
#if defined(HKS_SUPPORT_X25519_C) || defined(HKS_SUPPORT_ED25519_C)
        case HKS_ALG_X25519:
        case HKS_ALG_ED25519:
            return Curve25519ToX509PublicKey(&material1, x509Key);
#endif
        default:
            HKS_LOG_E("Unsupport alg type! type = 0x%X", publicKeyInfo->keyAlg);
            return HKS_ERROR_INVALID_ARGUMENT;
    }
#else
    (void)publicKey;
    (void)x509Key;
    return HKS_ERROR_NOT_SUPPORTED;
#endif
}

2.对于各类型密钥载体的检查函数

2.1 CheckRsaCtx

函数功能:对于rsaCtx->len进行检查

2.2 CheckEccXySize

函数功能:对于XY进行size检查

3.从X509标准Key转换为各个类型算法公钥的函数

3.1X509PublicKeyToRsa

函数功能:将X509标准的密钥转换为HksBlob类型的公钥

函数实现:首先对于rsaCtx->len进行检查---->将rsaCtx中的信息进行提取封装---->两个write函数写入N和E---->将得到的数据封装入rsaPublicKey

//转换为RSA HksBlob类型的公钥
static int32_t X509PublicKeyToRsa(mbedtls_rsa_context *rsaCtx, struct HksBlob *rsaPublicKey)
{
    //对于rsaCtx->len进行检查
    int32_t ret = CheckRsaCtx(rsaCtx);
    if (ret != HKS_SUCCESS) {
        HKS_LOG_E("Check rsa ctx failed! ret = 0x%X", ret);
        return ret;
    }

    uint32_t nSize = rsaCtx->len;
    uint32_t eSize = rsaCtx->len;

    uint32_t totalSize = sizeof(struct HksPubKeyInfo) + nSize + eSize;
    uint8_t *keyBuffer = (uint8_t *)HksMalloc(totalSize);
    if (keyBuffer == NULL) {
        HKS_LOG_E("X509 public key to rsa malloc keyBuffer failed!");
        return HKS_ERROR_MALLOC_FAIL;
    }

    //将rsaCtx中的信息进行提取封装
    struct HksPubKeyInfo *pubKeyInfo = (struct HksPubKeyInfo *)keyBuffer;
    pubKeyInfo->keyAlg = HKS_ALG_RSA;
    pubKeyInfo->keySize = rsaCtx->len * HKS_BITS_PER_BYTE;
    pubKeyInfo->nOrXSize = nSize;
    pubKeyInfo->eOrYSize = eSize;
    pubKeyInfo->placeHolder = 0;

    //两个write函数写入N和E
    ret = mbedtls_mpi_write_binary(&rsaCtx->N, keyBuffer + sizeof(struct HksPubKeyInfo), nSize);
    if (ret != HKS_MBEDTLS_SUCCESS) {
        HKS_LOG_E("X509 public key to rsa write N failed! mbedtls ret = 0x%X", ret);
        HKS_FREE_PTR(keyBuffer);
        return ret;
    }

    ret = mbedtls_mpi_write_binary(&rsaCtx->E, keyBuffer + sizeof(struct HksPubKeyInfo) + nSize, eSize);
    if (ret != HKS_MBEDTLS_SUCCESS) {
        HKS_LOG_E("X509 public key to rsa write E failed! mbedtls ret = 0x%X", ret);
        HKS_FREE_PTR(keyBuffer);
        return ret;
    }

    rsaPublicKey->data = keyBuffer;
    rsaPublicKey->size = totalSize;

    return HKS_SUCCESS;
}

3.2 X509PublicKeyToEcc

函数功能:将X509标准公钥转换到eccPublicKey中

//将X509Key转换为ECC
static int32_t X509PublicKeyToEcc(mbedtls_ecp_keypair *pubKey, struct HksBlob *eccPublicKey)
{
    //获取XY的size参数
    uint32_t xSize = mbedtls_mpi_size(&(pubKey->Q.X));
    uint32_t ySize = mbedtls_mpi_size(&(pubKey->Q.Y));

    //进行XY的size检查
    int32_t ret = CheckEccXySize(xSize, ySize);
    if (ret != HKS_SUCCESS) {
        HKS_LOG_E("Check ecc public key size failed! ret = 0x%X", ret);
        return ret;
    }

    uint32_t totalSize = sizeof(struct HksPubKeyInfo) + xSize + ySize;
    uint8_t *keyBuffer = (uint8_t *)HksMalloc(totalSize);
    if (keyBuffer == NULL) {
        HKS_LOG_E("X509 public key to ecc malloc keyBuffer failed!");
        return HKS_ERROR_MALLOC_FAIL;
    }

    //进行pubKeyInfo的构造
    struct HksPubKeyInfo *pubKeyInfo = (struct HksPubKeyInfo *)keyBuffer;
    pubKeyInfo->keyAlg = HKS_ALG_ECC;
    pubKeyInfo->keySize = mbedtls_mpi_size(&(pubKey->grp.P)) * HKS_BITS_PER_BYTE;
    pubKeyInfo->nOrXSize = xSize;
    pubKeyInfo->eOrYSize = ySize;
    pubKeyInfo->placeHolder = 0;

    ret = mbedtls_mpi_write_binary(&(pubKey->Q.X), keyBuffer + sizeof(struct HksPubKeyInfo), xSize);
    if (ret != HKS_MBEDTLS_SUCCESS) {
        HKS_LOG_E("X509 public key to ecc write X failed! mbedtls ret = 0x%X", ret);
        HKS_FREE_PTR(keyBuffer);
        return ret;
    }

    ret = mbedtls_mpi_write_binary(&(pubKey->Q.Y), keyBuffer + sizeof(struct HksPubKeyInfo) + xSize, ySize);
    if (ret != HKS_MBEDTLS_SUCCESS) {
        HKS_LOG_E("X509 public key to ecc write Y failed! mbedtls ret = 0x%X", ret);
        HKS_FREE_PTR(keyBuffer);
        return ret;
    }

    eccPublicKey->data = keyBuffer;
    eccPublicKey->size = totalSize;

    return HKS_SUCCESS;
}

3.3TranslateFromX509PublicKey

函数功能:封装根据ctx中的type和宏定义调用上述封装函数进行X509Key的转换(RSA ECC)

//封装根据ctx中的type和宏定义调用上述封装函数进行X509Key的转换(RSA ECC)
int32_t TranslateFromX509PublicKey(const struct HksBlob *x509Key, struct HksBlob *publicKey)
{
    mbedtls_pk_context ctx;
    mbedtls_pk_init(&ctx);
    //解析x509Key得到ctx
    int32_t ret = mbedtls_pk_parse_public_key(&ctx, x509Key->data, x509Key->size);
    if (ret != HKS_MBEDTLS_SUCCESS) {
        mbedtls_pk_free(&ctx);
        return HKS_ERROR_INVALID_ARGUMENT;
    }

    /* 1: if the context can do operations on the given type. */
    if (mbedtls_pk_can_do(&ctx, MBEDTLS_PK_RSA) == 1) {
#ifdef HKS_SUPPORT_RSA_C
        ret = X509PublicKeyToRsa(mbedtls_pk_rsa(ctx), publicKey);
#else
        ret = HKS_ERROR_INVALID_ALGORITHM;
#endif
    } else if (mbedtls_pk_can_do(&ctx, MBEDTLS_PK_ECKEY) == 1) {
#ifdef HKS_SUPPORT_ECC_C
        ret = X509PublicKeyToEcc(mbedtls_pk_ec(ctx), publicKey);
#else
        ret = HKS_ERROR_INVALID_ALGORITHM;
#endif
    } else {
        HKS_LOG_E("Unsupport alg type!");
        ret = HKS_ERROR_INVALID_ARGUMENT;
    }

    mbedtls_pk_free(&ctx);
    return ret;
}

3.4TranslateToInnerCurve25519Format

3.5TranslateToInnerAesFormat

两个转换函数将key中的信息转换为publicKey

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

国家一级假勤奋研究牲

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值