加解密 | AES加、解密学习
你的代码实现了一个简单的AES(高级加密标准)加密和解密的测试程序。以下是对代码的分析和一些改进建议:
代码功能
- 初始化数据和密钥:
- 定义了一个16字节的输入数据
input_data
。 - 定义了一个16字节的AES密钥
key
。 - 初始化了加密数据和解密数据的缓冲区。
- 定义了一个16字节的输入数据
- 密钥扩展:
- 使用
aes_expand_key
函数将原始密钥扩展为扩展密钥。
- 使用
- 加密和解密:
- 使用
aes_encrypt
函数对输入数据进行加密。 - 使用
aes_decrypt
函数对加密后的数据进行解密。
- 使用
- 打印信息:
- 打印了加密前后的数据、密钥等信息。
代码中的问题和改进建议
- 使用字符串作为密钥:
- 在C语言中,字符串以空字符
\0
结尾。因此,"1234567890abcdef"
实际上是一个17字节的字符串(包括空字符)。这可能导致密钥长度不正确。 - 改进建议:使用字节数组定义密钥,确保密钥长度为16字节。
- 在C语言中,字符串以空字符
- 加密和解密函数的参数类型:
aes_encrypt
和aes_decrypt
函数的参数类型需要明确。确保它们接受的是字节数组,并且长度正确。- 如果这些函数的实现需要16字节对齐的输入,需要确保输入数据的长度为16的倍数。
- 解密硬编码的十六进制字符串:
- 在代码中,你尝试直接将十六进制字符串
"8df9deff39e5877acf18f8056538864c"
传递给aes_decrypt
函数。这在C语言中是不正确的,因为字符串是字符数组,而不是字节数组。 - 改进建议:将十六进制字符串转换为字节数组后再进行解密。
- 在代码中,你尝试直接将十六进制字符串
- 打印加密后的数据:
- 加密后的数据是二进制数据,可能包含不可打印字符。因此,使用十六进制格式打印是正确的,但需要确保解密后的数据也是正确处理的。
改进后的代码
以下是改进后的代码示例:
c复制
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#define AES_KEY_LENGTH 16
#define AES_EXPAND_KEY_LENGTH 176 // AES-128 扩展密钥长度
typedef uint8_t u8;
// 假设的 AES 加密和解密函数
void aes_expand_key(const u8* key, u8* expanded_key);
void aes_encrypt(const u8* input, const u8* expanded_key, u8* output);
void aes_decrypt(const u8* input, const u8* expanded_key, u8* output);
int tester_aes() {
// 输入数据,必须是 16 字节的倍数
u8 input_data[16] = "Hello, AES!";
u8 encrypted_data[16];
u8 decrypted_data[16];
// AES 密钥 (128 位)
u8 key[AES_KEY_LENGTH] = {0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10};
u8 expanded_key[AES_EXPAND_KEY_LENGTH];
int i = 0;
aes_expand_key(key, expanded_key);
memset(encrypted_data, 0, sizeof(encrypted_data));
memset(decrypted_data, 0, sizeof(decrypted_data));
printf("sizeof(unsigned char): %ld\n", sizeof(unsigned char));
printf("sizeof(unsigned int) : %ld\n", sizeof(unsigned int));
printf("密钥:");
for (i = 0; i < AES_KEY_LENGTH; i++) {
printf("%02x", key[i]);
}
printf("\n");
printf("原始数据: ");
for (i = 0; i < 16; i++) {
printf("%02x", input_data[i]);
}
printf("\n");
// 加密
aes_encrypt(input_data, expanded_key, encrypted_data);
printf("加密后的数据: ");
for (i = 0; i < 16; i++) {
printf("%02x", encrypted_data[i]);
}
printf("\n");
// 解密
aes_decrypt(encrypted_data, expanded_key, decrypted_data);
printf("解密后的数据: ");
for (i = 0; i < 16; i++) {
printf("%02x", decrypted_data[i]);
}
printf("\n");
// 解密硬编码的十六进制字符串
u8 hex_data[16] = {0x8d, 0xf9, 0xde, 0xff, 0x39, 0xe5, 0x87, 0x7a, 0xcf, 0x18, 0xf8, 0x05, 0x65, 0x38, 0x86, 0x4c};
aes_decrypt(hex_data, expanded_key, decrypted_data);
printf("解密后的数据1: ");
for (i = 0; i < 16; i++) {
printf("%02x", decrypted_data[i]);
}
printf("\n");
return 0;
}
改进点说明
- 密钥定义:
- 使用字节数组定义密钥,确保密钥长度为16字节。
- 十六进制字符串转换:
- 将硬编码的十六进制字符串转换为字节数组,避免直接传递字符串。
- 打印数据:
- 使用十六进制格式打印所有数据,确保输出一致且易于理解。
注意事项
- 确保
aes_expand_key
、aes_encrypt
和aes_decrypt
函数的实现是正确的,并且它们的参数类型和长度符合要求。 - 如果需要处理更长的输入数据,需要分块处理,因为AES加密要求输入数据长度为16字节的倍数。
- 在实际应用中,密钥和数据应通过安全的方式传递和存储,避免硬编码在代码中。