密钥生成和适配转换的各类函数
知识分享
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