本文參考鏈接:
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