EVP

DNA图谱 / 问答 / 标签

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]

今天七月半。EVP。世界上真的有灵魂存在吗?

当然有了,有人见到不如有人证实,更有说服力中外不少纪录片都证实了鬼魂的存在推荐你去看这几片子《灵媒辑凶 》《鬼影森森》《克格勃超常现象研究档案》中有拍到鬼《灵魂之谜》《借尸还魂,真人真事》连中国教育台的都放此类片了,例如人文发现节目就放过《怪兽档案,恶灵惊魂》我最推荐你看的视频是国内的纪实片《大悲古寺》《 附体》《 因果报应实录》等相关视频,这个是最真实的,内容没有加工的片子,里面的人物真人真事,有据可查。我说的这些片子都是在网上很容易搜索到在线视频还有,我建议你去纪录影视类论坛转转,比如纪录片之家这样的论坛,能找到此类纪录片那些纪录片迷,知识丰富,眼界开阔,此类片子看得多,也相信鬼魂存在的,他们也可以给你推荐此类片子