用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("
###CYH: before size: %d, final_size is %d

", 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("
");
        }
    }
    printf("
");
}

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("

###CYH: key: ");
    for (i = 0; i < 32; i++)
        printf("%02x", key[i]);
    printf(" size: %d bytes
", (int)sizeof(key));

    printf("###CYH:  iv: ");
    for (i = 0; i < 16; i++)
        printf("%02x", iv[i]);
    printf(" size: %d bytes
", (int)sizeof(iv));

    //get normal file size
    stat("./uImage",&statbuf);
    filesize=statbuf.st_size;
    printf("###CYH: get uImage file size: %d bytes
", 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
", ret);
    
    //加密
    printf("
###CYH: before padding, buf(size: %d bytes):
", filesize);
    printf_buff(buf_normal, filesize);
    after_padding_buf = padding_buf(buf_normal, filesize, &final_size);
    printf("
###CYH: after padding, buf(size: %d bytes): 
", 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("
###CYH: after encrypt: 
");
    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
", 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("
###CYH: after decrypt: 
");
    printf_buff(buf_decrypt, filesize);

    // comapare result
    if(!memcmp(after_padding_buf, buf_decrypt, final_size)) {
        printf("
###CYH: test success

");    
    }else {
        printf("
###CYH: test failed

");    
    }

    // 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 ", 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

 

测试

测试过程操作及输出:
bert@bert-virtual-machine:/media/bert/work/testopenssl$ make clean && make && ./aestest
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

###CYH: before padding, 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

###CYH: after padding, buf(size: 96 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 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

###CYH: have wrote 96 bytes to uImage.enc

###CYH: after decrypt:
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

###CYH: test success

###CYH: have wrote 89 bytes to uImage.dec 

可见上面已经测试成功了

 

利用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

 

原文地址:https://www.cnblogs.com/cheyihaosky/p/13467341.html