您的位置:首页 > 运维架构

openssl之EVP

2015-06-26 17:00 183 查看
本文参考百度百科和http://blog.csdn.net/gdwzh/article/details/19231

一,什么是openssl?

SSL 是一个缩写,代表的是 Secure Sockets Layer。它是支持在 Internet 上进行安全通信的标准,并且将数据密码术集成到了协议之中。数据在离开您的计算机之前就已经被加密,然后只有到达它预定的目标后才被解密。证书和密码学算法支持了这一切的运转,使用 OpenSSL,您将有机会切身体会它们。

理论上,如果加密的数据在到达目标之前被截取或窃听,那些数据是不可能被破解的。不过,由于计算机的变化一年比一年快,而且密码翻译方法有了新的发展,因此,SSL 中使用的加密协议被破解的可能性也在增大。

可以将 SSL 和安全连接用于 Internet 上任何类型的协议,不管是 HTTP、POP3,还是 FTP。还可以用 SSL 来保护 Telnet 会话。虽然可以用 SSL 保护任何连接,但是不必对每一类连接都使用 SSL。如果连接传输敏感信息,则应使用 SSL。

OpenSSL 不仅仅是 SSL。它可以实现消息摘要、文件的加密和解密、数字证书、数字签名和随机数字。关于 OpenSSL 库的内容非常多,远不是一篇文章可以容纳的。OpenSSL 不只是 API,它还是一个命令行工具。命令行工具可以完成与 API 同样的工作,而且更进一步,可以测试 SSL 服务器和客户机。它还让开发人员对 OpenSSL 的能力有一个认识。

OpenSSL采用C语言作为开发语言,这使得OpenSSL具有优秀的跨平台性能,这对于广大技术人员来说是一件非常美妙的事情,可以在不同的平台使用同样熟悉的东西。OpenSSL支持Linux、Windows、BSD、Mac、VMS等平台,这使得OpenSSL具有广泛的适用性。

二,EVP

EVP是电脑的一种防毒技术,它可以防止缓存溢出,保护计算机免受缓存溢出型病毒及黑客程序的危害。

EVP系列的函数定义包含在#include "openssl/evp.h"里面,这是一系列封装了openssl加密库里面所有算法的函数。通过这样的统一的封装,使得只需要在初始化参数的时候做很少的改变,就可以使用相同的代码但采用不同的加密算法进行数据的加密和解密。
EVP系列函数主要封装了三大类型的算法:密钥证书管理,对称解密,非对称加密。

要支持全部这些算法,请调用OpenSSL_add_all_algorithms函数,下面分别就其结构作一个简单的介绍。

【公开密钥算法】

函数名称:EVP_Seal*...*,EVP_Open*...*

功能描述:该系列函数封装提供了公开密钥算法的加密和解密功能,实现了电子信封的功能。

相关文件:p_seal.c,p_open.c

【数字签名算法】

函数名称:EVP_Sign*...*,EVP_Verify*...*

功能描述:该系列函数封装提供了数字签名算法和功能。

相关文件:p_sign.c,p_verify.c

【对称加密算法】

函数名称:EVP_Encrypt*...*

功能描述:该系列函数封装提供了对称加密算法的功能。

相关文件:evp_enc.c,p_enc.c,p_dec.c,e_*.c

【信息摘要算法】

函数名称:EVP_Digest*...*

功能描述:该系列函数封装实现了多种信息摘要算法。

相关文件:digest.c,m_*.c

【信息编码算法】

函数名称:EVP_Encode*...*

功能描述:该系列函数封装实现了ASCII码与二进制码之间的转换函数和功能,如使用base64进行加密解密。

相关文件:encode.c

注意:

自从出现engin版本以后,所有对称加密算法和摘要算法可以用ENGINE模块实现的算法代替。如果ENGINE模块实现的对称加密和信息摘要函数被注册为缺省的实现算法,那么当使用各种EVP函数时,软件编译的时候会自动将该实现模块连接进去。

三,对称加密算法

对称加密算法封装的函数系列名字是以EVP_Encrypt*...*开头的,其实,这些函数只是简单调用了EVP_Cipher*...*系列的同名函数,换一个名字可能是为了更好的区别和理解。除了实现了对称加密算法外,EVP_Encrypt*...*系列还对块加密算法提供了缓冲功能。以后我们可能会更多使用EVP_Cipher的术语,因为它是真正的实现结构。

EVP_CIPHER和EVP_CIPHER_CTX这两个结构是EVP_Cipher(EVP_Encrypt)系列的两个基本结构,它们的其它一些列函数都是以这两个结构为基础实现了。文件evp/evp_enc.c是最高层的封装实现,各种加密的算法的封装在p_enc.c里面实现,解密算法的封装在p_dec.c里面实现,而各个e_*.c文件则是真正实现了各种算法的加解密功能,当然它们其实也是一些封装函数,真正的算法实现在各个算法同名目录里面的文件实现。

四,EVP_Encrypt支持的对称加密算法列表

openssl对称加密算法的格式都以函数形式提供,其实该函数返回一个该算法的结构体,其形式一般如下:

EVP_CIPHER* EVP_*(void)

在openssl中,所有提供的对称加密算法长度都是固定的,有特别说明的除外。下面对这些算法进行分类的介绍,首先介绍一下算法中使用的通用标志的含义。

【通用标志】

ecb——电子密码本(Electronic Code Book)加密方式

cbc——加密块链接(Cipher Block Chaining)加密方式

cfb——64位加密反馈(Cipher Feedback)加密方式

ofb——64位输出反馈(Output Feedback)加密方式

ede——该加密算法采用了加密、解密、加密的方式,第一个密钥和最后一个密钥是相同的

ede3——该加密算法采用了加密、解密、加密的方式,但是三个密钥都不相同

【NULL算法】

函数:EVP_enc_null()

说明:该算法不作任何事情,也就是没有进行加密处理

【DES算法】

函数:EVP_des_cbc(void), EVP_des_ecb(void), EVP_des_cfb(void), EVP_des_ofb(void)

说明:分别是CBC方式、ECB方式、CFB方式以及OFB方式的DES算法

【使用两个密钥的3DES算法】

函数:EVP_des_ede_cbc(void), EVP_des_ede(), EVP_des_ede_ofb(void),EVP_des_ede_cfb(void)

说明:分别是CBC方式、ECB方式、CFB方式以及OFB方式的3DES算法,算法的第一个密钥和最后一个密钥相同,事实上就只需要两个密钥

【使用三个密钥的3DES算法】

函数:EVP_des_ede3_cbc(void), EVP_des_ede3(), EVP_des_ede3_ofb(void), EVP_des_ede3_cfb(void)

说明:分别是CBC方式、ECB方式、CFB方式以及OFB方式的3DES算法,算法的三个密钥都不相同

【DESX算法】

函数:EVP_desx_cbc(void)

说明:CBC方式DESX算法

【RC4算法】

函数:EVP_rc4(void)

说明:RC4流加密算法。该算法的密钥长度可以改变,缺省是128位。

【40位RC4算法】

函数:EVP_rc4_40(void)

说明:密钥长度40位的RC4流加密算法。该函数可以使用EVP_rc4和EVP_CIPHER_CTX_set_key_length函数代替。

【IDEA算法】

函数:EVP_idea_cbc(),EVP_idea_ecb(void), EVP_idea_cfb(void), EVP_idea_ofb(void)

说明:分别是CBC方式、ECB方式、CFB方式以及OFB方式的IDEA算法。

【RC2算法】

函数:EVP_rc2_cbc(void), EVP_rc2_ecb(void), EVP_rc2_cfb(void), EVP_rc2_ofb(void)

说明:分别是CBC方式、ECB方式、CFB方式以及OFB方式的RC2算法,该算法的密钥长度是可变的,可以通过设置有效密钥长度或有效密钥位来设置参数来改变。缺省的是128位。

【定长的两种RC2算法】

函数:EVP_rc2_40_cbc(void), EVP_rc2_64_cbc(void)

说明:分别是40位和64位CBC模式的RC2算法。

【Blowfish算法】

函数:EVP_bf_cbc(void), EVP_bf_ecb(void), EVP_bf_cfb(void), EVP_bf_ofb(void)

说明:分别是CBC方式、ECB方式、CFB方式以及OFB方式的Blowfish算法,该算法的密钥长度是可变的

【CAST算法】

函数:EVP_cast5_cbc(void), EVP_cast5_ecb(void), EVP_cast5_cfb(void), EVP_cast5_ofb(void)

说明:分别是CBC方式、ECB方式、CFB方式以及OFB方式的CAST算法,该算法的密钥长度是可变的

【RC5算法】

函数:EVP_rc5_32_12_16_cbc(void), EVP_rc5_32_12_16_ecb(void), EVP_rc5_32_12_16_cfb(void), EVP_rc5_32_12_16_ofb(void)

说明:分别是CBC方式、ECB方式、CFB方式以及OFB方式的RC5算法,该算法的密钥长度可以根据参数“number of rounds”(算法中一个数据块被加密的次数)来设置,缺省的是128位密钥,加密次数为12次。目前来说,由于RC5算法本身实现代码的限制,加密次数只能设置为8、12或16。

【128位AES算法】

函数:EVP_aes_128_ecb(void),EVP_aes_128_cbc(void),PEVP_aes_128_cfb(void),EVP_aes_128_ofb(void)

说明:分别是CBC方式、ECB方式、CFB方式以及OFB方式的128位AES算法

【192位AES算法】

函数:EVP_aes_192_ecb(void),EVP_aes_192_cbc(void),PEVP_aes_192_cfb(void),EVP_aes_192_ofb(void)

说明:分别是CBC方式、ECB方式、CFB方式以及OFB方式的192位AES算法

【256位AES算法】

函数:EVP_aes_256_ecb(void),EVP_aes_256_cbc(void),PEVP_aes_256_cfb(void),EVP_aes_256_ofb(void)

说明:分别是CBC方式、ECB方式、CFB方式以及OFB方式的256位AES算法

上述的算法是0.9.7版本支持的所有对称加密算法。

五,EVP_Encrypt系列函数讲解

EVP_Cipher系列包含了很多函数,我将他们大概分成两部分来介绍,一部分是基本函数系列,就是本文要介绍的,另一个部分是设置函数系列。基本系列函数主要是进行基本的加密和解密操作的函数,他们的定义如下(openssl/evp.h):

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);

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);

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);

int EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *a);

其实在这里列出的函数虽然很多,但是大部分是功能重复的,有的是旧的版本支持的函数,新的版本中已经可以不再使用了。事实上,函数EVP_EncryptInit, EVP_EncryptFinal, EVP_DecryptInit, 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结构的内存的情况下重用该结构,方便很多。下面我们分别对这些函数进行介绍。

【EVP_CIPHER_CTX_init】

该函数初始化一个EVP_CIPHER_CTX结构体,只有初始化后该结构体才能在下面介绍的函数中使用。操作成功返回1,否则返回0。

【EVP_EncryptInit_ex】

该函数采用ENGINE参数impl的算法来设置并初始化加密结构体。其中,参数ctx必须在调用本函数之前已经进行了初始化。参数type通常通过函数类型来提供参数,如EVP_des_cbc函数的形式,即我们上一章中介绍的对称加密算法的类型。如果参数impl为NULL,那么就会使用缺省的实现算法。参数key是用来加密的对称密钥,iv参数是初始化向量(如果需要的话)。在算法中真正使用的密钥长度和初始化密钥长度是根据算法来决定的。在调用该函数进行初始化的时候,除了参数type之外,所有其它参数可以设置为NULL,留到以后调用其它函数的时候再提供,这时候参数type就设置为NULL就可以了。在缺省的加密参数不合适的时候,可以这样处理。操作成功返回1,否则返回0。

【EVP_EncryptUpdate】

该函数执行对数据的加密。该函数加密从参数in输入的长度为inl的数据,并将加密好的数据写入到参数out里面去。可以通过反复调用该函数来处理一个连续的数据块。写入到out的数据数量是由已经加密的数据的对齐关系决定的,理论上来说,从0到(inl+cipher_block_size-1)的任何一个数字都有可能(单位是字节),所以输出的参数out要有足够的空间存储数据。写入到out中的实际数据长度保存在outl参数中。操作成功返回1,否则返回0。

【EVP_EncryptFinal_ex】

该函数处理最后(Final)的一段数据。在函数在padding功能打开的时候(缺省)才有效,这时候,它将剩余的最后的所有数据进行加密处理。该算法使用标志的块padding方式(AKA PKCS padding)。加密后的数据写入到参数out里面,参数out的长度至少应该能够一个加密块。写入的数据长度信息输入到outl参数里面。该函数调用后,表示所有数据都加密完了,不应该再调用EVP_EncryptUpdate函数。如果没有设置padding功能,那么本函数不会加密任何数据,如果还有剩余的数据,那么就会返回错误信息,也就是说,这时候数据总长度不是块长度的整数倍。操作成功返回1,否则返回0。

PKCS padding标准是这样定义的,在被加密的数据后面加上n个值为n的字节,使得加密后的数据长度为加密块长度的整数倍。无论在什么情况下,都是要加上padding的,也就是说,如果被加密的数据已经是块长度的整数倍,那么这时候n就应该等于块长度。比如,如果块长度是9,要加密的数据长度是11,那么5个值为5的字节就应该增加在数据的后面。

【EVP_DecryptInit_ex, EVP_DecryptUpdate和EVP_DecryptFinal_ex】

这三个函数是上面三个函数相应的解密函数。这些函数的参数要求基本上都跟上面相应的加密函数相同。如果padding功能打开了,EVP_DecryptFinal会检测最后一段数据的格式,如果格式不正确,该函数会返回错误代码。此外,如果打开了padding功能,EVP_DecryptUpdate函数的参数out的长度应该至少为(inl+cipher_block_size)字节;但是,如果加密块的长度为1,则其长度为inl字节就足够了。三个函数都是操作成功返回1,否则返回0。

需要注意的是,虽然在padding功能开启的情况下,解密操作提供了错误检测功能,但是该功能并不能检测输入的数据或密钥是否正确,所以即便一个随机的数据块也可能无错的完成该函数的调用。如果padding功能关闭了,那么当解密数据长度是块长度的整数倍时,操作总是返回成功的结果。

【EVP_CipherInit_ex, EVP_CipherUpdate和EVP_CipherFinal_ex】

事实上,上面介绍的函数都是调用这三个函数实现的,它们是更底层的函数。完成了数据的加密和解密功能。他们根据参数enc决定执行加密还是解密操作,如果enc为1,则加密;如果enc为0,则解密;如果enc是-1,则不改变数据。三个函数都是操作成功返回1,否则返回0。

【EVP_CIPHER_CTX_cleanup】

该函数清除一个EVP_CIPHER_CTX结构中的所有信息并释放该结构占用的所有内存。在使用上述的函数完成一个加密算法过程后应该调用该函数,这样可以避免一些敏感信息遗留在内存造成安全隐犯。操作成功返回1,否则返回0。

【EVP_EncryptInit, EVP_DecryptInit和EVP_CipherInit】

这三个函数的功能分别跟函数EVP_EncryptInit_ex, EVP_DecryptInit_ex和EVP_CipherInit_ex功能相同,只是他们的ctx参数不需要进行初始化,并且使用缺省的算法库。三个函数都是操作成功返回1,否则返回0。

【EVP_EncryptFinal, EVP_DecryptFinal和EVP_CipherFinal】

这三个函数分别跟函数EVP_EncryptFinal_ex, EVP_DecryptFinal_ex以及EVP_CipherFinal_ex函数功能相同,不过,他们的参数ctx会在调用后自动释放。三个函数都是操作成功返回1,否则返回0。

接下来将介绍他们的一些扩充部分,即一些参数设置和其它辅助的函数,其定义如下(openssl/evp.h):

int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *x, int padding);

int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *x, int keylen);

const EVP_CIPHER *EVP_get_cipherbyname(const char *name);

#define EVP_get_cipherbynid(a) EVP_get_cipherbyname(OBJ_nid2sn(a))

#define EVP_get_cipherbyobj(a) EVP_get_cipherbynid(OBJ_obj2nid(a))

int EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *a);

#define EVP_CIPHER_nid(e) ((e)->nid)

#define EVP_CIPHER_block_size(e) ((e)->block_size)

#define EVP_CIPHER_key_length(e) ((e)->key_len)

#define EVP_CIPHER_iv_length(e) ((e)->iv_len)

#define EVP_CIPHER_flags(e) ((e)->flags)

#define EVP_CIPHER_mode(e) ((e)->flags) & EVP_CIPH_MODE)

int EVP_CIPHER_type(const EVP_CIPHER *ctx);

#define EVP_CIPHER_CTX_cipher(e) ((e)->cipher)

#define EVP_CIPHER_CTX_nid(e) ((e)->cipher->nid)

#define EVP_CIPHER_CTX_block_size(e) ((e)->cipher->block_size)

#define EVP_CIPHER_CTX_key_length(e) ((e)->key_len)

#define EVP_CIPHER_CTX_iv_length(e) ((e)->cipher->iv_len)

#define EVP_CIPHER_CTX_get_app_data(e) ((e)->app_data)

#define EVP_CIPHER_CTX_set_app_data(e,d) ((e)->app_data=(char *)(d))

#define EVP_CIPHER_CTX_type(c) EVP_CIPHER_type(EVP_CIPHER_CTX_cipher(c))

#define EVP_CIPHER_CTX_flags(e) ((e)->cipher->flags)

#define EVP_CIPHER_CTX_mode(e) ((e)->cipher->flags & EVP_CIPH_MODE)

int EVP_CIPHER_param_to_asn1(EVP_CIPHER_CTX *c, ASN1_TYPE *type);

int EVP_CIPHER_asn1_to_param(EVP_CIPHER_CTX *c, ASN1_TYPE *type);

【EVP_CIPHER_CTX_set_padding】

该函数设置是否采用padding功能.在算法缺省的情况下,是使用标准的块padding功能的,并且在解密的时候会自动接测padding并将它删除。如果将参数pad设置为0,则padding功能就会被禁止,那么在加密和解密的时候,数据应该为加密块长度的整数倍,否则就会出错。函数恒返回1。

【EVP_CIPHER_CTX_set_key_length】

该函数进行加密算法结构EVP_CIPHER_CTX密钥长度的设置。如果算法是一个密钥长度固定的算法,那么如果设置的密钥长度跟它固定的长度不一致,就会产生错误。

【EVP_get_cipherbyname, EVP_get_cipherbynid和EVP_get_cipherbyobj】

这三个函数都根据给定的参数返回一个EVP_CIPHER结构,不同的是给定的参数分别是算法名称、算法的NID和一个ASN1_OBJECT结构。具体的算法名称、NID以及ASN1_OBJECT结构请参看object/boject.h文件的定义。

【EVP_CIPHER_nid和EVP_CIPHER_CTX_nid】

这两个函数返回EVP_CIPHER或EVP_CIPHER_CTX结构内部的算法的NID。返回的NID值只是一个内部存储的值,并不一定真的有相应的OBJECT定义。

【EVP_CIPHER_key_length和EVP_CIPHER_CTX_key_length】

这两个函数返回EVP_CIPHER或EVP_CIPHER_CTX结构内部的算法的密钥长度。常量EVP_MAX_KEY_LENGTH定义了所有算法最长的密钥长度。需要注意的是,对于EVP_CIPHER_key_length函数来说,对特定的一种算法密钥长度是不变的,但是EVP_CIPHER_CTX_key_length函数对同一个算法密钥长度却是可变的。

【EVP_CIPHER_iv_length和EVP_CIPHER_CTX_iv_length】

这两个函数返回EVP_CIPHER或EVP_CIPHER_CTX结构内部的算法的初始化向量长度。如果算法不使用IV,那么就会返回0。常量EVP_MAX_IV_LENGTH定义了所有算法最长的IV长度

【EVP_CIPHER_block_size和EVP_CIPHER_CTX_block_size】

这两个函数返回EVP_CIPHER或EVP_CIPHER_CTX结构内部的算法的加密块长度。常量EVP_MAX_IV_LENGTH也是所有算法最长的块长度。

【EVP_CIPHER_type和EVP_CIPHER_CTX_type】

这两个函数返回EVP_CIPHER或EVP_CIPHER_CTX结构内部的算法的类型。该类型的值是算法的NID,一般来说,NID忽略了算法的一些参数,如40位和129位RC2算法的NID是相同的。如果算法没有相应定义的NID或者不是ASN1所支持的,那么本函数就会返回NID_undef。

【EVP_CIPHER_CTX_cipher】

该函数返回EVP_CIPHER_CTX结构里面的EVP_CIPHER结构。

【EVP_CIPHER_mode和EVP_CIPHER_CTX_mode】

这两个函数返回相应结构算法的块加密模式,包括EVP_CIPH_ECB_MODE, EVP_CIPH_CBC_MODE, EVP_CIPH_CFB_MODE和EVP_CIPH_OFB_MODE;如果算法是流加密算法,那么就返回EVP_CIPH_STREAM_CIPHER 。

【EVP_CIPHER_param_to_asn1】

该函数设置算法结构的参数,一般来说设置的值包括了所有参数和一个IV值。如果算法有IV,那么调用该函数时IV是必须设置的。该函数必须在所设置的算法结构使用之前(如调用EVP_EncryptUpdate和EVP_DecryptUpdate函数之前)调用。如果ASN1不支持该算法,那么调用该函数将导致失败。操作成功返回1,否则返回0。

【EVP_CIPHER_asn1_to_param】

该函数给用算法结构里面的值设置参数type的结构。其设置的内容由具体的算法决定。如在RC2算法中,它会设置IV和有效密钥长度。本函数应该在算法结构的基本算法类型已经设置了但是密钥还没有设置之前调用。例如,调用EVP_CipherInit函数的时候使用参数IV,并将key设置位NULL,然后就应该调用本函数,最后再调用EVP_CipherInit,这时候除了key设置位NULL外所有参数都应该设置。当ASN1不支持不支持该算法或者有参数不能设置的时候(如RC2的有效密钥长度不支持),该函数调用就会失败。操作成功返回1,否则返回0。

【EVP_CIPHER_CTX_ctrl】

该函数可以设置不同算法的特定的参数。目前只有RC2算法的有效密钥长度和RC5算法的加密次数(rounds)可以进行设置。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: