hks_crypto_ed25519.c代码分析

一、背景知识

 

二、代码分析

定义相关变量,定义公钥和私钥的字节数

#define CRYPTO_SUCCESS 1  //存放返回值表示加密成功
#define ED25519_PRIVATE_KEY_LEN 32 //私钥字节数32
#define ED25519_PUBLIC_KEY_LEN 32  //公钥字节数32

密钥信息保存
实现公钥私钥数据的复制保存。
参数详解:

  • pubKey:传入存放公钥数据的结构体
  • prikey:传入存放私钥数据的结构体
  • keyout:存放最后整合的结果
//保存密钥内容和相关信息
static int32_t SaveEd25519KeyMaterial(const struct HksBlob *pubKey, const struct HksBlob *priKey,
    struct HksBlob *keyOut)
{
    uint32_t totalSize = sizeof(struct KeyMaterial25519) + pubKey->size + priKey->size;
    //定义totalsize = 公钥长度加私钥长度加KeyMaterial25519结构体长度
    uint8_t *buffer = (uint8_t *)HksMalloc(totalSize);
    //申请一个tatalsize大小的缓冲区
    if (buffer == NULL) {
        return HKS_ERROR_MALLOC_FAIL;
    }

    struct KeyMaterial25519 *keyMaterial = (struct KeyMaterial25519 *)buffer;
    keyMaterial->keyAlg = HKS_ALG_ED25519;
    keyMaterial->keySize = HKS_CURVE25519_KEY_SIZE_256;
    keyMaterial->pubKeySize = pubKey->size;
    keyMaterial->priKeySize = priKey->size;
    //将公钥和私钥长度写进刚申请的结构体变量
    keyMaterial->reserved = 0;

    uint32_t offset = sizeof(struct KeyMaterial25519);
    if (memcpy_s(buffer + offset, pubKey->size, pubKey->data, pubKey->size) != EOK) {
        //将公钥内容写进buffer,偏置offset
        HKS_LOG_E("copy ed25519 public key failed");
        (void)memset_s(buffer, totalSize, 0, totalSize);
        //写入失败则初始化buffer内容然后释放空间
        HKS_FREE_PTR(buffer);
        return HKS_ERROR_BAD_STATE;
    }
    offset += pubKey->size;
    //将偏执变量往后移动公钥字节长度,可以当作一个游标用老切分数组
    if (memcpy_s(buffer + offset, priKey->size, priKey->data, priKey->size) != EOK) {
        //将私钥内容写进buffer缓冲区,以offset为偏置
        HKS_LOG_E("copy ed25519 private key failed");
        (void)memset_s(buffer, totalSize, 0, totalSize);
        HKS_FREE_PTR(buffer);
        //写入失败就初始化buffer,然后释放内存
        return HKS_ERROR_BAD_STATE;
    }

    keyOut->data = buffer;
    keyOut->size = totalSize;
    //最后将buffer关联在keyout.data,tatalsize赋值在keyout.size上,函数结束
    return HKS_SUCCESS;
}

检查是否全0

//检查key的数据域是否为全零
static bool IsBlobZero(const struct HksBlob *key)
{
    for (uint32_t i = 0; i < key->size; ++i) {
        if (key->data[i] != 0) {
            return false;
        }
    }
    return true;
}

实现私钥公钥的生成
使用随机数生成私钥,基于私钥计算得到公钥数据。

//生成密钥
int32_t HksEd25519GenerateKey(struct HksBlob *keyOut)
{
    uint8_t pubKey[ED25519_PUBLIC_KEY_LEN] = {0};
    uint8_t priKey[ED25519_PRIVATE_KEY_LEN] = {0};
    //定义两个数组来存放公钥私钥
    struct HksBlob pubKeyBlob = { ED25519_PUBLIC_KEY_LEN, pubKey };
    struct HksBlob priKeyBlob = { ED25519_PRIVATE_KEY_LEN, priKey };
    //定义两个hksblob结构体,存放公钥私钥等相关信息
    struct HksBlob tmp = { ED25519_PUBLIC_KEY_LEN, priKeyBlob.data }; //申请一个临时变量
    int32_t ret = HksCryptoHalFillRandom(&tmp);
    //将随机数据写进临时的私钥结构体
    if (ret != HKS_SUCCESS) {
        return ret;
    }

    ED25519_public_from_private(pubKeyBlob.data, priKeyBlob.data);
    //由私钥数据得到公钥数据
    if (IsBlobZero(&pubKeyBlob) || IsBlobZero(&priKeyBlob)) {
    //判断这两个数据域是否全零
        return HKS_ERROR_CRYPTO_ENGINE_ERROR;
    }

    return SaveEd25519KeyMaterial(&pubKeyBlob, &priKeyBlob, keyOut);
    //最后将详细内容写进keyout结构体
}

检查密钥的size问题

#endif /* HKS_SUPPORT_ED25519_GENERATE_KEY */
//检查相关参数
static int32_t CheckEd25519Material(const struct HksBlob *key)
{
    uint32_t totalSize = sizeof(struct KeyMaterial25519);
    if (key->size < totalSize) {
        HKS_LOG_E("Ed25519 key material too small");
        return HKS_ERROR_INVALID_KEY_INFO;
    //检查密钥尺寸size
    }

    struct KeyMaterial25519 *km = (struct KeyMaterial25519 *)key->data;
    if (((key->size - totalSize) < km->pubKeySize) ||
        ((key->size - totalSize) < km->priKeySize) ||
        ((key->size - totalSize) < (km->pubKeySize + km->priKeySize))) {
        HKS_LOG_E("Ed25519 key material wrong pub and pri key size %u, %u, %u",
            key->size, km->pubKeySize, km->priKeySize);
    //检查key.size-totalsize和数据区域各密钥的长度关系
        return HKS_ERROR_INVALID_KEY_INFO;
    }

    return HKS_SUCCESS;
}

检查公钥以及结果存放的变量size

#ifdef HKS_SUPPORT_ED2519_GET_PUBLIC_KEY
static int32_t GetEd25519PubKeyCheck(const struct HksBlob *key, const struct HksBlob *keyOut)
{
    int32_t ret = CheckEd25519Material(key);
    if (ret != HKS_SUCCESS) {
        return ret;
    }
    //先检查相关参数
    /* check keyOut */
    struct KeyMaterial25519 *km = (struct KeyMaterial25519 *)key->data;
    if ((km->pubKeySize > (INT32_MAX - sizeof(struct KeyMaterial25519))) ||
        (keyOut->size < (sizeof(struct KeyMaterial25519) + km->pubKeySize))) {
        HKS_LOG_E("Ecc public keyOut size too small! keyOut size = 0x%X", keyOut->size);
        return HKS_ERROR_BUFFER_TOO_SMALL;
    //检查keyout.size是否足够大可以存放公钥
    }

    return HKS_SUCCESS;
}

对输出数据output结构体进行检查以及部分值的初始化

int32_t HksGetEd25519PubKey(const struct HksBlob *input, struct HksBlob *output)
{
    int32_t ret = GetEd25519PubKeyCheck(input, output);
    //先检查两个结构体的大小
    if (ret != HKS_SUCCESS) {
        return ret;
    }

    struct KeyMaterial25519 *key = (struct KeyMaterial25519 *)input->data;
    uint32_t outLen = sizeof(struct KeyMaterial25519) + key->pubKeySize;
    if (memcpy_s(output->data, output->size, key, outLen) != EOK) {
    //初始化输出结构体的数据域
        HKS_LOG_E("memcpy_s ed25519 pub key failed");
        return HKS_ERROR_BAD_STATE;
    }

    ((struct KeyMaterial25519 *)output->data)->priKeySize = 0; //输出数据的私钥长度先置为0
    output->size = outLen; //输出的大小为公钥大小加结构体的大小
    return HKS_SUCCESS;
}

签名算法,基于ed25519_sign()函数

#endif
//签名算法
#ifdef HKS_SUPPORT_ED25519_SIGN_VERIFY
int32_t HksEd25519Sign(const struct HksBlob *key, const struct HksBlob *message, struct HksBlob *signature)
{
    int32_t ret = CheckEd25519Material(key);
    if (ret != HKS_SUCCESS) {
        return ret;
    }
    if (signature->size < HKS_SIGNATURE_MIN_SIZE) {
        return HKS_ERROR_INVALID_ARGUMENT;
    }
    //先对参数进行检查
    ret = ED25519_sign(signature->data, message->data, message->size,
        key->data + sizeof(struct KeyMaterial25519),
        key->data + sizeof(struct KeyMaterial25519) + ED25519_PUBLIC_KEY_LEN);
    //生成签名过程,该功能封装在ED25519_sign函数中
    if (ret != CRYPTO_SUCCESS) {
        HKS_LOG_E("ED25519_sign failed");
        return HKS_ERROR_CRYPTO_ENGINE_ERROR;
    }
    signature->size = HKS_SIGNATURE_MIN_SIZE;//初始化签名域大小

    return HKS_SUCCESS;
}

签名的验证 基于edd25519_verify()函数

//ed25519的验证过程
int32_t HksEd25519Verify(const struct HksBlob *key, const struct HksBlob *message,
    const struct HksBlob *signature)
{
    int32_t ret = CheckEd25519Material(key);
    if (ret != HKS_SUCCESS) {
        return ret;
    }
    if (signature->size < HKS_SIGNATURE_MIN_SIZE) {
        return HKS_ERROR_INVALID_ARGUMENT;
    }
    //上面部分先检查参数的size等问题                        
    ret = ED25519_verify(message->data, message->size, signature->data,
        key->data + sizeof(struct KeyMaterial25519));
    //调用封装好的函数ED25519_verify进行验证签名
    if (ret != CRYPTO_SUCCESS) {
        HKS_LOG_E("ED25519_verify failed");
        return HKS_ERROR_CRYPTO_ENGINE_ERROR;
    }

    return HKS_SUCCESS;
}

三、总结

以上为ed25519算法在hks中的代码体现,实现了公私钥的生成和签名生成以及验证的过程。欢迎阅读和点赞。