2021SC@SDUSC
21 EVP
21.1 EVP 简介
Openssl EVP(high-level cryptographic functions[1])提供了丰富的密码学中的各种函数。Openssl 中实现了各种对称算法、摘要算法以及签名/验签算法。EVP 函数将这些具体的算 法进行了封装。
EVP 主要封装了如下功能函数:
1)实现了 base64 编解码 BIO;
2)实现了加解密 BIO;
3)实现了摘要 BIO;
4)实现了 reliable BIO;
5)封装了摘要算法;
6)封装了对称加解密算法;
7)封装了非对称密钥的加密(公钥)、解密(私钥)、签名与验证以及辅助函数;
7)基于口令的加密(PBE);
8)对称密钥处理;
9)数字信封:数字信封用对方的公钥加密对称密钥,数据则用此对称密钥加密。 发送给对方时,同时发送对称密钥密文和数据密文。接收方首先用自己的私钥解密密钥 密文,得到对称密钥,然后用它解密数据。
10)其他辅助函数。
21.2 数据结构
EVP 数据结构定义在 crypto/evp.h 中
EVP_PKEY
该结构用来存放非对称密钥信息,可以是 RSA、DSA、DH 或 ECC 密钥。其中,ptr 用来存放密钥结构地址,attributes 堆栈用来存放密钥属性
/*
openssl-1.1.1/crypto/include/internal/evp_int.h:395
*/
/*
* Type needs to be a bit field Sub-type needs to be for variations on the
* method, as in, can it do arbitrary encryption....
*/
struct evp_pkey_st {
int type;
int save_type;
CRYPTO_REF_COUNT references;
const EVP_PKEY_ASN1_METHOD *ameth;
ENGINE *engine;
ENGINE *pmeth_engine; /* If not NULL public key ENGINE to use */
union {
void *ptr;
# ifndef OPENSSL_NO_RSA
struct rsa_st *rsa; /* RSA */
# endif
# ifndef OPENSSL_NO_DSA
struct dsa_st *dsa; /* DSA */
# endif
# ifndef OPENSSL_NO_DH
struct dh_st *dh; /* DH */
# endif
# ifndef OPENSSL_NO_EC
struct ec_key_st *ec; /* ECC */
ECX_KEY *ecx; /* X25519, X448, Ed25519, Ed448 */
# endif
} pkey;
int save_parameters;
STACK_OF(X509_ATTRIBUTE) *attributes; /* [ 0 ] */
CRYPTO_RWLOCK *lock;
} /* EVP_PKEY */ ;
/*
openssl-1.1.1/include/openssl/ossl_typ.h:93
*/
typedef struct evp_pkey_st EVP_PKEY;
EVP_MD
该结构用来存放摘要算法信息、非对称算法类型以及各种计算函数。主要各项意义如 下:
type: 摘要类型,一般是摘要算法 NID;
pkey_type: 公钥类型,一般是签名算法 NID;
md_size: 摘要值大小,为字节数;
flags: 用于设置标记;
init: 摘要算法初始化函数;
update: 多次摘要函数;
final: 摘要完结函数;
copy: 摘要上下文结构复制函数;
cleanup: 清除摘要上下文函数;
sign: 签名函数,其中 key 为非对称密钥结构地址;
verify: 摘要函数,其中 key 为非对称密钥结构地址。
openssl 对于各种摘要算法实现了上述结构,各个源码位于 cypto/evp 目录下,文件名 以 m_开头。Openssl 通过这些结构来封装了各个摘要相关的运算
/*
openssl-1.1.1/crypto/include/internal/evp_int.h:115
*/
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