linux openssl之EVP AES

linux openssl 值 AES加解密解说,本文章只要对openssl 之 EVP的api 函数讲解和代码例程展示。

openssl EVP相关api函数定义在(openssl/aes.h)头文件间,摘取如下所以:

/********对称加解密常用并推荐使用的api函数********/
int EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *a); 

int EVP_EncryptInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, ENGINE *impl, unsigned char *key, unsigned char *iv); 
int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out,int *outl, unsigned char *in, int inl); 
int EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out,int *outl); 

int EVP_DecryptInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, ENGINE *impl, unsigned char *key, unsigned char *iv); 
int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, unsigned char *in, int inl); 
int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *outm,int *outl); 

/********与上面的api函数功能功能相似,确切说上述函数都是调用下方函数进一步封装的********/
int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, ENGINE *impl, unsigned char *key, unsigned char *iv, int enc); 
int EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, unsigned char *in, int inl); 
int EVP_CipherFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl); 

/********下列函数为openssl旧版本所支持,为兼容以前的代码而被保留下来********/
int EVP_EncryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, unsigned char *key, unsigned char *iv); 
int EVP_EncryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl); 

int EVP_DecryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, unsigned char *key, unsigned char *iv); 
int EVP_DecryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl); 

int EVP_CipherInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, unsigned char *key, unsigned char *iv, int enc); 
int EVP_CipherFinal(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl); 

/* 其他常用api函数*/
int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *c, int pad);
EVP_CIPHER_CTX *EVP_CIPHER_CTX_new(void);
void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *ctx);
int EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *a); 

上面所列出的函数虽然很多,但是大部分是功能重复的,有的是旧的版本支持的函数,新的版本中已经可以不再使用了。事实上,函数EVP_EncryptInit, EVP_EncryptFinal, EVP_DecryptInit,EVP_DecryptFinal, EVP_CipherInit以及EVP_CipherFinal在新代码中不应该继续使用,他们保留下来只是为了兼容以前的代码。在新的代码中,应该使用EVP_EncryptInit_ex、EVP_EncryptFinal_ex、EVP_DecryptInit_ex、EVP_DecryptFinal_ex、EVP_CipherInit_ex以及EVP_CipherFinal_ex函数,因为它们可以在每次调用完算法后,不用重新释放和分配已有EVP_CIPHER_CTX结构的内存的情况下重用该结构,方便很多。下面我们分别对这些函数进行介绍。

函数解说:

1.int EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *a)

该函数初始化一个EVP_CIPHER_CTX结构体变量,只有初始化后该结构体才能在下面介绍的函数中使用。操作成功返回1,否则返回0。
注意openssl1.1.1开始不能使用“ EVP_CIPHER_CTX 变量名”来声明,否则编程出错。需要使用api函数:EVP_CIPHER_CTX_new来申请EVP_CIPHER_CTX 结构体变量内存。不适用是记得使用api函数:EVP_CIPHER_CTX_free释放内存,例如一下所示:

EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); //申请内存块,成功返回非NULL,失败返回NULL
........
EVP_CIPHER_CTX_free(ctx);	//释放内存块
/*
function:EVP_EncryptInit_ex
parameter:
       	ctx: 必须已初始化的EVP_CIPHER_CTX结构体参数
       	type:通常通过函数类型来提供参数,如EVP_aes_128_ecb()函数的形式
       	impl:通常使用NULL,即使用缺省的实现算法
       	key: 用于加密的对称密钥
       	iv:  iv参数是初始化向量(如果需要的话),不需要则设置为NULL
return:成功1, 失败0
*/
2.int EVP_EncryptInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, ENGINE *impl, unsigned char *key, unsigned char *iv);

若使用EVP_EncryptUpdate和EVP_EncryptFinal_ex进行加密的话,需要先调用EVP_EncryptInit_ex函数后才能进行加密操作。

/*
function:EVP_EncryptUpdate
parameter:
     	ctx:  必须已初始化的EVP_CIPHER_CTX结构体参数
     	out:  加密后的数据内存块首地址
     	outl: 加密后的数据字节长度
     	in:	  需要加密的原文数据内存块首地址
     	inl: 需要加密的原文数据字节长度
return:成功1, 失败0
*/
3.int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out,int *outl, unsigned char *in, int inl);

该函数用于对原文数据进行加密操作,加密数据范围,即参数outl的范围等于参数inl - inl%cipher_block_size。若需要加密的数据长度不是cipher_block_size整数倍,又没有disable padding功能,则剩余还没有加密的数据需要调用函数EVP_EncryptFinal_ex来处理。若需要加密的数据长度为cipher_block_size的整数倍,又disable padding功能,则参数outl == inl。若需要加密的数据长度为cipher_block_size的整数倍,但是没有disable padding功能,还是需要调用函数EVP_EncryptFinal_ex来结束加密操作。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
0、此例程调试环境 运行uname -a的结果如下: Linux freescale 3.0.35-2666-gbdde708-g6f31253 #1 SMP PREEMPT Thu Nov 30 15:45:33 CST 2017 armv7l GNU/Linux 简称2017 armv7l GNU/Linux 1、openssl 直接处理AES的API 在openssl/aes.h定义。是基本的AES库函数接口,可以直接调用,但是那个接口是没有填充的。而如果要与Java通信,必须要有填充模式。所以看第2条。 2、利用openssl EVP接口 在openssl/evp.h中定义。在这个接口中提供的AES是默认是pkcs5padding方式填充方案。 3、注意openssl新老版本的区别 看如下这段 One of the primary differences between master (OpenSSL 1.1.0) and the 1.0.2 version is that many types have been made opaque, i.e. applications are no longer allowed to look inside the internals of the structures. The biggest impact on applications is that: 1)You cannot instantiate these structures directly on the stack. So instead of: EVP_CIPHER_CTX ctx; you must instead do: EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); .... EVP_CIPHER_CTX_free(ctx); 2)You must only use the provided accessor functions to access the internals of the structure. 4、注意加密的内容是数据不限制是否为字符串 openssl接口加密的是数据,不限制是否为字符串,我看到有些人在加密时使用strlen(),来获取要加密的长度,如果是对字符串加密的话没有问题,如果不是字符串的话,用它获取的长度是到第一个0处,因为这个函数获取的是字符串长度,字符串是以零为终止的。 5、在调用EVP_EncryptFinal_ex时不要画蛇添足 正常加解密处理过程,引用网友的代码如下,经测试正确。 int kk_encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *key, unsigned char *iv, unsigned char *ciphertext) { EVP_CIPHER_CTX *ctx; int len; int ciphertext_len; ctx = EVP_CIPHER_CTX_new(); EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv); //EVP_EncryptInit_ex(ctx, EVP_aes_128_ecb(), NULL, key, iv); EVP_EncryptUpdate(ctx, ciphertext, &len;, plaintext, plaintext_len); ciphertext_len = len; EVP_EncryptFinal_ex(ctx, ciphertext + len, &len;); ciphertext_len += len; EVP_CIPHER_CTX_free(ctx); return ciphertext_len; } int kk_decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *key, unsigned char *iv, unsigned char *plaintext) { EVP_CIPHER_CTX *ctx; int len; int plaintext_len; ctx = EVP_CIPHER_CTX_new(); EVP_DecryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv); //EVP_DecryptInit_ex(ctx, EVP_aes_128_ecb(), NULL, key, iv); EVP_DecryptUpdate(ctx, plaintext, &len;, ciphertext, ciphertext_len); plaintext_len = len; EVP_DecryptFinal_ex(ctx, plaintext + len, &len;); plaintext_len += len; EVP_CIPHER_CTX_free(ctx); return plaintext_len; } 我看到有人提供的代码在加密长度正好是16字节的整数倍时特意不去调用EVP_EncryptFinal_ex,这实在是画蛇添足啊,不论什么情况下,最后一定要调用EVP_EncryptFinal_ex一次,然后结束加密过程。 6、Base64陷阱 如果用到了base64,要注意如下: 1)base64算法是将3个字节变成4个可显示字符。所以在如果数据长度不是3字节对齐时,会补0凑齐。 2)在解密时先要解base64,再解AES。在解base64后,要减掉补上的0。算法就去查看base64后的字符串尾处有几个=号,最多是2个,如果正好要加密的数据是3的倍数,不需要补0,那么base64后的数据尾处就没有=,如果补了1个0,就有一个=号。 算法如下: int encode_str_size = EVP_EncodeBlock(base64, en, el); int length = EVP_DecodeBlock(base64_out, base64, encode_str_size ); //EVP_DecodeBlock内部同样调用EVP_DecodeInit + EVP_DecodeUpdate + Evp_DecodeFinal实现,但是并未处理尾部的'='字符,因此结果字符串长度总是为3的倍数 while(base64[--encode_str_size] == '=') length--; 算法网友提供,测试正确。
### 回答1: openssl命令可以通过EVP库来解密EVP_aes_256_cbc加密的数据,具体命令如下: ``` openssl enc -d -aes-256-cbc -in [input_file] -out [output_file] -K [key_in_hex] -iv [iv_in_hex] ``` 其中: - `-d`: 指定解密操作。 - `-aes-256-cbc`: 指定使用AES-256算法和CBC模式。 - `-in [input_file]`: 指定输入文件路径。 - `-out [output_file]`: 指定输出文件路径。 - `-K [key_in_hex]`: 指定加密密钥,以16进制表示。 - `-iv [iv_in_hex]`: 指定初始化向量,以16进制表示。 例如,如果加密时使用的密钥是`0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef`,初始化向量是`0123456789abcdef0123456789abcdef`,加密后的数据保存在文件`encrypted.bin`中,解密后的数据要保存在文件`decrypted.bin`中,那么解密命令如下: ``` openssl enc -d -aes-256-cbc -in encrypted.bin -out decrypted.bin -K 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef -iv 0123456789abcdef0123456789abcdef ``` 执行命令后,输入密钥密码,即可完成解密操作。 ### 回答2: openssl是一个开放源代码的密码学工具库,它提供了各种加密和解密算法的实现。其中,EVP_aes_256_cbc是openssl库中的一个加密算法,它采用了256位的密钥长度和CBC(Cipher Block Chaining)模式。 要使用openssl解密EVP_aes_256_cbc命令,需要以下步骤: 1. 安装openssl:首先,需要在计算机上安装openssl库。可以通过下载openssl的源代码并编译安装,或者使用操作系统的包管理工具进行安装。 2. 准备密文和密钥:解密密文之前,需要获取密文和其对应的密钥。密文是通过EVP_aes_256_cbc算法加密得到的,密钥是用于解密的关键。确保密文和密钥的正确性和可用性。 3. 执行解密命令:使用openssl的命令行工具执行解密操作。打开终端或命令提示符,进入openssl的安装目录,执行以下命令: ``` openssl enc -d -aes-256-cbc -in ciphertext.txt -out plaintext.txt -pass file:secret.key ``` 其中,`ciphertext.txt`为密文文件的路径,`plaintext.txt`为解密后的明文输出文件的路径,`secret.key`为密钥文件的路径。`-d`表示解密操作,`-aes-256-cbc`指定了解密算法为EVP_aes_256_cbc。 4. 输入密钥密码:执行上述命令后,openssl会要求输入密钥密码。根据实际情况,输入正确的密钥密码并按下回车键。 5. 完成解密:执行完上述命令后,openssl会使用提供的密钥对密文进行解密,并将解密后的明文输出到指定的文件中。此时,解密操作完成。 需要注意的是,解密过程涉及到密文的保密性,在使用openssl解密时应确保密文和密钥不被泄露给不信任的第三方。此外,要保证openssl的正确安装和使用,以及密文和密钥的准确性。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值