OpenSSL之EVP用法
OpenSSL EVP(high-level cryptographic functions)提供了丰富的密码学中的各种函数。OpenSSL中实现了各种对称算法、摘要算法以及签名/验签算法。EVP函数将这些具体的算法进行了封装。
EVP主要封装了如下功能函数:
1)实现了BASE64编解码BIO;
2)实现了加解密BIO;
3)实现了摘要BIO;
4)实现了reliable BIO;
5)封装了摘要算法;
6)封装了对称加解密算法;
7)封装了非对称密钥的加密(公钥)、解密(私钥)、签名与验证以及辅助函数;
8)基于口令的加密(PBE);
9)对称密钥处理;
10)数字信封:数字信封用对方的公钥加密对称密钥,数据则用此对称密钥加密。发送给对方时,同时发送对称密钥密文和数据密文。接收方首先用自己的私钥解密密钥密文,得到对称密钥,然后用它解密数据。
11)其他辅助函数。
本文假设你已经安装好了OpenSSL,并且持有一份1.1.1的源码。
EVP相关的头文件在evp.h中、源文件在crypto/evp目录中。
由于EVP的功能过于强大,再加上我的精力和水平有限,暂时只对部分功能进行摘录和说明。
这个结构定义了摘要算法的抽象方法。主要字段含义:
type —— 摘要算法的NID。
pkey_type —— 与摘要算法相关的密钥NID。
md_size —— 摘要值的输出大小。
flags —— 内部标志。
init —— 初使化函数。
update —— 输入计算函数。
final —— 输出计算函数。
copy —— 摘要运算上下文复制函数。
cleanup —— 摘要运算上下文清理函数。
block_size —— 摘要运算分组大小。
ctx_size —— 摘要运算分组缓冲区大小。
md_ctrl —— 摘要运算指令控制函数。
支持的摘要算法包括:
const EVP_MD *EVP_md5(void);
const EVP_MD *EVP_sha1(void);
const EVP_MD *EVP_sha256(void);
const EVP_MD *EVP_sha512(void);
拿EVP_md5()来说,其返回值为:
下面这几个函数查询md的属性信息:
有时我们对使用的摘要算法不熟悉,这几个函数很有帮助。
EVP_MD_CTX *EVP_MD_CTX_new(void);
void EVP_MD_CTX_free(EVP_MD_CTX *ctx);
这两个函数用于创建和释放对称摘要上下文对象。
int EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type);
初使化摘要上下文,type为摘要算法抽象集合。
成功返回1,失败返回0。
int EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *d, size_t cnt);
向摘要计算的海棉结构输入一段数据。
成功返回1,失败返回0。
int EVP_DigestFinal(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *s);
生成最终摘要,输出摘要值和长度。
成功返回1,失败返回0。
int EVP_Digest(const void *data, size_t count, unsigned char *md, unsigned int *size, const EVP_MD *type, ENGINE *impl);
使用包装的一次性方法计算一段小数据的摘要。
成功返回1,失败返回0。
struct evp_cipher_st {
int nid;
int block_size;
/* Default value for variable length ciphers /
int key_len;
int iv_len;
/ Various flags /
unsigned long flags;
/ init key /
int ( init) (EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char iv, int enc);
/ encrypt/decrypt data /
int ( do_cipher) (EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char in, size_t inl);
/ cleanup ctx /
int ( cleanup) (EVP_CIPHER_CTX );
/ how big ctx->cipher_data needs to be /
int ctx_size;
/ Populate a ASN1_TYPE with parameters /
int ( set_asn1_parameters) (EVP_CIPHER_CTX *, ASN1_TYPE );
/ Get parameters from a ASN1_TYPE /
int ( get_asn1_parameters) (EVP_CIPHER_CTX *, ASN1_TYPE );
/ Miscellaneous operations /
int ( ctrl) (EVP_CIPHER_CTX *, int type, int arg, void ptr);
/ Application data */
void app_data;
} / EVP_CIPHER */ ;
typedef struct evp_cipher_st EVP_CIPHER;
这个结构定义了对称加密算法的抽象方法。主要字段含义:
nid —— 加密算法的NID。
block_size —— 分组大小。
key_len —— 密钥长度。
iv_len —— 初使向量长度。
flags —— 内部标志。
init —— 初使化函数。
do_cipher —— 中间运算函数。
cleanup —— 最终运算函数。
ctx_size —— 上下文大小。
ctrl —— 控制函数。
app_data —— 应用程序数据。
支持的CIPHER抽象加解密算法包括:
const EVP_CIPHER *EVP_des_ecb(void);
const EVP_CIPHER *EVP_des_ede3(void);
const EVP_CIPHER *EVP_aes_128_ecb(void);
const EVP_CIPHER *EVP_aes_128_cbc(void);
下面这几个函数查询cipher的属性信息:
int EVP_CIPHER_nid(const EVP_CIPHER *cipher);
int EVP_CIPHER_type(const EVP_CIPHER *ctx);
# define EVP_CIPHER_name(e) OBJ_nid2sn(EVP_CIPHER_nid(e))
int EVP_CIPHER_block_size(const EVP_CIPHER *cipher);
int EVP_CIPHER_key_length(const EVP_CIPHER *cipher);
int EVP_CIPHER_iv_length(const EVP_CIPHER *cipher);
有时我们对使用的加密算法不熟悉,这几个函数很有帮助。
EVP_CIPHER_CTX *EVP_CIPHER_CTX_new(void);
void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *c);
这两个函数用于创建和释放对称加解密上下文对象。
int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *x, int keylen);
当对称算法密钥长度为可变长时,设置对称算法的密钥长度。
成功返回1,失败返回0。
int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *c, int pad);
设置对称算法的填充,对称算法有时候会涉及填充。
pad取值0和1,当pad为1时表示使用填充。默认的填充策略采用PKCS5规范,即最后一个分组被填充n个字节时,其填充值均为n。
成功返回1,失败返回0。
int EVP_EncryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, const unsigned char *key, const unsigned char *iv);
初使化对称加密上下文。
成功返加1,失败返回0。
int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, const unsigned char *in, int inl);
加密一段明文。
成功返加1,失败返回0。成功时,outl输出密文长度。
int EVP_EncryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl);
加密余下的明文。
成功返加1,失败返回0。成功时,outl输出密文长度。
int EVP_DecryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, const unsigned char *key, const unsigned char *iv);
初使化对称解密上下文。
成功返加1,失败返回0。
int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, const unsigned char *in, int inl);
解密一段密文。
成功返加1,失败返回0。成功时,outl输出明文长度。
int EVP_DecryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl);
解密余下的密文。
成功返加1,失败返回0。成功时,outl输出明文长度。
int EVP_BytesToKey(const EVP_CIPHER *type, const EVP_MD *md,
const unsigned char *salt,
const unsigned char *data, int datal, int count,
unsigned char *key, unsigned char *iv);
计算密钥函数,它根据算法类型、摘要算法、salt以及输入数据计算出一个对称密钥和初始化向量iv。返加密钥的长度。
在PEM_do_header()函数中根据口令生成密钥时,有使用到这个函数。
这个结构定义了非对称密钥信息的存储容器。主要字段含义:
type —— 非对称加密算法的NID。
save_type —— 保存的PKEY类型。
pkey —— 保存的PKEY指针,如RSA结构指针。
EVP_PKEY *EVP_PKEY_new(void);
void EVP_PKEY_free(EVP_PKEY *pkey);
这两个函数用于创建和释放PKEY上下文对象。
int EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key);
为PKEY关联指定算法类型的上下文结构,如为RSA关联的宏定义如下:
# define EVP_SignInit(a,b) EVP_DigestInit(a,b)
# define EVP_SignUpdate(a,b,c) EVP_DigestUpdate(a,b,c)
int EVP_SignFinal(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *s,
EVP_PKEY *pkey);
签名计算。从宏定义可以看出实际上就是先计算摘要,再用RSA私钥加密。
成功返加1,失败返回0。
# define EVP_VerifyInit(a,b) EVP_DigestInit(a,b)
# define EVP_VerifyUpdate(a,b,c) EVP_DigestUpdate(a,b,c)
int EVP_VerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sigbuf,
unsigned int siglen, EVP_PKEY *pkey);
验签计算。从宏定义可以看出实际上就是先计算摘要,再用RSA公钥解密签名,再与摘要进行比对。
成功返加1,失败返回0。
下面这个例子演示了使用MD5的两种方法进行摘要计算的过程。
输出:
EVP_DigestInit() ret:[1]
EVP_DigestUpdate() ret:[1]
EVP_DigestFinal() ret:[1]
e380e88e8d09ebf8d8659a15b0ea70b5
EVP_Digest() ret:1
e380e88e8d09ebf8d8659a15b0ea70b5
下面这个例子演示了使用DES进行加解密的过程。为了方便程序实现,破例使用了std::string。
输出:
EVP_EncryptInit() ret:[1]
EVP_EncryptUpdate() ret:[1]
nCipherLen:[24]
EVP_EncryptFinal() ret:[1]
nCipherLen:[8]
cipher size:[32]
EVP_DecryptInit() ret:[1]
EVP_DecryptUpdate() ret:[1]
nTextLen:[24]
EVP_DecryptFinal() ret:[1]
nTextLen:[2]
text size:[26] body:[abcdefghijklmnopqrstuvwxyz]
下面这个例子演示了使用SHA1进行RSA签名和验签计算的过程。
输出:
RSA_generate_key_ex() ret:[1]
EVP_PKEY_assign_RSA() ret:[1]
EVP_SignInit() ret:[1]
EVP_SignUpdate() ret:[1]
EVP_SignFinal() ret:[1]
sha1 len:[64]
EVP_VerifyInit() ret:[1]
EVP_VerifyUpdate() ret:[1]
EVP_VerifyFinal() ret:[1]
这是什么加密的?能解么?
黑客基地下载解密软件
造梦西游3极品号源怎么用
极品号源用法 1先点开始找到控制面板点开 2控制面板里有个文件夹选项打开 3点查看 仔细找 找到有一个隐藏文件和文件夹 下面有两个选项 点显示所有文件和文件夹 4可以关掉文件夹选项了...5去百度上查个 文件修改器 V1.3 (有可能更新了)6下载好后解压 7打开 (有一个红色C的图...
ISK&L这中翻NattuT的歌yl译P&首求Dg文;;tilO
o我v等 一 g所那(s m的e!'e 疯s这t'l d痛血 把dn但alntt到t开什st我oo唯fo e誓rassl我tI运 htfhme mig事以Ien a 'oe etw看i的nr到这 s nutt s我 uii os atuvaldtorda Its,attI我gyit杀taonsit e的的og w延 hcan那yk'能oel d(我- 这手s要m在是ty我 eseto i 就l...
荆范丽科: 使用OpenSSL的EVP接口实现des128加密的逻辑流程如下: // 初始化上下文数据结构,指定算法(EVP_des_ede_cbc)、密钥(key)、初始化向量(initVector) // EVP_CIPHER_CTX_init(&ctx); EVP_EncryptInit_ex(&ctx, EVP_des_ede_cbc...
彭州市18586842212: 如何利用openssl来进行base64编解码 - ?
荆范丽科: openssl的用法, 请见之前博文, 下面仅仅给出base64编解码的代码:#include <iostream> #include <openssl/evp.h> #pragma comment(lib, "libeay32.lib") #pragma comment(lib, "ssleay32.lib") // 可以注释掉 using namespace std; // base64...
彭州市18586842212: 如何调用openssl 的加解密算法 进行base64 aes - 128 - ?
荆范丽科: 提供个加密函数代码:#define MAX_ENCRYPT_LEN 1024 void MyEncrypt(const unsigned char *sMsg, int cbMsg, unsigned char *sEncryptMsg, int &cbEncryptMsg) { OpenSSL_add_all_algorithms(); //产生会话密钥 unsigned char ...
彭州市18586842212: 如何使用Openssl 私钥进行解密 - ?
荆范丽科: 在ubuntu上要使用openssl的话需要先进行安装,命令如下: sudo apt-get install openssl 安装完成就可以使用openssl了. 首先需要进入openssl的交互界面,在命令行了输入openssl即可; 1)生成RSA私钥: genrsa -out rsa_private_key.pem ...
彭州市18586842212: java 调用evp接口实例?
荆范丽科: 没有这个 类型.你可以根据这个类型的规则自己封装.
彭州市18586842212: openssl aes - 256 - cbc加解密的问题 - ?
荆范丽科: 因为加密会分组,分组长度取决于你的密钥长度,不足部分就会填充.所以加密后的字符串会大于等于加密前长度. 反过来解密字符串就会小于等于解密前字符串长度.
彭州市18586842212: 想用C去实现 openssl里的 EVP - BytesToKey - ?
荆范丽科: 使用VS2005下的Visual Studio 2005 Command Prompt进入控制台模式(这个模式会自动设置各种环境变量) 、解压缩openssl的包,进入openssl的目录 、perl configure VC-WIN32 尽量在这个目录下执行该命令,否则找不到Configure文件,...
彭州市18586842212: 如何使用OpenSSL工具生成根证书与应用证书 - ?
荆范丽科: 使用OpenSSL工具生成根证书与应用证书方法: 1、生成顶级CA的公钥证书和私钥文件,有效期10年(RSA 1024bits,默认) openssl req -new -x509 -days 3650 -keyout CARoot1024.key -out CARoot1024.crt 2、 为顶级CA的私钥文件去除保...
彭州市18586842212: 如何使用OpenSSL创建证书 - ?
荆范丽科: 如果你想创建不是1年有效期的自签名证书,或想提供有关自己的额外信息,你可以用一个工具Open SSL来创建证书,而不是SDK随带的标准工具:MakeKeys.下面的命令,基于这里给出的建议,演示了如何创建具有10年有效期的自签名key...
彭州市18586842212: android 怎么使用自己编译的openssl - ?
荆范丽科: 自己结一下帖.是ndk api 8以下不支持libdl中某些特性的原因,添加 Application.mk APP_PLATFORM := android-8 再次编译成功