目录

NDK工程使用AES加密算法对任意长度明文加密失败

问题现象

使用密钥管理服务开发,参考加解密(C/C++)中的样例,发现如下情况加密会失败:

// 待加密内容,如下,能够加密成功
char tmpInData[] = "AES_ECB_INDATA_1";

// 修改为其他值,比如下面,加密就会失败
char tmpInData[] = "Hello World!";
char tmpInData[] = "abc";

加密成功日志如下:

04-18 16:06:52.181   55304-55304   A03200/com.exa...cation/MY_TAG  com.examp...lication  I     Success,  ohResult.errorCode=0, tmpInData=AES_ECB_INDATA_1.

加密失败日志如下:

04-18 16:04:11.635   54249-54249   C02F06/com.exa...lication/HUKS  com.examp...lication  I      HksReadRequestReply[84]: reply get errMsgLen = 145
04-18 16:04:11.635   54249-54249   C02F06/com.exa...lication/HUKS  com.examp...lication  E     [HksLog]: g_errMsg [ TeecRequestCmdInner[315]: invoke km command failed, cmd = 5, ret = 0xfffffffd, retOrigin = 4 <HksServiceFinish[2008] <HksIpcServiceUpdOrFin[830]]
04-18 16:04:11.635   54249-54249   C02F06/com.exa...lication/HUKS  com.examp...lication  E      HksClientFinish[789]: HksParamSet send fail, ret = -3
04-18 16:04:11.635   54249-54249   A03200/com.exa...cation/MY_TAG  com.examp...lication  I     Failed,  ohResult.errorCode=401, tmpInData=Hello World!.

背景知识

问题定位

加密失败错误码401为参数错误:

OH_HUKS_ERR_CODE_ILLEGAL_ARGUMENT = 401

针对问题现象进行分析:

  1. 字符串本身没有区别,唯一不同的是长度的差异;
  2. 尝试修改字符串的长度,长度等于16字节,长度大于16字节,长度小于16字节;
  3. 发现字符串长度等于16字节时可以正常加密,长度大于16字节,长度小于16字节均会加密失败。

    因此怀疑是跟明文长度和补位有关系。

分析结论

查看用例中:

static const uint32_t IV_SIZE = 16;
static uint8_t IV[IV_SIZE] = { 0 };

static struct OH_Huks_Param g_genEncDecParams[] = {
  // ...
  {
        .tag = OH_HUKS_TAG_PADDING,
        .uint32Param = OH_HUKS_PADDING_NONE
  }
}

OH_HUKS_TAG_PADDING补位标签设置的参数为OH_HUKS_PADDING_NONE,表明不会进行补位,因此字符串长度必须是块大小(16字节)的整数倍,否则加密会失败。

修改建议

查看HuksTypeApi中,填充算法类型枚举值:OH_HUKS_PADDING_NONE表示不使用填充算法,OH_HUKS_PADDING_PKCS7表示使用PKCS7填充算法。

将uint32Param = OH_HUKS_PADDING_NONE修改为OH_HUKS_PADDING_PKCS7后加密成功,修改如下。完整示例代码见加解密(C/C++)中的样例。

static const uint32_t IV_SIZE = 16;
static uint8_t IV[IV_SIZE] = {0}; // this is a test value, for real use the iv should be different every time.
static struct OH_Huks_Param g_genEncDecParams[] = {
    {.tag = OH_HUKS_TAG_ALGORITHM, .uint32Param = OH_HUKS_ALG_AES},
    {.tag = OH_HUKS_TAG_PURPOSE, .uint32Param = OH_HUKS_KEY_PURPOSE_ENCRYPT | OH_HUKS_KEY_PURPOSE_DECRYPT},
    {.tag = OH_HUKS_TAG_KEY_SIZE, .uint32Param = OH_HUKS_AES_KEY_SIZE_256},
    {.tag = OH_HUKS_TAG_PADDING, .uint32Param = OH_HUKS_PADDING_PKCS7},
    {.tag = OH_HUKS_TAG_BLOCK_MODE, .uint32Param = OH_HUKS_MODE_CBC}};
static struct OH_Huks_Param g_encryptParams[] = {
    {.tag = OH_HUKS_TAG_ALGORITHM, .uint32Param = OH_HUKS_ALG_AES},
    {.tag = OH_HUKS_TAG_PURPOSE, .uint32Param = OH_HUKS_KEY_PURPOSE_ENCRYPT},
    {.tag = OH_HUKS_TAG_KEY_SIZE, .uint32Param = OH_HUKS_AES_KEY_SIZE_256},
    {.tag = OH_HUKS_TAG_PADDING, .uint32Param = OH_HUKS_PADDING_PKCS7},
    {.tag = OH_HUKS_TAG_BLOCK_MODE, .uint32Param = OH_HUKS_MODE_CBC},
    {.tag = OH_HUKS_TAG_IV,
     .blob = {
         .size = IV_SIZE,
         .data = (uint8_t *)IV // this is a test value, for real use the iv should be different every time.
     }}};
static struct OH_Huks_Param g_decryptParams[] = {
    {.tag = OH_HUKS_TAG_ALGORITHM, .uint32Param = OH_HUKS_ALG_AES},
    {.tag = OH_HUKS_TAG_PURPOSE, .uint32Param = OH_HUKS_KEY_PURPOSE_DECRYPT},
    {.tag = OH_HUKS_TAG_KEY_SIZE, .uint32Param = OH_HUKS_AES_KEY_SIZE_256},
    {.tag = OH_HUKS_TAG_PADDING, .uint32Param = OH_HUKS_PADDING_PKCS7},
    {.tag = OH_HUKS_TAG_BLOCK_MODE, .uint32Param = OH_HUKS_MODE_CBC},
    {.tag = OH_HUKS_TAG_IV,
     .blob = {
         .size = IV_SIZE,
         .data = (uint8_t *)IV // this is a test value, for real use the iv should be different every time.
     }}};