赞
踩
自己对代码的一些见解
这里主要是使用mbedtls库中aes对应的一些函数,该库中将功能基本封装好。鸿蒙这里进行了进一步的适配和封装。主要实现一些密钥的生成,加解密的实现。这里的加解密相比其他文件有一个特殊点:就是加解密都封装在一个函数内,在函数形参中传入逻辑变量来实现。相当于一个开关变量,开的时候实现加密,关闭的时候实现解密。真正的封装好各部分功能。
aes算法介绍链接:
1.密钥的生成
实现最基础的密钥生成(基于随机数的生成实现密钥生成,填写随机数据进key中data)
//密钥的生成 int32_t HksMbedtlsAesGenerateKey(const struct HksKeySpec *spec, struct HksBlob *key) { const uint32_t keyByteLen = spec->keyLen / HKS_BITS_PER_BYTE; uint8_t *outKey = (uint8_t *)HksMalloc(keyByteLen); //先申请空间用来存放随机数据(密钥数据) if (outKey == NULL) { return HKS_ERROR_MALLOC_FAIL; } mbedtls_entropy_context entropy; mbedtls_ctr_drbg_context ctrDrbg; int32_t ret = HksCtrDrbgSeed(&ctrDrbg, &entropy); //随机数种子(熵源) if (ret != HKS_SUCCESS) { HKS_FREE_PTR(outKey); return ret; } do { ret = mbedtls_ctr_drbg_random(&ctrDrbg, outKey, keyByteLen); //在对应空间outkey生成随机数 if (ret != HKS_MBEDTLS_SUCCESS) { HKS_LOG_E("Mbedtls ctr drbg random failed! mbedtls ret = 0x%X", ret); (void)memset_s(outKey, keyByteLen, 0, keyByteLen); HKS_FREE_PTR(outKey); break; } //将最后结果写进key的数据域和size key->data = outKey; key->size = keyByteLen; } while (0); mbedtls_ctr_drbg_free(&ctrDrbg); mbedtls_entropy_free(&entropy); //释放随机数空间和熵源 return ret; }
2.aes/cbc在nopadding模式下的加密
第一种加密模式,其中参数最重要的个人认为是这个bool变量 encrypt。他象个开关控制是加密还是解密。
参数介绍:
static int32_t AesCbcNoPaddingCrypt(const struct HksBlob *key, const struct HksCipherParam *cipherParam, const struct HksBlob *message, const bool encrypt, struct HksBlob *cipherText) { mbedtls_aes_context ctx; mbedtls_aes_init(&ctx); int32_t ret; do { if (encrypt) { ret = mbedtls_aes_setkey_enc(&ctx, key->data, key->size * HKS_BITS_PER_BYTE); //根据传入的参数,如果为逻辑真就设置一套加密密钥 } else { ret = mbedtls_aes_setkey_dec(&ctx, key->data, key->size * HKS_BITS_PER_BYTE); } //如果为逻辑假就设置一套解密密钥 if (ret != HKS_MBEDTLS_SUCCESS) { HKS_LOG_E("Mbedtls aes set key failed! mbedtls ret = 0x%X", ret); break; } /* mbedtls_aes_crypt_cbc will refresh iv, so need a temp iv */ uint8_t tmpIv[HKS_AES_CBC_NOPADDING_IV_SIZE]; //定义一组临时向量iv if (memcpy_s(tmpIv, HKS_AES_CBC_NOPADDING_IV_SIZE, cipherParam->iv.data, cipherParam->iv.size) != EOK) { HKS_LOG_E("Memcpy temp iv failed!"); break; } //初始化tmpiv的空间为cipherParam->iv.data ret = mbedtls_aes_crypt_cbc(&ctx, (encrypt ? MBEDTLS_AES_ENCRYPT : MBEDTLS_AES_DECRYPT), message->size, tmpIv, message->data, cipherText->data); //加解密的实现,根据逻辑值判断为加密还是解密 if (ret != HKS_MBEDTLS_SUCCESS) { HKS_LOG_E("Mbedtks aes cbc crypt failed! mbedtls ret = 0x%X", ret); (void)memset_s(cipherText->data, cipherText->size, 0, cipherText->size); break; } cipherText->size = message->size; //将最后加密后的message内容写进密文 } while (0); mbedtls_aes_free(&ctx); //释放相关空间ctx return ret; }
3.aes/cbc在pkcs7下的加密
该函数也是一种加解密的方式,上一种是nopadding,着一种是okcs7的方法。参数功能基本相似。
参数介绍:
//pkcs7的加解密 static int32_t AesCbcPkcs7Crypt(const struct HksBlob *key, const struct HksCipherParam *cipherParam, const struct HksBlob *message, const bool encrypt, struct HksBlob *cipherText) { const uint32_t keyBitLen = key->size * HKS_BITS_PER_BYTE; //密钥的位长度 const mbedtls_cipher_info_t *info = mbedtls_cipher_info_from_values(MBEDTLS_CIPHER_ID_AES, keyBitLen, MBEDTLS_MODE_CBC); //村数组中获取密文信息 mbedtls_cipher_context_t ctx; mbedtls_cipher_init(&ctx); //cipher变量初始化 int32_t ret; do { ret = mbedtls_cipher_setup(&ctx, info); //以指定信息设置ctx if (ret != HKS_SUCCESS) { HKS_LOG_E("Mbedtls cbc pkcs7 setup ctx failed! mbedtls ret = 0x%X", ret); break; } ret = mbedtls_cipher_setkey(&ctx, key->data, keyBitLen, (encrypt ? MBEDTLS_ENCRYPT : MBEDTLS_DECRYPT)); //根据encrypt传入的逻辑值来判断是要设置加密密文还是解密密文 if (ret != HKS_SUCCESS) { HKS_LOG_E("Mbedtls cbc pkcs7 set key failed! mbedtls ret = 0x%X", ret); break; } ret = mbedtls_cipher_crypt(&ctx, cipherParam->iv.data, cipherParam->iv.size, message->data, message->size, cipherText->data, (size_t *)&(cipherText->size)); //加解密的实现。上一步密钥密文信息的设置结果,在ctx中的结果实现加解密。 if (ret != HKS_MBEDTLS_SUCCESS) { HKS_LOG_E("Mbedtls cbc pkcs7 crypt failed! mbedtls ret = 0x%X", ret); (void)memset_s(cipherText->data, cipherText->size, 0, cipherText->size); } } while (0); mbedtls_cipher_free(&ctx); return ret; }
4.aes/cbc的普通加密
该函数主要也是调用之前的加密方法,将算法写进usageSpec进行判断选用不同的模式进行加解密。
//封装函数 #if defined(HKS_SUPPORT_AES_CBC_NOPADDING) || defined(HKS_SUPPORT_AES_CBC_PKCS7) static int32_t AesCbcCrypt(const struct HksBlob *key, const struct HksUsageSpec *usageSpec, const struct HksBlob *message, const bool encrypt, struct HksBlob *cipherText) { const struct HksCipherParam *cipherParam = (struct HksCipherParam *)(usageSpec->algParam); switch (usageSpec->padding) { //根据usageSpec中内容进行分支,里面是判断选用nopadding还是pkcs7算法 #ifdef HKS_SUPPORT_AES_CBC_NOPADDING case HKS_PADDING_NONE: return AesCbcNoPaddingCrypt(key, cipherParam, message, encrypt, cipherText); #endif #ifdef HKS_SUPPORT_AES_CBC_PKCS7 case HKS_PADDING_PKCS7: return AesCbcPkcs7Crypt(key, cipherParam, message, encrypt, cipherText); #endif default: HKS_LOG_E("Unsupport padding! mode = 0x%X", usageSpec->padding); return HKS_ERROR_INVALID_PADDING; } }
5.aes和gcm的加密
aes和gcm的加密模式。
static int32_t AesEncryptGcm(const struct HksBlob *key, const struct HksUsageSpec *usageSpec, const struct HksBlob *message, struct HksBlob *cipherText, struct HksBlob *tagAead) { mbedtls_gcm_context ctx; mbedtls_gcm_init(&ctx); //先定义及初始化一个gcm的密文信息ctx int32_t ret; do { ret = mbedtls_gcm_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, key->data, key->size * HKS_BITS_PER_BYTE); //设置一个密钥,写进key中 if (ret != HKS_MBEDTLS_SUCCESS) { HKS_LOG_E("Mbedtls aes gcm set key failed! mbedtls ret = 0x%X", ret); break; } const struct HksAeadParam *aeadParam = (struct HksAeadParam *)(usageSpec->algParam); ret = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_ENCRYPT, message->size, aeadParam->nonce.data, aeadParam->nonce.size, aeadParam->aad.data, aeadParam->aad.size, message->data, cipherText->data, tagAead->size, tagAead->data); //调用mbedtls_gcm_crypt_and_tag实现加密和标记 if (ret != HKS_MBEDTLS_SUCCESS) { HKS_LOG_E("Mbedtls aes gcm encryot failed! mbedtls ret = 0x%X", ret); (void)memset_s(cipherText->data, cipherText->size, 0, cipherText->size); (void)memset_s(tagAead->data, tagAead->size, 0, tagAead->size); break; //加密失败的处理 } cipherText->size = message->size; //将最后结果写进密文 } while (0); mbedtls_gcm_free(&ctx); return ret; }
6.aes和gcm的解密
对应的解密函数,一般加密函数会对应一个唯一的解密函数。或者是将两个函数写在一起,用逻辑变量区分。
//aes/gcm的解密 static int32_t AesDecryptGcm(const struct HksBlob *key, const struct HksUsageSpec *usageSpec, const struct HksBlob *message, struct HksBlob *cipherText) { mbedtls_gcm_context ctx; mbedtls_gcm_init(&ctx); int32_t ret; do { ret = mbedtls_gcm_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, key->data, key->size * HKS_BITS_PER_BYTE); if (ret != HKS_MBEDTLS_SUCCESS) { HKS_LOG_E("Mbedtls aes gcm set key failed! mbedtls ret = 0x%X", ret); break; } const struct HksAeadParam *aeadParam = (struct HksAeadParam *)(usageSpec->algParam); ret = mbedtls_gcm_auth_decrypt(&ctx, message->size, aeadParam->nonce.data, aeadParam->nonce.size, aeadParam->aad.data, aeadParam->aad.size, aeadParam->tagDec.data, aeadParam->tagDec.size, message->data, cipherText->data); if (ret != HKS_MBEDTLS_SUCCESS) { HKS_LOG_E("Mbedtls aes gcm decrypt failed! mbedtls ret = 0x%X", ret); (void)memset_s(cipherText->data, cipherText->size, 0, cipherText->size); break; } cipherText->size = message->size; } while (0); mbedtls_gcm_free(&ctx); return ret; }
7.密钥的检查
检查密钥的位长度size是否位128、192、256等。
//密钥的检查
static int32_t CheckKeySize(const struct HksBlob *key)
{
if ((key->size != HKS_KEY_BYTES(HKS_AES_KEY_SIZE_128)) && (key->size != HKS_KEY_BYTES(HKS_AES_KEY_SIZE_192)) &&
(key->size != HKS_KEY_BYTES(HKS_AES_KEY_SIZE_256))) {
//检查密钥字节长度是否为128或者是192或者是256
return HKS_ERROR_INVALID_KEY_SIZE;
}
return HKS_SUCCESS;
}
8.加密和解密功能的封装
总的函数功能封装,将会情况写进usagespec中,然后采用switch语句将不同函数封装进去,cbc将nopadding和pkcs7封装在了一起,整体叫做cbc加密,而相对应的另一种加解密方式就是gcm和aes的加解密模式,这里封装cbc和gcm的情况。同时实现了解密的封装。
//函数功能的封装,根据不同情况判断使用何种加解密方式 int32_t HksMbedtlsAesEncrypt(const struct HksBlob *key, const struct HksUsageSpec *usageSpec, const struct HksBlob *message, struct HksBlob *cipherText, struct HksBlob *tagAead) { if (CheckKeySize(key) != HKS_SUCCESS) { HKS_LOG_E("Invalid aes keySiz = 0x%X", key->size); return HKS_ERROR_INVALID_KEY_SIZE; } switch (usageSpec->mode) { //基于usageSpec->mode进行分支选择加解密算法 #if defined(HKS_SUPPORT_AES_CBC_NOPADDING) || defined(HKS_SUPPORT_AES_CBC_PKCS7) case HKS_MODE_CBC: return AesCbcCrypt(key, usageSpec, message, true, cipherText); #endif #ifdef HKS_SUPPORT_AES_GCM case HKS_MODE_GCM: return AesEncryptGcm(key, usageSpec, message, cipherText, tagAead); #endif #ifdef HKS_SUPPORT_AES_CCM case HKS_MODE_CCM: return AesEncryptCcm(key, usageSpec, message, cipherText, tagAead); #endif default: HKS_LOG_E("Unsupport key alg! mode = 0x%X", usageSpec->mode); return HKS_ERROR_INVALID_ARGUMENT; } }
解密的封装
//解密的封装 int32_t HksMbedtlsAesDecrypt(const struct HksBlob *key, const struct HksUsageSpec *usageSpec, const struct HksBlob *message, struct HksBlob *cipherText) { if (CheckKeySize(key) != HKS_SUCCESS) { HKS_LOG_E("Invalid aes keySize = 0x%X", key->size); return HKS_ERROR_INVALID_KEY_SIZE; } switch (usageSpec->mode) { #if defined(HKS_SUPPORT_AES_CBC_NOPADDING) || defined(HKS_SUPPORT_AES_CBC_PKCS7) case HKS_MODE_CBC: return AesCbcCrypt(key, usageSpec, message, false, cipherText); #endif #ifdef HKS_SUPPORT_AES_GCM case HKS_MODE_GCM: return AesDecryptGcm(key, usageSpec, message, cipherText); #endif #ifdef HKS_SUPPORT_AES_CCM case HKS_MODE_CCM: return AesDecryptCcm(key, usageSpec, message, cipherText); #endif default: HKS_LOG_E("Unsupport key alg! mode = 0x%X", usageSpec->mode); return HKS_ERROR_INVALID_ARGUMENT; } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。