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

[复制链接]
 楼主| sujingliang 发表于 2024-7-22 13:17 | 显示全部楼层 |阅读模式
<
本帖最后由 sujingliang 于 2024-7-22 15:40 编辑

一.什么是AES加密?

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

对称加密的流程:
1610045-20220803155700662-53646350.png

  • 明文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的过程中,用到了伽罗瓦域的原理。


1610045-20220803161847175-718977485.png

以上为原理部分,说实话非专业人士不是很容易看得懂。姑且认为是个黑盒子,输入为(明文、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、数据定义:
  1. uint32_t pKeyAES[4] = {0xFEFFE992,0x8665731C,0x6D6A8F94,0x67308308};
  2. uint32_t pInitVectAES[4] = {0xCAFEBABE,0xFACEDBAD,0xDECAF888,0x00000002};
  3. __ALIGN_BEGIN static const uint32_t HeaderAES[5] __ALIGN_END = {
  4.                             0xfeedface,0xdeadbeef,0xfeedface,0xdeadbeef,0xabaddad2};


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

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

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

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


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

3、main()片段
  1. Show_Message();
  2.         
  3.          /* USER CODE BEGIN 2 */
  4.   /*##-2- Encryption Phase #################################################*/
  5.         
  6.         printf("\r\nEncryption Phase #################################################\r\n");
  7.         printf("HAL_CRYP_Encrypt start...[uwTick=%d]\r\n",uwTick);
  8.   if (HAL_CRYP_Encrypt(&hcryp, Plaintext, PLAINTEXT_SIZE, EncryptedText, TIMEOUT_VALUE) != HAL_OK)
  9.   {
  10.     /* Processing Error */
  11.     Error_Handler();
  12.   }
  13.         printf("HAL_CRYP_Encrypt finished...[uwTick=%d]\r\n",uwTick);
  14.   /*Compare results with expected buffer*/
  15.         
  16.         printf("加密结果:\r\n");
  17.         for(int i=0;i<PLAINTEXT_SIZE;i++){
  18.                 printf("0x%08X,",EncryptedText[i]);
  19.         }
  20.         printf("\r\n");
  21.         
  22.         
  23.         printf("预期加密结果:\r\n");
  24.         for(int i=0;i<PLAINTEXT_SIZE;i++){
  25.                 printf("0x%08X,",Ciphertext[i]);
  26.         }
  27.         printf("\r\n");
  28.   if(memcmp(EncryptedText, Ciphertext, 4*PLAINTEXT_SIZE) != 0)
  29.   {
  30.     /* Processing Error */
  31.     Error_Handler();
  32.   }
  33.   /* Compute the authentication TAG */
  34.   if (HAL_CRYPEx_AESGCM_GenerateAuthTAG(&hcryp,TAG, TIMEOUT_VALUE) != HAL_OK)
  35.   {
  36.     /* Processing Error */
  37.     Error_Handler();
  38.   }
  39.         
  40.         printf("加密令牌TAG结果:\r\n");
  41.         for(int i=0;i<4;i++){
  42.                 printf("0x%08X,",TAG[i]);
  43.         }
  44.         printf("\r\n");
  45.   /*Compare results with expected buffer*/
  46.   if(memcmp(TAG, ExpectedTAG, 16) != 0)
  47.   {
  48.     /* Processing Error */
  49.     Error_Handler();
  50.   }
  51.         printf("预期加密令牌TAG结果:\r\n");
  52.         for(int i=0;i<4;i++){
  53.                 printf("0x%08X,",ExpectedTAG[i]);
  54.         }
  55.         printf("\r\n");
  56.         


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

  59.         printf("HAL_CRYP_Decrypt start...[uwTick=%d]\r\n",uwTick);
  60.   if (HAL_CRYP_Decrypt(&hcryp,Ciphertext , PLAINTEXT_SIZE, DecryptedText, TIMEOUT_VALUE) != HAL_OK)
  61.   {
  62.     /* Processing Error */
  63.     Error_Handler();
  64.   }
  65.         printf("HAL_CRYP_Decrypt finished...[uwTick=%d]\r\n",uwTick);
  66.         
  67.         printf("解密结果:\r\n");
  68.         for(int i=0;i<PLAINTEXT_SIZE;i++){
  69.                 printf("0x%08X,",DecryptedText[i]);
  70.         }
  71.         printf("\r\n");
  72.         
  73.   /*Compare results with expected buffer*/
  74.   if(memcmp(DecryptedText, Plaintext, 16) != 0)
  75.   {
  76.     /* Processing Error */
  77.     Error_Handler();
  78.   }

  79.         printf("明文:\r\n");
  80.         for(int i=0;i<PLAINTEXT_SIZE;i++){
  81.                 printf("0x%08X,",Plaintext[i]);
  82.         }
  83.         printf("\r\n");
  84.   /* Compute the authentication TAG */
  85.   if (HAL_CRYPEx_AESGCM_GenerateAuthTAG(&hcryp,TAG, TIMEOUT_VALUE) != HAL_OK)
  86.   {
  87.     /* Processing Error */
  88.     Error_Handler();
  89.   }
  90.         
  91.         printf("解密令牌TAG结果:\r\n");
  92.         for(int i=0;i<4;i++){
  93.                 printf("0x%08X,",TAG[i]);
  94.         }
  95.         printf("\r\n");        
  96.   /*Compare results with expected buffer*/
  97.   if(memcmp(TAG, ExpectedTAG, 16) != 0)
  98.   {
  99.     /* Processing Error */
  100.     Error_Handler();
  101.   }
  102.         printf("预期解密令牌TAG结果:\r\n");
  103.         for(int i=0;i<4;i++){
  104.                 printf("0x%08X,",ExpectedTAG[i]);
  105.         }
  106.         printf("\r\n");        
HAL_CRYP_Encrypt是加密函数
HAL_CRYP_Decrypt是解密函数
HAL_CRYPEx_AESGCM_GenerateAuthTAG生成TAG


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

  3.   /* USER CODE BEGIN AES_Init 0 */

  4.   /* USER CODE END AES_Init 0 */

  5.   /* USER CODE BEGIN AES_Init 1 */

  6.   /* USER CODE END AES_Init 1 */
  7.   hcryp.Instance = AES;
  8.   hcryp.Init.DataType = CRYP_NO_SWAP;
  9.   hcryp.Init.KeySize = CRYP_KEYSIZE_128B;
  10.   hcryp.Init.pKey = (uint32_t *)pKeyAES;
  11.   hcryp.Init.pInitVect = (uint32_t *)pInitVectAES;
  12.   hcryp.Init.Algorithm = CRYP_AES_GCM_GMAC;
  13.   hcryp.Init.Header = (uint32_t *)HeaderAES;
  14.   hcryp.Init.HeaderSize = 5;
  15.   hcryp.Init.DataWidthUnit = CRYP_DATAWIDTHUNIT_WORD;
  16.   hcryp.Init.HeaderWidthUnit = CRYP_HEADERWIDTHUNIT_WORD;
  17.   hcryp.Init.KeyIVConfigSkip = CRYP_KEYIVCONFIG_ALWAYS;
  18.   hcryp.Init.KeyMode = CRYP_KEYMODE_NORMAL;
  19.   if (HAL_CRYP_Init(&hcryp) != HAL_OK)
  20.   {
  21.     Error_Handler();
  22.   }
  23.   /* USER CODE BEGIN AES_Init 2 */

  24.   /* USER CODE END AES_Init 2 */

  25. }

五、运行效果


aes2.gif

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

六、总结

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位。
发给她更好fh 发表于 2024-7-31 23:20 | 显示全部楼层
Key(密钥):用于加密和解密的密码。
IV(Initialization Vector,初始化向量):用于增加加密的随机性,防止相同明文产生相同密文。
Cipher(密文):加密后的数据。
TAG(消息认证码):用于验证密文的完整性和真实性。
AAD(附加认证数据):与明文一起处理,但不进行加密的数据,增加了加密系统的安全性。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

84

主题

146

帖子

3

粉丝
快速回复 在线客服 返回列表 返回顶部