用openssl aes256 api实现文件加解密-带例程,兼容openssl enc -aes-256-cbc命令
本文参考链接:
https://blog.csdn.net/u010144805/article/details/78627599
https://blog.csdn.net/u010144805/article/details/78627599
https://blog.csdn.net/zisehuoxia/article/details/106214671
感谢他们的分享!
下面是我自己的尝试过程,记录一下:
我的ubuntu版本: 16.04 64位
openssl 版本:OpenSSL 1.0.2g 1 Mar 2016 (输入命令 openssl version -a查看)
于是我下了源码包回来, 链接: http://www.linuxfromscratch.org/blfs/view/7.9/postlfs/openssl.html
从源码中将相关文件移到一个目录里面(Makefile, main.c,uImage自己新建, uImage.enc uImage.dec是生成文件)
移植后的目录结构:
改过的一些文件内容:
aes_locl.h
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
#define STRICT_ALIGNMENT 1
#undef PEDANTIC
#undef FULL_UNROLL
#undef OPENSSL_SMALL_FOOTPRINT
# define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ ((u32)(pt)[2] << 8) ^ ((u32)(pt)[3]))
# define PUTU32(ct, st) { (ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); (ct)[2] = (u8)((st) >> 8); (ct)[3] = (u8)(st); }
typedef long long i64;
typedef unsigned long long u64;
typedef unsigned int u32;
typedef unsigned short u16;
typedef unsigned char u8;
# define MAXKC (256/32)
# define MAXKB (256/8)
# define MAXNR 14
main.c
#include <aes_locl.h>
#include <openssl/modes.h>
#include <openssl/aes.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
unsigned char *padding_buf(unsigned char *buf,int size, int *final_size) {//注释2
unsigned char *ret = NULL;
int pidding_size = AES_BLOCK_SIZE - (size % AES_BLOCK_SIZE);
int i;
*final_size = size + pidding_size;
//printf("\n###CYH: before size: %d, final_size is %d\n\n", size, *final_size);
ret = (unsigned char *)malloc(size+pidding_size);
memcpy( ret, buf, size);
if (pidding_size!=0) {
for (i =size;i < (size+pidding_size); i++ ) {
ret[i] = pidding_size;
}
}
return ret;
}
void printf_buff(unsigned char *buff,int size) {
int i = 0;
for (i=0;i<size;i ++ ) {
printf( "%02X ", (unsigned char)buff[i] );
if ((i+1) % 16 == 0) {
printf("\n");
}
}
printf("\n");
}
int main()
{
//unsigned char key[32] = "1234567890";
unsigned char key[32] = {0x11, 0x22, 0x33, 0x44, 0x55,0x66, 0x77, 0x88}; //注意:这里必须是16进制
//unsigned char iv[16] = "123456";
unsigned char iv[16] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; // 注意:这里必须是16进制
unsigned char iv_copy[16];
unsigned char *buf_normal;
unsigned char *buf_encrypt;
unsigned char *buf_decrypt;
unsigned char *after_padding_buf;
AES_KEY aesKey;
int fd_normal, fd_encrypt, fd_decrypt;
unsigned int filesize = 0;
struct stat statbuf;
int ret = 0, i;
int final_size = 0;
//print key and iv content
printf("\n\n###CYH: key: ");
for (i = 0; i < 32; i++)
printf("%02x", key[i]);
printf(" size: %d bytes\n", (int)sizeof(key));
printf("###CYH: iv: ");
for (i = 0; i < 16; i++)
printf("%02x", iv[i]);
printf(" size: %d bytes\n", (int)sizeof(iv));
//get normal file size
stat("./uImage",&statbuf);
filesize=statbuf.st_size;
printf("###CYH: get uImage file size: %d bytes\n", filesize);
//malloc memory
buf_normal = malloc(filesize);
//get normal file data
fd_normal = open("./uImage", O_RDONLY);
ret = read(fd_normal, buf_normal, filesize);
printf("###CYH: read uImage buf size: %d bytes\n", ret);
//加密
printf("\n###CYH: before padding, buf(size: %d bytes):\n", filesize);
printf_buff(buf_normal, filesize);
after_padding_buf = padding_buf(buf_normal, filesize, &final_size);
printf("\n###CYH: after padding, buf(size: %d bytes): \n", final_size);
printf_buff(after_padding_buf, final_size);
buf_encrypt = malloc(final_size);
buf_decrypt = malloc(final_size);
memcpy(iv_copy, iv, 16);//向量在运算过程中会被改变,为了之后可以正常解密,拷贝一份副本使用
private_AES_set_encrypt_key(key, 256, &aesKey);
AES_cbc_encrypt(after_padding_buf, buf_encrypt, final_size, &aesKey, iv_copy, 1);
printf("\n###CYH: after encrypt: \n");
printf_buff(buf_encrypt, final_size);
fd_encrypt = open("./uImage.enc", O_CREAT|O_RDWR, 0755);
ret = write(fd_encrypt, buf_encrypt, final_size);
printf("###CYH: have wrote %d bytes to uImage.enc\n", ret);
close(fd_encrypt);
//解密
memcpy(iv_copy, iv, 16);
private_AES_set_decrypt_key(key, 256, &aesKey);
AES_cbc_encrypt(buf_encrypt, buf_decrypt, final_size, &aesKey, iv_copy, 0);
printf("\n###CYH: after decrypt: \n");
printf_buff(buf_decrypt, filesize);
// comapare result
if(!memcmp(after_padding_buf, buf_decrypt, final_size)) {
printf("\n###CYH: test success\n\n");
}else {
printf("\n###CYH: test failed\n\n");
}
// write decrypt file
fd_decrypt = open("./uImage.dec", O_CREAT|O_RDWR, 0755);
ret = write(fd_decrypt, buf_decrypt, filesize);
printf("###CYH: have wrote %d bytes to uImage.dec\n\n", ret);
close(fd_decrypt);
return 0;
}
Makefile
CC := gcc
AS := as
LD := ld
INCLUDE := -I.
INCLUDE += -I ./include
DEFINES :=
#DEFINES += -D AUTO_INIT
CFLAGS := -g -Wall -O3 $(DEFINES) $(INCLUDE)
LIBS :=
LIBS += -lpthread
LDFLAGS :=
.PHONY : all clean
TARGET = aestest
OBJS = main.c aes_cbc.c aes_core.c cbc128.c
all: $(TARGET)
$(TARGET): $(OBJS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LDFLAGS) $(LIBS)
clean:
rm -f $(TARGET)
rm -f *.o
rm -f uImage.*
uImage
testopenssltestopenssltestopenssltestopenssltestopenssltestopenssltestopenssltestopenssl
测试
测试过程操作及输出:
rm -f aestest
rm -f *.o
rm -f uImage.*
gcc -g -Wall -O3 -I. -I ./include -o aestest main.c aes_cbc.c aes_core.c cbc128.c -lpthread
###CYH: key: 1122334455667788000000000000000000000000000000000000000000000000 size: 32 bytes
###CYH: iv: 11223344556600000000000000000000 size: 16 bytes
###CYH: get uImage file size: 89 bytes
###CYH: read uImage buf size: 89 bytes
74 65 73 74 6F 70 65 6E 73 73 6C 74 65 73 74 6F
70 65 6E 73 73 6C 74 65 73 74 6F 70 65 6E 73 73
6C 74 65 73 74 6F 70 65 6E 73 73 6C 74 65 73 74
6F 70 65 6E 73 73 6C 74 65 73 74 6F 70 65 6E 73
73 6C 74 65 73 74 6F 70 65 6E 73 73 6C 74 65 73
74 6F 70 65 6E 73 73 6C 0A
74 65 73 74 6F 70 65 6E 73 73 6C 74 65 73 74 6F
70 65 6E 73 73 6C 74 65 73 74 6F 70 65 6E 73 73
6C 74 65 73 74 6F 70 65 6E 73 73 6C 74 65 73 74
6F 70 65 6E 73 73 6C 74 65 73 74 6F 70 65 6E 73
73 6C 74 65 73 74 6F 70 65 6E 73 73 6C 74 65 73
74 6F 70 65 6E 73 73 6C 0A 07 07 07 07 07 07 07 (补全)
###CYH: after encrypt:
D4 9D E2 C7 49 70 71 4A 9A CD 85 52 5D D6 74 70
6C 47 D2 84 96 4D 21 A0 61 A7 D7 FB D9 3A 49 5E
7A 75 72 11 11 3D 47 2B 85 33 D9 DC 94 AA 16 11
1E F7 76 74 23 CC A9 51 6D 83 54 FE 11 EE C0 BE
19 EF B8 E4 FE 2E 17 2D D8 43 B5 8F FF F8 FA 95
41 64 12 58 58 06 8D 2E 56 48 3A F9 AB 5D 3B 16
74 65 73 74 6F 70 65 6E 73 73 6C 74 65 73 74 6F
70 65 6E 73 73 6C 74 65 73 74 6F 70 65 6E 73 73
6C 74 65 73 74 6F 70 65 6E 73 73 6C 74 65 73 74
6F 70 65 6E 73 73 6C 74 65 73 74 6F 70 65 6E 73
73 6C 74 65 73 74 6F 70 65 6E 73 73 6C 74 65 73
74 6F 70 65 6E 73 73 6C 0A
可见上面已经测试成功了
利用openssl命令对通过代码生成的加密文件uImage.enc进行解密:
openssl enc -aes256 -d -p -K 1122334455667788 -iv 112233445566 -in uImage.enc -out uImage.dec (大写的K)
没报错, 测试通过
加上p选项可以把key打印出来
可能会出现的报错:
如果代码里面的iv和key写的是字符串,那可能会出现以下错误:
bert@bert-virtual-machine:/media/bert/work/testopenssl$ openssl enc -aes-256-cbc -d -p -K 1122334455667788 -iv 112233445566 -in uImage.enc -out uImage.dec salt=0000000000000000 key=1122334455667788000000000000000000000000000000000000000000000000 iv =11223344556600000000000000000000 bad decrypt 140185284007576:error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt:evp_enc.c:529:
如果你不做padding buf这一步(或者你全补的是0),也就是补成16的倍数,你会遇到下面报错
salt=0100000000000000
key=1122334455667788000000000000000000000000000000000000000000000000
iv =11223344556600000000000000000000
bad decrypt
140648214177432:error:0606506D:digital envelope routines:EVP_DecryptFinal_ex:wrong final block length:evp_enc.c:518:
如果key不对你可能会遇到报错
openssl enc -aes256 -d -p -K 1122334455667788 -iv 112233445566 -in uImage.enc -out uImage.dec (大写的K) --> 大写的K,写成小写的k
bert@bert-virtual-machine:/media/bert/work/testopenssl$ openssl enc -aes-256-cbc -d -p -k 1122334455667788 -iv 112233445566 -in uImage.enc -out uImage.dec
bad magic number