打印
[STM32H5]

【STM32 Nucleo-64测评】4、AES加密GCM模式测试

[复制链接]
655|7
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 sujingliang 于 2024-7-22 15:40 编辑

一.什么是AES加密?

常见的加密主要分为两类:对称加密和非对称加密,AES加密就是对称加密的一种,即加密和解密使用相同的一把密钥。它的全称是Advanced Encryption Standard(高级加密标准),主要是用来取代DES加密算法,目前已经被全世界广泛采用,各大处理器厂商也在各自的CPU中,集成了专门的AES指令集,从而在硬件层面提升了AES加解密的速度。

对称加密的流程:


  • 明文P(plainText):未经加密的数据
  • 密钥K(key):用来加密明文的密码。在对称加密算法中,加密与解密的密钥是相同的,由双方协商产生,绝不可以泄漏
  • 密文C(cipherText): 经过加密的数据
  • 加密函数E(encrypt):C = E(K, P),即将明文和密钥作为参数,传入加密函数中,就可以获得密文
  • 解密函数D(decrypt):P = D(K, C),即将密文和密钥作为参数,传入解密函数中,就可以获得明文
  AES主要工作模式(其实还有很多模式) :ECB (Electroniccodebook,电子密码本)、CBC (Cipher-block chaining,密码分组链接)、CFB (Cipher feedback,密文反馈)、OFB (Output feedback,输出反馈)、PCBC (Propagating cipher-block chaining,增强型密码分组链接) 、GCM(伽罗瓦计数器模式)。

二、GCM(伽罗瓦计数器模式)工作模式

伽罗瓦计数器模式从名字上可以看出来,它还是以CTR模式为蓝本,除此之外还提供了防篡改校验。其原理是允许输入一定的自定义数据参与MAC校验码的生成。

如果你对比ECB和GCM对同样明文的加密,会发现GCM的密文比ECB的密文要长,这是因为GCM的密文中还追加了MAC指纹。这也是为什么,如果你修改了ECB的密文,解密并不会失败,只是得不到期望的值,而修改了GCM的密文,解密会失败,因为GCM解密过程中还要对MAC指纹进行校验。之所以较伽罗瓦计数器模式,就是因为在计算MAC的过程中,用到了伽罗瓦域的原理。




以上为原理部分,说实话非专业人士不是很容易看得懂。姑且认为是个黑盒子,输入为(明文、KEY、IV、ADD、)经过GCM后输出(密文、TAG)。
三、主要名词
因为要使用HAL库中的HAL_CRYP_Encrypt等函数,必须先了解一些名称。

Key: 加解密使用到的密钥,在AES规范中,支持128、192、256bit三种密钥长度,这也对应了加解密的强度
IV        Initialization vector:在部分分组加密模式中使用的,额外输入的随机初始化向量,其作用一般是用于使同样的明文多次加密的结果增加随机性,工程实践中一般称为Nonce
Cipher(密文):密文是明文经过加密算法处理后的结果,是加密过程中的输出。在AES GCM中,明文通过AES加密算法和IV、密钥等参数被加密成密文。
TAG(消息认证码):TAG是AES GCM加密过程中生成的一个认证标记,用于验证密文的完整性和真实性。它基于加密的明文和任何附加认证数据(AAD)计算得出。
附加认证数据(AAD):在AES GCM加密中,AAD是一组与明文一起处理的非加密数据。这些数据对于加密过程来说是可见的,但不需要保密。AAD的存在允许加密通信的双方验证加密数据的上下文或关联性,从而增加加密系统的安全性。


四、AES加密GCM模式测试
1、数据定义:
uint32_t pKeyAES[4] = {0xFEFFE992,0x8665731C,0x6D6A8F94,0x67308308};
uint32_t pInitVectAES[4] = {0xCAFEBABE,0xFACEDBAD,0xDECAF888,0x00000002};
__ALIGN_BEGIN static const uint32_t HeaderAES[5] __ALIGN_END = {
                            0xfeedface,0xdeadbeef,0xfeedface,0xdeadbeef,0xabaddad2};


uint32_t Plaintext[PLAINTEXT_SIZE] = {0xd9313225,0xf88406e5,0xa55909c5,0xaff5269a,
                                      0x86a7a953,0x1534f7da,0x2e4c303d,0x8a318a72,
                                      0x1c3c0c95,0x95680953,0x2fcf0e24,0x49a6b525,
                                      0xb16aedf5,0xaa0de657,0xba637b39};

uint32_t Ciphertext[15] = {0x42831ec2,0x21777424,0x4b7221b7,0x84d0d49c,
                           0xe3aa212f,0x2c02a4e0,0x35c17e23,0x29aca12e,
                           0x21d514b2,0x5466931c,0x7d8f6a5a,0xac84aa05,
                           0x1ba30b39,0x6a0aac97,0x3d58e091};

uint32_t ExpectedTAG[4]={0x5bc94fbc,0x3221a5db,0x94fae95a,0xe7121a47};
pKeyAES:密钥
pInitVectAES:IV        Initialization vector
HeaderAES:附加认证数据(AAD)
Plaintext:明文

Ciphertext:期望密文
ExpectedTAG:期望TAG(消息认证码)


2、Show_Message(void)
static void Show_Message(void)
{
        printf("板子名称:%s\r\n",BSP_GetBoardName());
        printf("版本:%d\r\n",BSP_GetVersion());
        printf("板子ID:%s\r\n",BSP_GetBoardID());
        printf("[STM32 Nucleo-64测评] 4、AES加密GCM模式测试\r\n");
        
}

3、main()片段
 Show_Message();
        
         /* USER CODE BEGIN 2 */
  /*##-2- Encryption Phase #################################################*/
        
        printf("\r\nEncryption Phase #################################################\r\n");
        printf("HAL_CRYP_Encrypt start...[uwTick=%d]\r\n",uwTick);
  if (HAL_CRYP_Encrypt(&hcryp, Plaintext, PLAINTEXT_SIZE, EncryptedText, TIMEOUT_VALUE) != HAL_OK)
  {
    /* Processing Error */
    Error_Handler();
  }
        printf("HAL_CRYP_Encrypt finished...[uwTick=%d]\r\n",uwTick);
  /*Compare results with expected buffer*/
        
        printf("加密结果:\r\n");
        for(int i=0;i<PLAINTEXT_SIZE;i++){
                printf("0x%08X,",EncryptedText[i]);
        }
        printf("\r\n");
        
        
        printf("预期加密结果:\r\n");
        for(int i=0;i<PLAINTEXT_SIZE;i++){
                printf("0x%08X,",Ciphertext[i]);
        }
        printf("\r\n");
  if(memcmp(EncryptedText, Ciphertext, 4*PLAINTEXT_SIZE) != 0)
  {
    /* Processing Error */
    Error_Handler();
  }
  /* Compute the authentication TAG */
  if (HAL_CRYPEx_AESGCM_GenerateAuthTAG(&hcryp,TAG, TIMEOUT_VALUE) != HAL_OK)
  {
    /* Processing Error */
    Error_Handler();
  }
        
        printf("加密令牌TAG结果:\r\n");
        for(int i=0;i<4;i++){
                printf("0x%08X,",TAG[i]);
        }
        printf("\r\n");
  /*Compare results with expected buffer*/
  if(memcmp(TAG, ExpectedTAG, 16) != 0)
  {
    /* Processing Error */
    Error_Handler();
  }
        printf("预期加密令牌TAG结果:\r\n");
        for(int i=0;i<4;i++){
                printf("0x%08X,",ExpectedTAG[i]);
        }
        printf("\r\n");
        


/*##-3- Decryption Phase #################################################*/
        printf("\r\n\Decryption Phase #################################################\r\n");

        printf("HAL_CRYP_Decrypt start...[uwTick=%d]\r\n",uwTick);
  if (HAL_CRYP_Decrypt(&hcryp,Ciphertext , PLAINTEXT_SIZE, DecryptedText, TIMEOUT_VALUE) != HAL_OK)
  {
    /* Processing Error */
    Error_Handler();
  }
        printf("HAL_CRYP_Decrypt finished...[uwTick=%d]\r\n",uwTick);
        
        printf("解密结果:\r\n");
        for(int i=0;i<PLAINTEXT_SIZE;i++){
                printf("0x%08X,",DecryptedText[i]);
        }
        printf("\r\n");
        
  /*Compare results with expected buffer*/
  if(memcmp(DecryptedText, Plaintext, 16) != 0)
  {
    /* Processing Error */
    Error_Handler();
  }

        printf("明文:\r\n");
        for(int i=0;i<PLAINTEXT_SIZE;i++){
                printf("0x%08X,",Plaintext[i]);
        }
        printf("\r\n");
  /* Compute the authentication TAG */
  if (HAL_CRYPEx_AESGCM_GenerateAuthTAG(&hcryp,TAG, TIMEOUT_VALUE) != HAL_OK)
  {
    /* Processing Error */
    Error_Handler();
  }
        
        printf("解密令牌TAG结果:\r\n");
        for(int i=0;i<4;i++){
                printf("0x%08X,",TAG[i]);
        }
        printf("\r\n");        
  /*Compare results with expected buffer*/
  if(memcmp(TAG, ExpectedTAG, 16) != 0)
  {
    /* Processing Error */
    Error_Handler();
  }
        printf("预期解密令牌TAG结果:\r\n");
        for(int i=0;i<4;i++){
                printf("0x%08X,",ExpectedTAG[i]);
        }
        printf("\r\n");        
HAL_CRYP_Encrypt是加密函数
HAL_CRYP_Decrypt是解密函数
HAL_CRYPEx_AESGCM_GenerateAuthTAG生成TAG


4、AES初始化
static void MX_AES_Init(void)
{

  /* USER CODE BEGIN AES_Init 0 */

  /* USER CODE END AES_Init 0 */

  /* USER CODE BEGIN AES_Init 1 */

  /* USER CODE END AES_Init 1 */
  hcryp.Instance = AES;
  hcryp.Init.DataType = CRYP_NO_SWAP;
  hcryp.Init.KeySize = CRYP_KEYSIZE_128B;
  hcryp.Init.pKey = (uint32_t *)pKeyAES;
  hcryp.Init.pInitVect = (uint32_t *)pInitVectAES;
  hcryp.Init.Algorithm = CRYP_AES_GCM_GMAC;
  hcryp.Init.Header = (uint32_t *)HeaderAES;
  hcryp.Init.HeaderSize = 5;
  hcryp.Init.DataWidthUnit = CRYP_DATAWIDTHUNIT_WORD;
  hcryp.Init.HeaderWidthUnit = CRYP_HEADERWIDTHUNIT_WORD;
  hcryp.Init.KeyIVConfigSkip = CRYP_KEYIVCONFIG_ALWAYS;
  hcryp.Init.KeyMode = CRYP_KEYMODE_NORMAL;
  if (HAL_CRYP_Init(&hcryp) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN AES_Init 2 */

  /* USER CODE END AES_Init 2 */

}

五、运行效果




网上AES在线工具计算比较:


六、总结

1、加密解密结果正确。

2、加密和解密耗时大约3、4个TICKS。

3、官方例子位置:STM32Cube_FW_H5_V1.3.0\Projects\NUCLEO-H533RE\Examples\CRYP\CRYP_AES_GCM_Padding



使用特权

评论回复
沙发
呐咯密密| | 2024-7-24 11:38 | 只看该作者
ST有工具配置吗

使用特权

评论回复
板凳
kqh11a| | 2024-7-29 14:25 | 只看该作者
GCM是基于计数器模式(CTR)的加密模式,它结合了加密和认证的功能:

加密:使用AES算法对数据块进行加密。
认证:使用Galois域的乘法来生成认证码(TAG),验证数据的完整性。

使用特权

评论回复
地板
发给她更好fh| | 2024-7-31 23:20 | 只看该作者
AES(Advanced Encryption Standard) 是一种对称加密算法,用于加密和解密数据。它的主要特点是:

对称加密:加密和解密使用相同的密钥。
块加密:AES处理数据块,每块128位(16字节),支持三种密钥长度:128位、192位和256位。

使用特权

评论回复
5
发给她更好fh| | 2024-7-31 23:20 | 只看该作者
Key(密钥):用于加密和解密的密码。
IV(Initialization Vector,初始化向量):用于增加加密的随机性,防止相同明文产生相同密文。
Cipher(密文):加密后的数据。
TAG(消息认证码):用于验证密文的完整性和真实性。
AAD(附加认证数据):与明文一起处理,但不进行加密的数据,增加了加密系统的安全性。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

14

主题

25

帖子

0

粉丝