这次测评就进行AES加解密测试,本人对AES不是很了解,本次主要是分享使用STM32 HAL库进行AES-GCM/AES-CBC加解密过程。
一、AES是什么?
AES(英语全称:Advanced Encryption Standard,中文名称:高级加密标准),是美国联邦政府采用的一种区块加密标准。这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用,高级加密标准由美国国家标准与技术研究院(NIST)于2001年11月26日发布于FIPS PUB 197,并在2002年5月26日成为有效的标准,现在成为对称密钥加密中最流行的算法之一。(以上信息来源于网络)
二、AES原理
AES加密流程:图来源于网络
三、加密模式
AES的加密模式有以下几种
- 电子密码本:Electronic Code Book Mode (ECB)
- 密码分组链接:Cipher Block Chaining Mode (CBC)
- 密文反馈:Cipher Feedback Mode (CFB)
- 输出反馈:Output Feedback Mode (OFB)
- 计数器模式:Counter Mode (CTR)
- 填充密码分组链接:Propagating Cipher Block Chaining Mode(PCBC)
ECB模式和CBC模式是最常用的两种模式,其他的模式稍作了解即可。 需要块对对齐(填充)的AES加密模式:ECB、CBC、PCBC,其余模式无需块对齐。 需要初始向量的AES加密模式:除ECB模式外,都需要初始向量。
简单介绍一下CBC模式和GCM模式;
1)CBC模式
CBC模式对于每个待加密的密码块,在加密前会先与前一个密码块的密文异或然后再用加密器加密(图中的圆圈十字符号表示异或操作,下同)。第一个明文块与一个叫初始化向量的数据块异或。加、解密双方共同知晓密钥和初始化向量才能实现加解密。
2)GCM模式
GCM ( Galois/Counter Mode) 指的是该对称加密采用Counter模式,并带有GMAC消息认证码
优点:安全性比ECB模式高;是SSL的标准。
缺点:数据块之间的加密有依赖关系,因此不能并行计算
四、程序编写
1、AES-GCM模式
1)CubeMx配置
2)主函数
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_AES_Init();
MX_ICACHE_Init();
MX_USART2_UART_Init();
/* USER CODE BEGIN 2 */
/* USER CODE BEGIN 2 */
/*##-2- Encryption Phase #################################################*/
printf("\r\nEncryption Phase #################################################\r\n");
printf("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("Encrypt finished...[uwTick=%d]\r\n",uwTick);
/*Compare results with expected buffer*/
printf("Encrypted data\r\n");
for(int i=0;i < PLAINTEXT_SIZE;i++){
printf("0x%08X,",EncryptedText[i]);
}
printf("\r\nexpected cipher text\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("authentication TAG\r\n");
for(int i=0;i<4;i++){
printf("0x%08X,",TAG[i]);
}
/*Compare results with expected buffer*/
if(memcmp(TAG, ExpectedTAG, 16) != 0)
{
/* Processing Error */
Error_Handler();
}
printf("\r\nExpected TAG:\r\n");
for(int i=0;i<4;i++){
printf("0x%08X,",ExpectedTAG[i]);
}
/*##-3- Decryption Phase #################################################*/
printf("\r\nDecryption Phase #################################################\r\n");
printf("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("Decrypt finished...[uwTick=%d]\r\n",uwTick);
for(int i=0;i<PLAINTEXT_SIZE;i++){
printf("0x%08X,",DecryptedText[i]);
}
/*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("authentication 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("Expected TAG\r\n");
for(int i=0;i<4;i++){
printf("0x%08X,",ExpectedTAG[i]);
}
printf("\r\n");
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
3)验证
a、工具验证
b、串口打印
2、AES-CBC模式
1)CubeMx配置
2)主函数
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_AES_Init();
MX_ICACHE_Init();
MX_USART2_UART_Init();
/* USER CODE BEGIN 2 */
printf("\r\nCBC Encryption Phase #################################################\r\n");
printf("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("Encrypt finished...[uwTick=%d]\r\n",uwTick);
/*Compare results with expected buffer*/
printf("Encrypted data\r\n");
for(int i=0;i < PLAINTEXT_SIZE;i++){
printf("0x%08X,",EncryptedText[i]);
}
printf("\r\nexpected cipher text\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();
}
printf("\r\nCBC Decryption Phase #################################################\r\n");
printf("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("Decrypt finished...[uwTick=%d]\r\n",uwTick);
for(int i=0;i<PLAINTEXT_SIZE;i++){
printf("0x%08X,",DecryptedText[i]);
}
/*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");
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
3)验证
a、工具验证
b、串口打印
整体来看,加密和解密耗时2ms;加密速度还是挺快的。
五、参考资料:
什么是 AES-GCM加密算法_aes gcm-CSDN博客
在线验证工具:
工程代码:
1、AES-GCM
2、AES-CBC