AES加密标准又称为高级加密标准Rijndael加密法,是美国国家标准技术研究所NIST旨在取代DES的21世纪的加密标准。AES的基本要求是,采用对称分组密码体制,密钥长度可以为128、192或256位,分组长度128位。AES算法是最为常见的额对称加密算法之一。
AES的加解密流程图如下:
加解密流程图部件说明:
AES | 密钥长度(32bit) | 分组长度(32bit) | 加密轮数 |
---|---|---|---|
AES-128 | 4 | 4 | 10 |
AES-192 | 6 | 4 | 12 |
AES-256 | 8 | 4 | 14 |
.
├── include
│ ├── tiny_aes.h // aes 头文件
│ ├── tiny_base64.h // base64 头文件
│ ├── tinycrypt_config.h // tinycrypt 配置头文件
│ ├── tinycrypt.h // tinycrypt 头文件
│ ├── tiny_md5.h // md5 头文件
│ ├── tiny_sha1.h // sha1 头文件
│ └── tiny_sha2.h // sha2 头文件
├── LICENSE
├── README.md
├── samples
│ ├── aes_sample.c // aes 测试用例头文件
│ └── md5_sample.c // md5 测试用例头文件
└── src
├── tiny_aes.c // aes 源文件
├── tiny_base64.c // base64 源文件
├── tiny_md5.c // md5 头文件
├── tiny_sha1.c // sha1 头文件
└── tiny_sha2.c // sha2 头文件
.
├── main.c
├── makefile
└── tinycrypt
├── include
│ ├── tiny_aes.h
│ ├── tiny_base64.h
│ ├── tinycrypt_config.h
│ ├── tinycrypt.h
│ ├── tiny_md5.h
│ ├── tiny_sha1.h
│ └── tiny_sha2.h
├── LICENSE
├── README.md
├── samples
│ ├── aes_sample.c
│ └── md5_sample.c
└── src
├── tiny_aes.c
├── tiny_base64.c
├── tiny_md5.c
├── tiny_sha1.c
└── tiny_sha2.c
在目录中增加makefile文件和main.c,其中makefile用于构建工程,main.c用于编写我们的测试代码,其中:
makefile文件内容:
VERSION = 1.0.0 # 版本号
SOURCE = main.c # 源文件
SOURCE += $(wildcard ./tinycrypt/src/*.c) # 通过wildcard函数获取tinycrypt源文件
OBJECT = $(patsubst %.c, %.o, $(SOURCE)) # 通过patsubst函数替换源文件为目标文件
INCLUDE = -I ./tinycrypt/include # 包含头文件路径
TARGET = tinycrypt # 目标文件名字
CC = gcc # 工具链
CFLAGS = -Wall -g # 编译选项
OUTPUT = output # 输出目录
$(TARGET): $(OBJECT) # 构建执行命令
@mkdir -p $(OUTPUT) # 创建输出目录
$(CC) $^ $(CFLAGS) -o $(OUTPUT)/$(TARGET)_$(VERSION) # 编译
%.o: %.c # 将源文件编译成目标文件
$(CC) $(INCLUDE) $(CFLAGS) -c $< -o $@
.PHONY:clean # 执行make clean之后,清除过程文件
clean:
@rm -rf $(OBJECT) $(OUTPUT)
#include
#include
#include
#include
#include
#include
#include
#include
#include "tiny_aes.h"
#define ENCRYPT_TEST_FILE "./index.js"
#define ENCRYPT_TEST_ENCRYPT_FILE "./encrypt_index.js"
#define ENCRYPT_TEST_DECRYPT_FILE "./decrypt_index.js"
#define ENCRYPT_SINGLE_SIZE 1024 // 加密单包长度
#define ENCRYPT_AES_IV_LEN 16 // AES向量长度
#define ENCRYPT_AES_KEY_LEN 256 // AES密钥长度
#define ENCRYPT_AES_IV "0123456789ABCDEF" // AES向量
#define ENCRYPT_AES_KEY "0123456789ABCDEF0123456789ABCDEF" // AES密钥
// AES参数结构体定义
typedef struct
{
uint8_t aesIv[ENCRYPT_AES_IV_LEN];
uint8_t aesKey[ENCRYPT_AES_KEY_LEN];
tiny_aes_context aes_ctx;
} EncryptInfo;
static EncryptInfo g_info = {0};
// aes 参数初始化
void aes_init(const char *iv, const char *key)
{
memset(g_info.aesIv, 0, ENCRYPT_AES_IV_LEN);
memset(g_info.aesKey, 0, ENCRYPT_AES_KEY_LEN);
if (iv == NULL) {
memcpy(g_info.aesIv, ENCRYPT_AES_IV, strlen(ENCRYPT_AES_IV));
}
else {
memcpy(g_info.aesIv, iv, strlen(iv));
}
if(key == NULL) {
memcpy(g_info.aesKey, ENCRYPT_AES_KEY, strlen(ENCRYPT_AES_KEY));
}
else {
memcpy(g_info.aesKey, key, strlen(key));
}
}
// aes加密函数的封装
void aes_encrypt(uint8_t *dest_buff, const uint8_t *src_buff, uint32_t len)
{
tiny_aes_crypt_cbc(&g_info.aes_ctx, AES_ENCRYPT, len, g_info.aesIv, (uint8_t *)src_buff, dest_buff);
}
// aes解密函数的封装
void aes_decrypt(uint8_t *dest_buff, const uint8_t *src_buff, uint32_t len)
{
tiny_aes_crypt_cbc(&g_info.aes_ctx, AES_DECRYPT, len, g_info.aesIv, (uint8_t *)src_buff, dest_buff);
}
int main(int argc, char *argv[])
{
int raw_size = 0;
int src_fd = -1;
int encrypt_fd = -1;
int decrypt_fd = -1;
int src_file_size = 0;
int srv_file_offset = 0;
uint8_t src_buff[ENCRYPT_SINGLE_SIZE];
uint8_t encrypt_buff[ENCRYPT_SINGLE_SIZE];
uint8_t decrypt_buff[ENCRYPT_SINGLE_SIZE];
// 加密文件,将明文文件(index.js)通过AES加密为加密文件(encrypt_index.js)
{
aes_init(NULL, NULL); // aes 初始化
tiny_aes_setkey_enc(&g_info.aes_ctx, (uint8_t *)g_info.aesKey, ENCRYPT_AES_KEY_LEN); // 设置密钥
src_fd = open(ENCRYPT_TEST_FILE, O_RDONLY, 0777); // 打开明文文件
if (src_fd == -1) {
printf("%d-ERR: open file(%s) failedrn", __LINE__, ENCRYPT_TEST_FILE);
return -1;
}
encrypt_fd = open(ENCRYPT_TEST_ENCRYPT_FILE, O_RDWR | O_CREAT | O_TRUNC, 0777); // 打开加密文件
if (encrypt_fd == -1) {
printf("%d-ERR: open file(%s) failedrn", __LINE__, ENCRYPT_TEST_ENCRYPT_FILE);
return -1;
}
raw_size = lseek(src_fd, 0, SEEK_END); // 获取明文文件的大小
srv_file_offset = 0;
lseek(src_fd, 0, SEEK_SET);
printf("%d-INFO: source file size: %drn", __LINE__, raw_size);
while (srv_file_offset < raw_size) {
memset(src_buff, 0, ENCRYPT_SINGLE_SIZE);
memset(encrypt_buff, 0, ENCRYPT_SINGLE_SIZE);
read(src_fd, src_buff, ENCRYPT_SINGLE_SIZE); // 读取明文文件内容
aes_encrypt(encrypt_buff, src_buff, ENCRYPT_SINGLE_SIZE); // 明文文件内容加密
write(encrypt_fd, encrypt_buff, ENCRYPT_SINGLE_SIZE); // 将加密内容写入加密文件中
srv_file_offset += ENCRYPT_SINGLE_SIZE;
}
close(src_fd);
src_fd = -1;
close(encrypt_fd);
encrypt_fd = -1;
}
// 解密文件,将加密文件(encrypt_index.js)通过AES解密为解密文件(decrypt_index.js)
{
aes_init(NULL, NULL); // aes 初始化
tiny_aes_setkey_dec(&g_info.aes_ctx, (uint8_t *)g_info.aesKey, ENCRYPT_AES_KEY_LEN); // 设置密钥
src_fd = open(ENCRYPT_TEST_ENCRYPT_FILE, O_RDONLY, 0777); // 打开密文文件
if (src_fd == -1) {
printf("%d-ERR: open file(%s) failedrn", __LINE__, ENCRYPT_TEST_ENCRYPT_FILE);
return -1;
}
decrypt_fd = open(ENCRYPT_TEST_DECRYPT_FILE, O_RDWR | O_CREAT | O_TRUNC, 0777); // 打开解密文件
if (decrypt_fd == -1) {
printf("%d-ERR: open file(%s) failedrn", __LINE__, ENCRYPT_TEST_DECRYPT_FILE);
return -1;
}
src_file_size = raw_size; // 设置明文文件的大小
srv_file_offset = 0;
lseek(src_fd, 0, SEEK_SET);
printf("%d-INFO: encrypt file size: %drn", __LINE__, src_file_size);
while (srv_file_offset < src_file_size) {
memset(src_buff, 0, ENCRYPT_SINGLE_SIZE);
memset(decrypt_buff, 0, ENCRYPT_SINGLE_SIZE);
if((srv_file_offset + ENCRYPT_SINGLE_SIZE) < src_file_size)
{
read(src_fd, src_buff, ENCRYPT_SINGLE_SIZE); // 读取密文文件内容
aes_decrypt(decrypt_buff, src_buff, ENCRYPT_SINGLE_SIZE); // 密文文件解密
write(decrypt_fd, decrypt_buff, ENCRYPT_SINGLE_SIZE); // 将解密内容写入解密文件中
srv_file_offset += ENCRYPT_SINGLE_SIZE;
}
else
{
read(src_fd, src_buff, ENCRYPT_SINGLE_SIZE); // 读取最后一包密文文件内容
aes_decrypt(decrypt_buff, src_buff, (ENCRYPT_SINGLE_SIZE)); // 密文文件解密
write(decrypt_fd, decrypt_buff, (src_file_size - srv_file_offset)); // 将最后一包解密内容写入解密文件中
break;
}
}
close(src_fd);
src_fd = -1;
close(decrypt_fd);
decrypt_fd = -1;
}
return 0;
}
验证时发现一个问题,加密内容的长度需要16字节的整数倍,所以加密完的文件大小也为16字节的整数倍。值得注意的是,解密的最后一包要根据明文文件的大小算出来的,然后写进解密文件中,因为加密文件是16字节对齐的,所以要去除16字节对齐。
编译及运行:
rice@rice:~/project/encrypt$ make
gcc -I ./tinycrypt/include -Wall -g -c main.c -o main.o
gcc -I ./tinycrypt/include -Wall -g -c tinycrypt/src/tiny_sha1.c -o tinycrypt/src/tiny_sha1.o
gcc -I ./tinycrypt/include -Wall -g -c tinycrypt/src/tiny_aes.c -o tinycrypt/src/tiny_aes.o
gcc -I ./tinycrypt/include -Wall -g -c tinycrypt/src/tiny_md5.c -o tinycrypt/src/tiny_md5.o
gcc -I ./tinycrypt/include -Wall -g -c tinycrypt/src/tiny_sha2.c -o tinycrypt/src/tiny_sha2.o
gcc -I ./tinycrypt/include -Wall -g -c tinycrypt/src/tiny_base64.c -o tinycrypt/src/tiny_base64.o
gcc main.o tinycrypt/src/tiny_sha1.o tinycrypt/src/tiny_aes.o tinycrypt/src/tiny_md5.o tinycrypt/src/tiny_sha2.o tinycrypt/src/tiny_base64.o -Wall -g -o output/tinycrypt_1.0.0
rice@rice:~/ohos/project/encrypt$ ./output/tinycrypt_1.0.0
136-INFO: source file size: 445
171-INFO: encrypt file size: 445
rice@rice:~/ohos/project/encrypt$
审核编辑 黄宇
全部0条评论
快来发表一下你的评论吧 !