OpenSSL EVP编程介绍
What
EVP 接口(Envelope Public Key Cryptography,信封公钥密码学)是 OpenSSL 提供的一套统一的高层密码学 API,它封装了底层的对称加密、非对称加密、哈希、签名验签等所有核心操作,旨在让开发者无需关注底层算法细节,就能安全、高效地实现密码学功能。
How to use
EVP接口的设计架构围绕着Context对象展开。无论何种操作(加密、解密、签名、验签),都要先创建Context对象,然后将操作中使用到的信息(公钥、IV等)都设置到Context对象中,然后使用该Context进行操作。
下面以RSA加密、解密为例进行说明:
- 获取密钥对象pkey,有多种方式如
d2i_PUBKEY(nullptr, &p, public_key.size());
,该接口可以直接解析DER格式的公钥 - 创建Context对象,通过`EVP_PKEY_CTX_new(pkey, nullptr);``。
- 初始化Context对象,通过
EVP_PKEY_decrypt_init(ctx);
- 设置Padding类型,通过
EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING);
- 加密获取密文长度,通过
EVP_PKEY_encrypt(ctx, NULL, &outlen, plaintext.data(), plaintext.size())
- 加密获取密文,通过
EVP_PKEY_encrypt(ctx, ciphertext.data(), &outlen, plaintext.data(), plaintext.size())
- 释放密钥对象,通过
EVP_PKEY_free(pkey);
- 释放Context对象,通过
EVP_PKEY_free(pkey);
Tips
不同类型的Context对象
不同的操作对应不同的Context对象,对应的EVP接口前缀也不一样。
- 非对称加密(RSA、SM2等)的Context类型,EVP_PKEY_CTX。
- 对称加密(AES、SM4等)的Context类型,EVP_CIPHER_CTX。
- 摘要计算(MD5、SM3、SHA等)的Context类型,EVP_MD_CTX。
关于SM2withSM3
对于SM2withSM3,使用EVP_MD_CTX类型的Context
- 初始化Context:
EVP_MD_CTX_new()
; - 初始化Context:
EVP_DigestSignInit(mctx, nullptr, EVP_sm3(), nullptr, pkey)
- 更新签名数据:
EVP_DigestSignUpdate(mctx, plaintext.data(), plaintext.size())
- 结束签名:
EVP_DigestSignFinal(mctx, signature.data(), &sig_len)
关于AES的Block大小
AES的block大小跟密钥长度无关固定为16字节