21.openssl编程——EVP

21.1 EVP简介
Openssl EVP (high-level cryptographic functions)提供丰富的密码学中的各种函数。
EVP主要封装如下功能函数:
a.实现了base64编解码BIO
b.实现了加解密BIO
c.实现了摘要BIO
d.实现了reliableBIO;
e.封装了摘要算法
f.封装了对称加解密算法
g.封装了非对称密钥的加密(公钥)、解密(私钥)、签名与验证以及辅助函数
h.基于口令的加密(PBE)
i.数字信封:数字信封用对方的公钥加密对称加密,数据则用此对称密钥加密。发哦是哪个给对方时,同时发送对称密钥密文和数据密文。接收方首先用自己的私钥解密密钥密文,得到对称密钥,然后用他解密数据。
j.其他辅助函数
21.2 数据结构
struct evp_pkey_st {
int type;
int save_type;
CRYPTO_REF_COUNT references;
const EVP_PKEY_ASN1_METHOD *ameth;
ENGINE *engine;
ENGINE *pmeth_engine;
union {
#ifndef OPENSSL_NO_RSA
struct rsa_st *rsa;
#endif
struct dsa_st *dsa;
#ifndef OPENSSL_NO_DSA
struct dh_st *dh;
#endif
#ifndef OPENSSL_NO_EC
struct ec_key_st *ec;
#endif
} pkey;
}
EVP_MD
struct evp_md_st {
int type;
int pkey_type;
int md_size;
unsigned long flags;
int (*init) (EVP_MD_CTX *ctx);
int (*update) (EVP_MD_CTX *ctx, const void *data, size_t count);
int (*final) (EVP_MD_CTX *ctx, unsigned char *md);
int (*copy) (EVP_MD_CTX *to, const EVP_MD_CTX *from);
int (*cleanup) (EVP_MD_CTX *ctx);
int block_size;
int ctx_size;
int (*md_ctrl) (EVP_MD_CTX *ctx, int cmd, int p1, vpid *p2);
}
type:摘要类型,一般是摘要算算NID;
pkey_type:公钥类型,一般是签名算法NID;
md_size:摘要值大小,为字节数
flags:用于设置标记
init:摘要算法初始化函数
update:多次摘要函数
final:摘要完结函数
copy:摘要上下文结构复制函数
cleanup:清除摘要上下文函数
sign:签名函数,其中Key为非对称密钥结构地址。
erify:摘要函数,其中key为非对称结构地址。
21.2.3EVP_CIPHER
struct evp_cipher_st {
int nid;
int block_size;
int key_len;
int iv_len;
unsigned long flags;
int (*init) (EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc);
int (*do_cipher) (EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl);
int (*cleanup) (EVP_CIPHER_CTX *);
int ctx_size;
int (*set_asn1_parameters) (EVP_CIPHER_CTX *, ASN1_TYPE *);
int (*get_asn1_parameters) (EVP_CIPHER_CTX *, ASN1_TYPE *);
int (*ctrl) (EVP_CIPHER_CTX *, int type, int arg, void *ptr);
void *app_data;
}
mid:对称算法nid;
block_size:对称算法每次加解密的字节数
key_len:对称算法的密钥长度字节数
iv_len:对称算法的填充长度
flags:用于标记
init:加密初始化函数,用来初始化ctx,key为对称密钥值,iv为初始化向量,enc用于指明要加密还是解密
do_cipher:对称运算函数,用于加密或解密
cleanup:清楚上下文函数
set_asn1_parameters:设置上下文参数函数
set_asn1_parameters:获取上下文参数函数
ctl:控制函数
app_data:用于存放应用数据
21.2.4EVP_CIPHER_CTX
struct evp_cipher_ctx_st {
const EVP_CIPHER *cipher;
ENGINE *engine;
int encrypt;
int buf_lenb;
unsigned char oiv[EVP_MAX_IV_LENGTH];
unsigned char iv[EVP_MAX_IV_LENGTH];
unsigned char buf[EVP_MAX_BLOCK_LENGTH];
int num;
void *app_data;
int key_len;
unsgined long flags;
void *cipher_datra;
int final_used;
int block_mask;
unsigned char final[EVP_MAX_BLOCK_LENGTH]
}
cipher:指明对称算法
engine:硬件引擎
encrypt:是加密还是解密,非0位加密,0位解密
buf和buf_len:指明还有多少数据为进行运算
oiv:原始初始化向量
iv:当前的初始化向量
final:存放最终结果,一般与final函数对应
21.3 源码结构
evp源码位于crypty/evp目录
a.全局函数
主要c_allc.c、c_alldc | c_all.c以及names.c。他们加载openssl支持所有的对称算法和摘要算法,放入到哈希表中。实现OpenSSL_add_digests | OpenSSL_add_all_cipher以及Openssl_add_all_algorithms(调用了前两个函数)函数。用户也可以单独加再只要函数(EVP_add_digetst)和对称计算函数(EVP_add_cipher)
b.BIO扩充
包括bio_b64.c | bio_enc.c | bio_md.c和bio_ok.c,各自实现了BIO_METHOD方法,分别用于base64编解码、对称加解密以及摘要。
c.摘要算法EVP封装
由digest.c实现,实现过程中调用了对应摘要算法的回调函数。各个摘要算法提供了自己的EVP_MD静态结构,对应源码为m_xxx.c
d.对称算法EVP封装
由evp_en.c实现,实现过程调用了具体对称算法函数,实现了Update操作。各种对称算法都提供了一个EVP_CIPHER静态结构,对应源码为e_xxx.c。
一般用户至少需要实现如下功能:
*构造一个新的静态的VP_CIPHER结构
*实现EVP_CIPHER结构中的init函数,该函数用于设置iv,设置加解密标记、以及根据外密钥生成自己的内部密钥
*实现do_cipher函数,该函数仅对block_size字节的数据进行对称运算
*实现cleanup函数,该函数主要用于清除内存中的密钥信息。
e.非对称算法EVP封装
主要以p_开头文件。其中,
p_enc.c封装了公钥加密;
p_dec.封装了私钥解密;
p_lib.c实现一些辅助函数
p_sign.c封装了签名函数
p_verify.c封装了验签函数
p_seal.c封装了数字信封;
p_open.c封装了解数字信封
f.基于口令的加密
包括p5_crpt2.c p5_crpt.c和evp_phe.c
21.4 摘要函数
典型的摘要函数主要有
1) EVP_md5
2) EVP_sha1
3) EVP_sha256
4) EVP_DigestInit
摘要初始化函数,需要有EVP_MD作为输入参数
5) EVP_DigsetUpdate和EVP_DigesInit_ex
摘要Update函数,用于进行多次摘要
6) EVP_DigestFinal和EVP_DIgestFinal_ex
摘要Final函数,用户得到最终结果
7) EVP_Digest
对一个数据进行摘要,他一次调用了上述三个函数
21.5 对称加解密函数
典型的加解密函数主要有:
a EVP_CIPHER_CTX_inti
初始化对称计算上下文
b.EVP_CIPHER_CTX_cleanup;
清楚对称算法上下文数据,他调用用户提供的销毁函数清楚存在的内部密钥数据
c EVP_des_ede3_ecb
返回一个EVP_CIPHER
d EVP_EncryptInit和EVP_EncryptInit_ex
加密初始化函数,本函数调用具体算法的init回调函数,将外送密钥key转换为内部密钥形式,将初始化向量iv拷贝到ctx结构中
e EVP_EncryptUpdate
获取加密结构,函数可能涉及填充,他调用了具体算法的do_cipher回调函数
f EVP_EncryptFinal和EVP_EncryptFinal_ex
解密初始化函数
g EVP_DecryptFinal和EVP_DecryptInit_ex
解密初始化函数
h EVP_DecrytUpdate
解密函数,用于多次计算,他调用了具体算法的do_cipher回调函数
i EVP_DecryptFinal和EVP_DecryptFinal_ex
获取解密结果,函数可能涉及去填充,他调用具体算法的do——cipher回调函数
j EVP_BytesToKey
计算密钥函数,他根据算法类型、摘要算法\satl以及输入数据计算出一个对称密钥和初始化响铃iv
k. PKCS5_PB3_keyivgen和PKCS5_v2_PBE_keyivgen
实现了PKCS5基于口令生成密钥 和初始化向量的算法
l. PKCS5_PBE_add
加载所有openssl实现的基于口令生成密钥的算法
m. EVP_PBE_alg_add
添加一个PBE算法
21.5 对称加解密函数
典型的加解密函数
a. EVP_CIPHER_CTX_init
初始化对称计算上下文
b. EVP_CIPHER_CTX_cleanup
清除对称算法上下文数据,他调用用户提供的销毁函数清除存中的内部密钥以及其他数据
c. EVP_des_ede3_ecb
返回一个EVP_CIPHER;
d.EVP_EncryptInit和EVP_EncryptInit_ex
加密初始化函数,本函数调用具体算法的init回调函数,将外送密钥key转换为内部密钥形式,将初始化向量iv拷贝到ctx结构中
e. EVP_EncryptUpdate
加密函数,用于对此计算,他调用了具体算法的do_cipher回调函数
f. EVP_EncryptFinal和EVP_EncryptFinal_ex
获取加密结果,函数可能涉及填充,他叼调用了具体算法的do_cipher会带哦函数
h. EVP_DecryptInit和EVP_DecryptInit_ex
解密初始化函数
i.EVP_DecryptUpdate
解密函数,用于多次计算,他调用了具体算法的do_cipher回调函数
j.EVP_DecryptFinal和EVP_DecryptFinal_ex
获取解密结果,函数可能涉及去填充,他调用了具体算法的do_cipher回调函数
k.EVP_BytesToKey
计算密钥函数、他根据算法类型、摘要算法、salt以及输入数据计算出一个对称密钥和初始化向量iv
l. PKCS5_PBE_keyivgen和PKCS5_v2_PBE_keyivgen
实现了PKCS5基于口令生成密钥和初始化向量的算法
m. PKCS5_PBE_add
加载所有openssl实现的基于口令生成密钥的算法
n. EVP_PBE_alg_add
添加一个PBE算法
21.6 非对称函数
典型的非对称函数有:
a.EVP_PKEY_encrypt
公钥加密
b.EVP_PEKY_decrypt
私钥解密
c.EVP_PKEY_assign
设置EVP_PKEY中具体的密钥结构,使他代表密钥
d.EVP_PKEY_assign_RSA/EVP_PKEY_set1_RSA
设置EVP_PKEY中的RSA密钥结构,使他代表该RSA密钥
e.EVP_PKEY_get1_RSA
获取EVP_PKEY的RSA密钥结构
f.EVP_SignFinal
签名操作,输入参数必须有私钥(EVP_PKEY)
g. EVP_VerifyFinal
验证签名,输入参数必须有公钥(EVP_PKEY)
h.int EVP_OpenInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, const unsgined char *ek, int ekl, const unsigned char *iv, EVP_PKEY *priv)
解数字信封初始化操作,type为对称加密算法,ek密钥密文,ek1为密钥密文长度,iv为填充值,priv为用户私钥
i.EVP_OpenUpdate
做解密运算
j.EVP_OpenFinal
做解密运算,解开数字信封
k. int EVP_SealInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, unsgined char **ek, int *ekl, unsgined char *iv, EVP_PKEY **pubk, int npubk)
type为对称算法,ek数组用来存放对多个公钥对称加密结果,ek1用于存放ek1数组中每个密钥密的长度,iv为填充值,pubk数组用来存放多个公钥,npubk为公钥个数,本函数用多个公钥分贝加密密钥,并做加密初始化。
l.EVP_SealUpdate
做加密运算
m.EVP_SealFinal
做加密元算,制作数字信封。
21.7 BASE64编解码函数
a.EVP_EncodeInit
BASE64编码初始化
b.EVP_EncodeUpdate
BASE64编码,可多次调用
c.EVP_EncodeFinal
BASE64编码,并获取最终结果
d.EVP_DecodeInit
BASE64解码初始化
e.EVP_DecodeUpdate
输入数据长度不能大于80字节。
f.EVP_DecodeFinal
BASE64解码,并获取最终结果
g.EVP_EncodeBlock
BASE64编码函数,本函数可单独调用
h.EVP_DecocdeBlock
BASE64解码,本函数可单独调用,对输入数据长度无要求。
21.8 对其他函数
a.EVP_add_cipher
将对称算法加入到全局变量,以供调用。
b.EVP_ add_digest
将摘要算法加入到全局变量中,以供调用
c.EVP_CIPHER_CTX_ctrl
对称算法控制函数,他调用了用户实现的ctrl回调函数
d.EVP_CIPHER_CTX_set_key_length
当对称算法密钥长度为可变长时,设置对称算法的密钥长度
e.EVP_CIPHER_CTX_set_padding
设置对称算法的填充,对称算法有时候会涉及填充。加密分组长度大于一时,用户输入数据不是加密分组的整数倍是,会涉及到填充。填充在最后一个分组来完成,openssl分组填充时,如果有n个填充,则将最后一个分组用n来填满。
f. EVP_CIPHER_get_asn1_iv
获取原始iv,存放ASN1_TYPE结构中
g.EVP_CIPHER_param_to_asn1
设置对称算法参数,参数存放ASN1_TYPE类型中,他调用用户实现的回调函数set_asn1_parameters实现的
h.EVP_CIPHER_type
获取对称算法的类型
i.EVP_CipherInit/EVP_CipherInit_ex
对称算法计算(加解密)初始化函数,_ex函数多了硬件enginge参数,EVP_EncryptInitEVP_DecryptInit函数也调用本函数
j.EVP_CipherUpdate
对称计算(加/解密)函数,他调用了EVP_EncryptUpdate和EVP_DecryptUppdate函数
k.EVP_CipherFinal/EVP_CipherFinal_ex
对称就按(加/解)函数,调用了EVP_EncryptFianl和EVP_DecryptFianl;本函数主要用来处理最后加密分组,可能会有对称计算
l.EVP_cleanup
清除加载的各种算法,包括对称算法、摘要算法以及PBE算法,并清除这些算法相关的哈希表的内容
m.EVP_get_cipherbyname
根据字符串名字来获取一种对称算法(EVP_CIPHER),本函数查询对称算法哈希表的内容
n.EVP_get_cipherbyname
根据字符串各自来获取一种对称算法(EVP_CIPHER),本函数查询对算算法哈希表
o.EVP_get_digetbyname
根据字符串获取摘要算法(EVP_MID),本函数查询摘要算法哈希表
p.EVP_get_pw_prompt
获取口令提示信息字符串
q.int EVP_PBE_CipherInit(ASN1_OBJECT *pbe_obj, const char *pass, int passlen, ASN1_TYPE *param, EVP_CIPHER_CTX *ctx, int en_de)
PBE初始化函数。本函数用口令生成对称算法的密钥和初始化向量,并作加解密初始化操作。
r.EVP_PBE_cleanup
删除所有的PBE信息,释放全局堆栈中的信息
s.EVP_PKEY *EVP_PKCS82PKEY(PKCS8_PRIV_KEY_INFO *p8)
将PKCS8_PRIV_KEY_INFO(x509.h中定义)中保存的私钥转换为EVP_PKEY结构
t.EVP_PKEY2PKC28/EVP_PKEY2PKCS8_broken
将EVP_PKEY结构中的私钥转换为PKCS8_PRIV_KEY_INFO数据结构存储
v.EVP_PKEY_bits
非对称密钥大小,为比特数
w. EVP_PKEY_cmp_parameters
比较非对称密钥的密钥参数,用于DSA和ECC密钥。
x.EVP_PKEY_copy_parameters
拷贝非对称密钥的密钥参数,用于DSA和ECC密钥
y. EVP_PKEY_free
释放非对称密钥数据结构
z. EVP_PKEY_get1_DH/EVP_PKEY_set1_DH
获取/设置EVP_get1_DSA/EVP_PKEY_set1_DSA
a1.EVP_PKEY_get1_RSA/EVP_PEKY_set1_RSA
获取/设置EVP_PKEY中结构中的RSA结构密钥
b1.EVP_PKEY_missing_parameters
检查费对称密钥参数是否齐全,用于DSA和ECC密钥
c1.EVP_PLEY_new
生成一个EVP_PKEY结构
d1.EVP_PKEY_size
获取非对称密钥的自己大小
e1.EVP_PKEY_type
获取EVP_PKEY中表示非对称密钥的类型
f1.int EVP_readpw_string(char *buf, int length, const char *prompt, int verify)
获取用户输入的口令;buf用来存放用户输入的口令,length为buf长度,prompt为提示给用户的信息,如果为空,他采用内置的提示信息,verify为0时,不要求验证用户输入口令,否则会要求用户输入两遍。返回0表示成功。
g1.EVP_set_pw_prompt
设置内置的提示信息,用于需要用户输入口令的场合。
21.9 对称加密过程
对称加密过程中
a.EVP_EncryptInit
设置buf_len为0,表明临时缓冲区buf没有数据
b. EVP_EncryptUpdate
ctx结构中的buf缓冲区用于存放上次EVP_EncryptUpdate遗留下来的为加密的指明其长度。如果buf_len为0,加密的时候先加密输入数据的整数倍,将余下的数据放入缓冲区。如果buf_len为0,加密的时候先加密输入数据的一部分(凑足一个分组的长度),然后用上面的方法加密,输出结果是加密过程的数据
c. EVP_EncryptFinal
加密ctx的buf中余下数据,如果长度不够一个分组(分组长度不为1),则填充,然后在加密,输出结果
posted @ 2018-01-23 21:37  艾小小雨  阅读(1753)  评论(0编辑  收藏  举报