OpenSSL中的EVP接口

摘要算法(Digest)

EVP_MD结构保存了摘要算法的实现,相同的API,使用不同的EVP_MD,就可以实现不同的摘要算法。

获取EVP_MD

直接根据算法获取:

        #include <openssl/evp.h>

        const EVP_MD *EVP_md2(void);
        const EVP_MD *EVP_md4(void);
        const EVP_MD *EVP_md5(void);
        const EVP_MD *EVP_md5_sha1(void);
        const EVP_MD *EVP_mdc2(void);
        const EVP_MD *EVP_ripemd160(void);
        const EVP_MD *EVP_sha1(void);
        const EVP_MD *EVP_sha224(void);
        const EVP_MD *EVP_sha256(void);
        const EVP_MD *EVP_sha512_224(void);
        const EVP_MD *EVP_sha512_256(void);
        const EVP_MD *EVP_sha384(void);
        const EVP_MD *EVP_sha512(void);
        const EVP_MD *EVP_sha3_224(void);
        const EVP_MD *EVP_sha3_256(void);
        const EVP_MD *EVP_sha3_384(void);
        const EVP_MD *EVP_sha3_512(void);
        const EVP_MD *EVP_shake128(void);
        const EVP_MD *EVP_shake256(void);
        const EVP_MD *EVP_sm3(void);
        const EVP_MD *EVP_whirlpool(void);

根据名字查找:

        EVP_MD *EVP_MD_fetch(OSSL_LIB_CTX *ctx, const char *algorithm,
                             const char *properties);
        int EVP_MD_up_ref(EVP_MD *md);
        void EVP_MD_free(EVP_MD *md);
        
        const EVP_MD *EVP_get_digestbyname(const char *name);
        const EVP_MD *EVP_get_digestbynid(int type);
        const EVP_MD *EVP_get_digestbyobj(const ASN1_OBJECT *o);

OpenSSL3.0之前的版本使用EVP_get_digestbyname,OpenSSL3.0使用EVP_MD_fetch。

获取摘要长度和数据块长度(字节)

int EVP_MD_get_size(const EVP_MD *md);
#define EVP_MD_size EVP_MD_get_size
int EVP_MD_CTX_get_size(const EVP_MD_CTX *ctx);
#define EVP_MD_CTX_size EVP_MD_CTX_get_size

int EVP_MD_get_block_size(const EVP_MD *md);
#define EVP_MD_block_size EVP_MD_get_block_size
int EVP_MD_CTX_get_block_size(const EVP_MD_CTX *ctx);
#define EVP_MD_CTX_block_size EVP_MD_CTX_get_block_size

通常block size对Digest算法没什么意义。

Digest API

        EVP_MD_CTX *EVP_MD_CTX_new(void);
        int EVP_MD_CTX_reset(EVP_MD_CTX *ctx);
        void EVP_MD_CTX_free(EVP_MD_CTX *ctx);

        int EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type);
        int EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *d, size_t cnt);
        int EVP_DigestFinal(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *s);

例子

        #include <stdio.h>
        #include <string.h>
        #include <openssl/evp.h>

        int main(int argc, char *argv[])
        {
            EVP_MD_CTX *mdctx;
            const EVP_MD *md;
            char mess1[] = "Test Message\n";
            char mess2[] = "Hello World\n";
            unsigned char md_value[EVP_MAX_MD_SIZE];
            unsigned int md_len, i;

            if (argv[1] == NULL) {
                printf("Usage: mdtest digestname\n");
                exit(1);
            }

            md = EVP_get_digestbyname(argv[1]);
            if (md == NULL) {
                printf("Unknown message digest %s\n", argv[1]);
                exit(1);
            }

            mdctx = EVP_MD_CTX_new();
            EVP_DigestInit_ex2(mdctx, md, NULL);
            EVP_DigestUpdate(mdctx, mess1, strlen(mess1));
            EVP_DigestUpdate(mdctx, mess2, strlen(mess2));
            EVP_DigestFinal_ex(mdctx, md_value, &md_len);
            EVP_MD_CTX_free(mdctx);

            printf("Digest is: ");
            for (i = 0; i < md_len; i++)
                printf("%02x", md_value[i]);
            printf("\n");

            exit(0);
        }

对称加密(Cipher)

EVP_CIPHER结构保存了加密算法的实现,相同的API,使用不同的EVP_CIPHER,就可以实现不同的加密算法。

获取EVP_CIPHER

直接根据算法获取:

        #include <openssl/evp.h>

        const EVP_CIPHER *EVP_enc_null(void);
        const EVP_CIPHER *EVP_ciphername(void)
   EVP_ciphername is used a placeholder for any of the described cipher functions, such as EVP_des_cbc.

   EVP_des_cbc, EVP_des_cfb, EVP_des_cfb1, EVP_des_cfb8, EVP_des_cfb64, EVP_des_ecb, EVP_des_ofb, EVP_des_ede, EVP_des_ede_cbc,
   EVP_des_ede_cfb, EVP_des_ede_cfb64, EVP_des_ede_ecb, EVP_des_ede_ofb, EVP_des_ede3, EVP_des_ede3_cbc, EVP_des_ede3_cfb,
   EVP_des_ede3_cfb1, EVP_des_ede3_cfb8, EVP_des_ede3_cfb64, EVP_des_ede3_ecb, EVP_des_ede3_ofb, EVP_des_ede3_wrap - EVP DES cipher
   
   EVP_desx_cbc - EVP DES-X cipher

   EVP_aes_128_cbc, EVP_aes_192_cbc, EVP_aes_256_cbc, EVP_aes_128_cfb, EVP_aes_192_cfb, EVP_aes_256_cfb, EVP_aes_128_cfb1,
   EVP_aes_192_cfb1, EVP_aes_256_cfb1, EVP_aes_128_cfb8, EVP_aes_192_cfb8, EVP_aes_256_cfb8, EVP_aes_128_ctr, EVP_aes_192_ctr,
   EVP_aes_256_ctr, EVP_aes_128_ecb, EVP_aes_192_ecb, EVP_aes_256_ecb, EVP_aes_128_ofb, EVP_aes_192_ofb, EVP_aes_256_ofb,
   EVP_aes_128_cbc_hmac_sha1, EVP_aes_256_cbc_hmac_sha1, EVP_aes_128_cbc_hmac_sha256, EVP_aes_256_cbc_hmac_sha256, EVP_aes_128_ccm,
   EVP_aes_192_ccm, EVP_aes_256_ccm, EVP_aes_128_gcm, EVP_aes_192_gcm, EVP_aes_256_gcm, EVP_aes_128_ocb, EVP_aes_192_ocb,
   EVP_aes_256_ocb, EVP_aes_128_wrap, EVP_aes_192_wrap, EVP_aes_256_wrap, EVP_aes_128_wrap_pad, EVP_aes_192_wrap_pad,
   EVP_aes_256_wrap_pad, EVP_aes_128_xts, EVP_aes_256_xts - EVP AES cipher

   EVP_aria_128_cbc, EVP_aria_192_cbc, EVP_aria_256_cbc, EVP_aria_128_cfb, EVP_aria_192_cfb, EVP_aria_256_cfb, EVP_aria_128_cfb1,
   EVP_aria_192_cfb1, EVP_aria_256_cfb1, EVP_aria_128_cfb8, EVP_aria_192_cfb8, EVP_aria_256_cfb8, EVP_aria_128_ctr, EVP_aria_192_ctr,
   EVP_aria_256_ctr, EVP_aria_128_ecb, EVP_aria_192_ecb, EVP_aria_256_ecb, EVP_aria_128_ofb, EVP_aria_192_ofb, EVP_aria_256_ofb,
   EVP_aria_128_ccm, EVP_aria_192_ccm, EVP_aria_256_ccm, EVP_aria_128_gcm, EVP_aria_192_gcm, EVP_aria_256_gcm

   EVP_bf_cbc, EVP_bf_cfb, EVP_bf_cfb64, EVP_bf_ecb, EVP_bf_ofb - EVP Blowfish cipher

   EVP_blake2b512, EVP_blake2s256 - BLAKE2 For EVP

   EVP_camellia_128_cbc, EVP_camellia_192_cbc, EVP_camellia_256_cbc, EVP_camellia_128_cfb, EVP_camellia_192_cfb, EVP_camellia_256_cfb,
   EVP_camellia_128_cfb1, EVP_camellia_192_cfb1, EVP_camellia_256_cfb1, EVP_camellia_128_cfb8, EVP_camellia_192_cfb8,
   EVP_camellia_256_cfb8, EVP_camellia_128_ctr, EVP_camellia_192_ctr, EVP_camellia_256_ctr, EVP_camellia_128_ecb, EVP_camellia_192_ecb,
   EVP_camellia_256_ecb, EVP_camellia_128_ofb, EVP_camellia_192_ofb, EVP_camellia_256_ofb - EVP Camellia cipher

   EVP_cast5_cbc, EVP_cast5_cfb, EVP_cast5_cfb64, EVP_cast5_ecb, EVP_cast5_ofb - EVP CAST cipher

   EVP_chacha20, EVP_chacha20_poly1305 - EVP ChaCha20 stream cipher

   EVP_idea_cbc, EVP_idea_cfb, EVP_idea_cfb64, EVP_idea_ecb, EVP_idea_ofb - EVP IDEA cipher

   EVP_rc2_cbc, EVP_rc2_cfb, EVP_rc2_cfb64, EVP_rc2_ecb, EVP_rc2_ofb, EVP_rc2_40_cbc, EVP_rc2_64_cbc - EVP RC2 cipher

   EVP_rc4, EVP_rc4_40, EVP_rc4_hmac_md5 - EVP RC4 stream cipher

   EVP_rc5_32_12_16_cbc, EVP_rc5_32_12_16_cfb, EVP_rc5_32_12_16_cfb64, EVP_rc5_32_12_16_ecb, EVP_rc5_32_12_16_ofb - EVP RC5 cipher

   EVP_seed_cbc, EVP_seed_cfb, EVP_seed_cfb128, EVP_seed_ecb, EVP_seed_ofb - EVP SEED cipher

   EVP_sm4_cbc, EVP_sm4_ecb, EVP_sm4_cfb, EVP_sm4_cfb128, EVP_sm4_ofb, EVP_sm4_ctr - EVP SM4 cipher

根据名字查找:

        EVP_CIPHER *EVP_CIPHER_fetch(OSSL_LIB_CTX *ctx, const char *algorithm,
                                     const char *properties);
        int EVP_CIPHER_up_ref(EVP_CIPHER *cipher);
        void EVP_CIPHER_free(EVP_CIPHER *cipher);
        
        const EVP_CIPHER *EVP_get_cipherbyname(const char *name);
        const EVP_CIPHER *EVP_get_cipherbynid(int nid);
        const EVP_CIPHER *EVP_get_cipherbyobj(const ASN1_OBJECT *a);

OpenSSL3.0之前的版本使用EVP_get_digestbyname,OpenSSL3.0使用EVP_MD_fetch。

Cipher API

上下文管理

        EVP_CIPHER_CTX *EVP_CIPHER_CTX_new(void);
        int EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *ctx);
        void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *ctx);

Encrypt API

        int EVP_EncryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type,
                            const unsigned char *key, const unsigned char *iv);
        int EVP_EncryptInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type,
                               ENGINE *impl, const unsigned char *key, const unsigned char *iv);
        int EVP_EncryptInit_ex2(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type,
                                const unsigned char *key, const unsigned char *iv,
                                const OSSL_PARAM params[]);
                                
        int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out,
                              int *outl, const unsigned char *in, int inl);
                              
        int EVP_EncryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl);
       int EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl);

Decrypt API

        int EVP_DecryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type,
                            const unsigned char *key, const unsigned char *iv);
        int EVP_DecryptInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type,
                               ENGINE *impl, const unsigned char *key, const unsigned char *iv);
        int EVP_DecryptInit_ex2(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type,
                                const unsigned char *key, const unsigned char *iv,
                                const OSSL_PARAM params[]);

        int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out,
                              int *outl, const unsigned char *in, int inl);

        int EVP_DecryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl);
        int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl);

加解密统一API

        int EVP_CipherInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type,
                           const unsigned char *key, const unsigned char *iv, int enc);
        int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type,
                              ENGINE *impl, const unsigned char *key, const unsigned char *iv, int enc);
        int EVP_CipherInit_ex2(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type,
                               const unsigned char *key, const unsigned char *iv,
                               int enc, const OSSL_PARAM params[]);

        int EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out,
                             int *outl, const unsigned char *in, int inl);

        int EVP_CipherFinal(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl);
        int EVP_CipherFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl);

其他设置

        int EVP_CIPHER_get_block_size(const EVP_CIPHER *e);
        int EVP_CIPHER_get_key_length(const EVP_CIPHER *e);
        int EVP_CIPHER_get_iv_length(const EVP_CIPHER *e);
        int EVP_CIPHER_CTX_get_block_size(const EVP_CIPHER_CTX *ctx);
        int EVP_CIPHER_CTX_get_key_length(const EVP_CIPHER_CTX *ctx);
        int EVP_CIPHER_CTX_get_iv_length(const EVP_CIPHER_CTX *ctx);
         int EVP_CIPHER_CTX_get_tag_length(const EVP_CIPHER_CTX *ctx);

        int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *x, int padding);
        int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *x, int keylen);
        int EVP_CIPHER_CTX_rand_key(EVP_CIPHER_CTX *ctx, unsigned char *key);
        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);

        
        int EVP_CIPHER_CTX_is_encrypting(const EVP_CIPHER_CTX *ctx);

        #define EVP_CIPHER_block_size EVP_CIPHER_get_block_size
        #define EVP_CIPHER_key_length EVP_CIPHER_get_key_length
        #define EVP_CIPHER_iv_length EVP_CIPHER_get_iv_length
        #define EVP_CIPHER_CTX_encrypting EVP_CIPHER_CTX_is_encrypting
        #define EVP_CIPHER_CTX_block_size EVP_CIPHER_CTX_get_block_size
        #define EVP_CIPHER_CTX_key_length EVP_CIPHER_CTX_get_key_length
        #define EVP_CIPHER_CTX_iv_length EVP_CIPHER_CTX_get_iv_length
        #define EVP_CIPHER_CTX_tag_length EVP_CIPHER_CTX_get_tag_length

例子

非对称加密

密钥管理

公钥算法上下文 EVP_PKEY_CTX

        #include <openssl/evp.h>

        EVP_PKEY_CTX *EVP_PKEY_CTX_new(EVP_PKEY *pkey, ENGINE *e);
        EVP_PKEY_CTX *EVP_PKEY_CTX_new_id(int id, ENGINE *e);
        EVP_PKEY_CTX *EVP_PKEY_CTX_new_from_name(OSSL_LIB_CTX *libctx,
                                                 const char *name,
                                                 const char *propquery);
        EVP_PKEY_CTX *EVP_PKEY_CTX_new_from_pkey(OSSL_LIB_CTX *libctx,
                                                 EVP_PKEY *pkey,
                                                 const char *propquery);
        EVP_PKEY_CTX *EVP_PKEY_CTX_dup(const EVP_PKEY_CTX *ctx);
        void EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx);
        int EVP_PKEY_CTX_is_a(EVP_PKEY_CTX *ctx, const char *keytype);

常用的可能是EVP_PKEY_CTX_new_from_name和EVP_PKEY_CTX_new

各种参数设置

        #include <openssl/evp.h>

        int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype,
                              int cmd, int p1, void *p2);
        int EVP_PKEY_CTX_ctrl_uint64(EVP_PKEY_CTX *ctx, int keytype, int optype,
                                     int cmd, uint64_t value);
        int EVP_PKEY_CTX_ctrl_str(EVP_PKEY_CTX *ctx, const char *type,
                                  const char *value);

        int EVP_PKEY_CTX_md(EVP_PKEY_CTX *ctx, int optype, int cmd, const char *md);

        int EVP_PKEY_CTX_set_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD *md);
        int EVP_PKEY_CTX_get_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD **pmd);

        int EVP_PKEY_CTX_set_mac_key(EVP_PKEY_CTX *ctx, const unsigned char *key,
                                     int len);
        int EVP_PKEY_CTX_set_group_name(EVP_PKEY_CTX *ctx, const char *name);
        int EVP_PKEY_CTX_get_group_name(EVP_PKEY_CTX *ctx, char *name, size_t namelen);

        int EVP_PKEY_CTX_set_kem_op(EVP_PKEY_CTX *ctx, const char *op);

        #include <openssl/rsa.h>

        int EVP_PKEY_CTX_set_rsa_padding(EVP_PKEY_CTX *ctx, int pad);
        int EVP_PKEY_CTX_get_rsa_padding(EVP_PKEY_CTX *ctx, int *pad);
        int EVP_PKEY_CTX_set_rsa_pss_saltlen(EVP_PKEY_CTX *ctx, int saltlen);
        int EVP_PKEY_CTX_get_rsa_pss_saltlen(EVP_PKEY_CTX *ctx, int *saltlen);
        int EVP_PKEY_CTX_set_rsa_keygen_bits(EVP_PKEY_CTX *ctx, int mbits);
        int EVP_PKEY_CTX_set1_rsa_keygen_pubexp(EVP_PKEY_CTX *ctx, BIGNUM *pubexp);
        int EVP_PKEY_CTX_set_rsa_keygen_primes(EVP_PKEY_CTX *ctx, int primes);
        int EVP_PKEY_CTX_set_rsa_mgf1_md_name(EVP_PKEY_CTX *ctx, const char *mdname,
                                            const char *mdprops);
        int EVP_PKEY_CTX_set_rsa_mgf1_md(EVP_PKEY_CTX *ctx, const EVP_MD *md);
        int EVP_PKEY_CTX_get_rsa_mgf1_md(EVP_PKEY_CTX *ctx, const EVP_MD **md);
        int EVP_PKEY_CTX_get_rsa_mgf1_md_name(EVP_PKEY_CTX *ctx, char *name,
                                              size_t namelen);
        int EVP_PKEY_CTX_set_rsa_oaep_md_name(EVP_PKEY_CTX *ctx, const char *mdname,
                                              const char *mdprops);
        int EVP_PKEY_CTX_set_rsa_oaep_md(EVP_PKEY_CTX *ctx, const EVP_MD *md);
        int EVP_PKEY_CTX_get_rsa_oaep_md(EVP_PKEY_CTX *ctx, const EVP_MD **md);
        int EVP_PKEY_CTX_get_rsa_oaep_md_name(EVP_PKEY_CTX *ctx, char *name,
                                              size_t namelen);
        int EVP_PKEY_CTX_set0_rsa_oaep_label(EVP_PKEY_CTX *ctx, void *label,
                                             int len);
        int EVP_PKEY_CTX_get0_rsa_oaep_label(EVP_PKEY_CTX *ctx, unsigned char **label);

        #include <openssl/dsa.h>

        int EVP_PKEY_CTX_set_dsa_paramgen_bits(EVP_PKEY_CTX *ctx, int nbits);
        int EVP_PKEY_CTX_set_dsa_paramgen_q_bits(EVP_PKEY_CTX *ctx, int qbits);
        int EVP_PKEY_CTX_set_dsa_paramgen_md(EVP_PKEY_CTX *ctx, const EVP_MD *md);
        int EVP_PKEY_CTX_set_dsa_paramgen_md_props(EVP_PKEY_CTX *ctx,
                                                   const char *md_name,
                                                   const char *md_properties);
        int EVP_PKEY_CTX_set_dsa_paramgen_type(EVP_PKEY_CTX *ctx, const char *name);
        int EVP_PKEY_CTX_set_dsa_paramgen_gindex(EVP_PKEY_CTX *ctx, int gindex);
        int EVP_PKEY_CTX_set_dsa_paramgen_seed(EVP_PKEY_CTX *ctx,
                                               const unsigned char *seed,
                                               size_t seedlen);

        #include <openssl/dh.h>

        int EVP_PKEY_CTX_set_dh_paramgen_prime_len(EVP_PKEY_CTX *ctx, int len);
        int EVP_PKEY_CTX_set_dh_paramgen_subprime_len(EVP_PKEY_CTX *ctx, int len);
        int EVP_PKEY_CTX_set_dh_paramgen_generator(EVP_PKEY_CTX *ctx, int gen);
        int EVP_PKEY_CTX_set_dh_paramgen_type(EVP_PKEY_CTX *ctx, int type);
        int EVP_PKEY_CTX_set_dh_pad(EVP_PKEY_CTX *ctx, int pad);
        int EVP_PKEY_CTX_set_dh_nid(EVP_PKEY_CTX *ctx, int nid);
        int EVP_PKEY_CTX_set_dh_rfc5114(EVP_PKEY_CTX *ctx, int rfc5114);
        int EVP_PKEY_CTX_set_dhx_rfc5114(EVP_PKEY_CTX *ctx, int rfc5114);
        int EVP_PKEY_CTX_set_dh_paramgen_gindex(EVP_PKEY_CTX *ctx, int gindex);
        int EVP_PKEY_CTX_set_dh_paramgen_seed(EVP_PKEY_CTX *ctx,
                                               const unsigned char *seed,
                                               size_t seedlen);
        int EVP_PKEY_CTX_set_dh_kdf_type(EVP_PKEY_CTX *ctx, int kdf);
        int EVP_PKEY_CTX_get_dh_kdf_type(EVP_PKEY_CTX *ctx);
        int EVP_PKEY_CTX_set0_dh_kdf_oid(EVP_PKEY_CTX *ctx, ASN1_OBJECT *oid);
        int EVP_PKEY_CTX_get0_dh_kdf_oid(EVP_PKEY_CTX *ctx, ASN1_OBJECT **oid);
        int EVP_PKEY_CTX_set_dh_kdf_md(EVP_PKEY_CTX *ctx, const EVP_MD *md);
        int EVP_PKEY_CTX_get_dh_kdf_md(EVP_PKEY_CTX *ctx, const EVP_MD **md);
        int EVP_PKEY_CTX_set_dh_kdf_outlen(EVP_PKEY_CTX *ctx, int len);
        int EVP_PKEY_CTX_get_dh_kdf_outlen(EVP_PKEY_CTX *ctx, int *len);
        int EVP_PKEY_CTX_set0_dh_kdf_ukm(EVP_PKEY_CTX *ctx, unsigned char *ukm, int len);

        #include <openssl/ec.h>

        int EVP_PKEY_CTX_set_ec_paramgen_curve_nid(EVP_PKEY_CTX *ctx, int nid);
        int EVP_PKEY_CTX_set_ec_param_enc(EVP_PKEY_CTX *ctx, int param_enc);
        int EVP_PKEY_CTX_set_ecdh_cofactor_mode(EVP_PKEY_CTX *ctx, int cofactor_mode);
        int EVP_PKEY_CTX_get_ecdh_cofactor_mode(EVP_PKEY_CTX *ctx);
        int EVP_PKEY_CTX_set_ecdh_kdf_type(EVP_PKEY_CTX *ctx, int kdf);
        int EVP_PKEY_CTX_get_ecdh_kdf_type(EVP_PKEY_CTX *ctx);
        int EVP_PKEY_CTX_set_ecdh_kdf_md(EVP_PKEY_CTX *ctx, const EVP_MD *md);
        int EVP_PKEY_CTX_get_ecdh_kdf_md(EVP_PKEY_CTX *ctx, const EVP_MD **md);
        int EVP_PKEY_CTX_set_ecdh_kdf_outlen(EVP_PKEY_CTX *ctx, int len);
        int EVP_PKEY_CTX_get_ecdh_kdf_outlen(EVP_PKEY_CTX *ctx, int *len);
        int EVP_PKEY_CTX_set0_ecdh_kdf_ukm(EVP_PKEY_CTX *ctx, unsigned char *ukm, int len);

生成密钥

        int EVP_PKEY_keygen_init(EVP_PKEY_CTX *ctx);
        int EVP_PKEY_paramgen_init(EVP_PKEY_CTX *ctx);
        int EVP_PKEY_generate(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey);

例如:

  • Generate a 2048 bit RSA key:
        #include <openssl/evp.h>
        #include <openssl/rsa.h>

        EVP_PKEY_CTX *ctx;
        EVP_PKEY *pkey = NULL;

        ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
        if (!ctx)
            /* Error occurred */
        if (EVP_PKEY_keygen_init(ctx) <= 0)
            /* Error */
        if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, 2048) <= 0)
            /* Error */

        /* Generate key */
        if (EVP_PKEY_keygen(ctx, &pkey) <= 0)
            /* Error */
  • Generate a key from a set of parameters:
        #include <openssl/evp.h>
        #include <openssl/rsa.h>

        EVP_PKEY_CTX *ctx;
        ENGINE *eng;
        EVP_PKEY *pkey = NULL, *param;

        /* Assumed param, eng are set up already */
        ctx = EVP_PKEY_CTX_new(param, eng);
        if (!ctx)
            /* Error occurred */
        if (EVP_PKEY_keygen_init(ctx) <= 0)
            /* Error */

        /* Generate key */
        if (EVP_PKEY_keygen(ctx, &pkey) <= 0)
            /* Error */
  • Example of generation callback for OpenSSL public key implementations:
        /* Application data is a BIO to output status to */

        EVP_PKEY_CTX_set_app_data(ctx, status_bio);

        static int genpkey_cb(EVP_PKEY_CTX *ctx)
        {
            char c = '*';
            BIO *b = EVP_PKEY_CTX_get_app_data(ctx);
            int p = EVP_PKEY_CTX_get_keygen_info(ctx, 0);

            if (p == 0)
                c = '.';
            if (p == 1)
                c = '+';
            if (p == 2)
                c = '*';
            if (p == 3)
                c = '\n';
            BIO_write(b, &c, 1);
            (void)BIO_flush(b);
            return 1;
        }

密钥参数打印

        #include <openssl/evp.h>

        int EVP_PKEY_print_public(BIO *out, const EVP_PKEY *pkey,
                                  int indent, ASN1_PCTX *pctx);
        int EVP_PKEY_print_public_fp(FILE *fp, const EVP_PKEY *pkey,
                                     int indent, ASN1_PCTX *pctx);
        int EVP_PKEY_print_private(BIO *out, const EVP_PKEY *pkey,
                                   int indent, ASN1_PCTX *pctx);
        int EVP_PKEY_print_private_fp(FILE *fp, const EVP_PKEY *pkey,
                                      int indent, ASN1_PCTX *pctx);
        int EVP_PKEY_print_params(BIO *out, const EVP_PKEY *pkey,
                                  int indent, ASN1_PCTX *pctx);
        int EVP_PKEY_print_params_fp(FILE *fp, const EVP_PKEY *pkey,
                                     int indent, ASN1_PCTX *pctx);

密钥的提取和指定

        int EVP_PKEY_get_raw_private_key(const EVP_PKEY *pkey, unsigned char *priv,
                                         size_t *len);
        int EVP_PKEY_get_raw_public_key(const EVP_PKEY *pkey, unsigned char *pub,
                                        size_t *len);

        EVP_PKEY *EVP_PKEY_new_raw_private_key_ex(OSSL_LIB_CTX *libctx,
                                                  const char *keytype,
                                                  const char *propq,
                                                  const unsigned char *key,
                                                  const unsigned char *key,
                                                  size_t keylen);
        EVP_PKEY *EVP_PKEY_new_raw_private_key(int type, ENGINE *e,
                                               const unsigned char *key, size_t keylen);
        EVP_PKEY *EVP_PKEY_new_raw_public_key_ex(OSSL_LIB_CTX *libctx,
                                                 const char *keytype,
                                                 const char *propq,
                                                 const unsigned char *key,
                                                 size_t keylen);
        EVP_PKEY *EVP_PKEY_new_raw_public_key(int type, ENGINE *e,
                                              const unsigned char *key, size_t keylen);

密钥的保存和读取

使用OSSL_ENCODER和OSSL_DECODER

构建OSSL_ENCODER_CTX

        #include <openssl/encoder.h>

        OSSL_ENCODER_CTX *
        OSSL_ENCODER_CTX_new_for_pkey(const EVP_PKEY *pkey, int selection,
        OSSL_ENCODER_CTX_new_for_pkey(const EVP_PKEY *pkey, int selection,
                                      const char *output_type,
                                      const char *output_structure,
                                      const char *propquery);

        int OSSL_ENCODER_CTX_set_cipher(OSSL_ENCODER_CTX *ctx,
                                        const char *cipher_name,
                                        const char *propquery);
        int OSSL_ENCODER_CTX_set_passphrase(OSSL_ENCODER_CTX *ctx,
                                            const unsigned char *kstr,
                                            size_t klen);
        int OSSL_ENCODER_CTX_set_pem_password_cb(OSSL_ENCODER_CTX *ctx,
                                                 pem_password_cb *cb, void *cbarg);
        int OSSL_ENCODER_CTX_set_passphrase_ui(OSSL_ENCODER_CTX *ctx,
                                               const UI_METHOD *ui_method,
                                               void *ui_data);
        int OSSL_ENCODER_CTX_set_passphrase_cb(OSSL_ENCODER_CTX *ctx,
                                               OSSL_PASSPHRASE_CALLBACK *cb,
                                               void *cbarg);

编码输出

        #include <openssl/encoder.h>

        int OSSL_ENCODER_to_data(OSSL_ENCODER_CTX *ctx, unsigned char **pdata,
                                 size_t *pdata_len);
        int OSSL_ENCODER_to_bio(OSSL_ENCODER_CTX *ctx, BIO *out);
        int OSSL_ENCODER_to_fp(OSSL_ENCODER_CTX *ctx, FILE *fp);

构建OSSL_DECODER_CTX

        #include <openssl/decoder.h>

        typedef struct ossl_decoder_ctx_st OSSL_DECODER_CTX;

        OSSL_DECODER_CTX *OSSL_DECODER_CTX_new(void);
        const OSSL_PARAM *OSSL_DECODER_settable_ctx_params(OSSL_DECODER *decoder);
        int OSSL_DECODER_CTX_set_params(OSSL_DECODER_CTX *ctx,
                                        const OSSL_PARAM params[]);
        void OSSL_DECODER_CTX_free(OSSL_DECODER_CTX *ctx);

        int OSSL_DECODER_CTX_set_selection(OSSL_DECODER_CTX *ctx, int selection);
        int OSSL_DECODER_CTX_set_input_type(OSSL_DECODER_CTX *ctx,
                                            const char *input_type);
        int OSSL_DECODER_CTX_set_input_structure(OSSL_DECODER_CTX *ctx,
                                                 const char *input_structure);
        int OSSL_DECODER_CTX_add_decoder(OSSL_DECODER_CTX *ctx, OSSL_DECODER *decoder);
        int OSSL_DECODER_CTX_add_extra(OSSL_DECODER_CTX *ctx,
                                       OSSL_LIB_CTX *libctx,
                                       const char *propq);
        int OSSL_DECODER_CTX_get_num_decoders(OSSL_DECODER_CTX *ctx);

        typedef struct ossl_decoder_instance_st OSSL_DECODER_INSTANCE;
        OSSL_DECODER *
        OSSL_DECODER_INSTANCE_get_decoder(OSSL_DECODER_INSTANCE *decoder_inst);
        void *
        OSSL_DECODER_INSTANCE_get_decoder_ctx(OSSL_DECODER_INSTANCE *decoder_inst);
        const char *
        OSSL_DECODER_INSTANCE_get_input_type(OSSL_DECODER_INSTANCE *decoder_inst);
        OSSL_DECODER_INSTANCE_get_input_structure(OSSL_DECODER_INSTANCE *decoder_inst,
                                                  int *was_set);

        typedef int OSSL_DECODER_CONSTRUCT(OSSL_DECODER_INSTANCE *decoder_inst,
                                           const OSSL_PARAM *object,
                                           void *construct_data);
        typedef void OSSL_DECODER_CLEANUP(void *construct_data);

        int OSSL_DECODER_CTX_set_construct(OSSL_DECODER_CTX *ctx,
                                           OSSL_DECODER_CONSTRUCT *construct);
        int OSSL_DECODER_CTX_set_construct_data(OSSL_DECODER_CTX *ctx,
                                                void *construct_data);
        int OSSL_DECODER_CTX_set_cleanup(OSSL_DECODER_CTX *ctx,
                                         OSSL_DECODER_CLEANUP *cleanup);
        OSSL_DECODER_CONSTRUCT *OSSL_DECODER_CTX_get_construct(OSSL_DECODER_CTX *ctx);
        void *OSSL_DECODER_CTX_get_construct_data(OSSL_DECODER_CTX *ctx);
        OSSL_DECODER_CLEANUP *OSSL_DECODER_CTX_get_cleanup(OSSL_DECODER_CTX *ctx);

        int OSSL_DECODER_export(OSSL_DECODER_INSTANCE *decoder_inst,
                                void *reference, size_t reference_sz,
                                OSSL_CALLBACK *export_cb, void *export_cbarg);

解码

        #include <openssl/decoder.h>

        int OSSL_DECODER_from_bio(OSSL_DECODER_CTX *ctx, BIO *in);
        int OSSL_DECODER_from_fp(OSSL_DECODER_CTX *ctx, FILE *fp);
        int OSSL_DECODER_from_data(OSSL_DECODER_CTX *ctx, const unsigned char **pdata,
                                   size_t *pdata_len);
使用EVP_PKEY_todata和EVP_PKEY_fromdata
        #include <openssl/evp.h>

        int EVP_PKEY_todata(const EVP_PKEY *pkey, int selection, OSSL_PARAM **params);
        int EVP_PKEY_export(const EVP_PKEY *pkey, int selection,
                            OSSL_CALLBACK *export_cb, void *export_cbarg);

        int EVP_PKEY_fromdata_init(EVP_PKEY_CTX *ctx);
        int EVP_PKEY_fromdata(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey, int selection,
                              OSSL_PARAM params[]);
        const OSSL_PARAM *EVP_PKEY_fromdata_settable(EVP_PKEY_CTX *ctx, int selection);

检测私钥是否正确

        #include <openssl/evp.h>

        int EVP_PKEY_check(EVP_PKEY_CTX *ctx);
        int EVP_PKEY_param_check(EVP_PKEY_CTX *ctx);
        int EVP_PKEY_param_check_quick(EVP_PKEY_CTX *ctx);
        int EVP_PKEY_public_check(EVP_PKEY_CTX *ctx);
        int EVP_PKEY_public_check_quick(EVP_PKEY_CTX *ctx);
        int EVP_PKEY_private_check(EVP_PKEY_CTX *ctx);
        int EVP_PKEY_pairwise_check(EVP_PKEY_CTX *ctx);

加解密

        #include <openssl/evp.h>

        int EVP_PKEY_encrypt_init(EVP_PKEY_CTX *ctx);
        int EVP_PKEY_encrypt_init_ex(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[]);
        int EVP_PKEY_encrypt(EVP_PKEY_CTX *ctx,
                             unsigned char *out, size_t *outlen,
                             const unsigned char *in, size_t inlen);

        int EVP_PKEY_decrypt_init(EVP_PKEY_CTX *ctx);
        int EVP_PKEY_decrypt_init_ex(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[]);
        int EVP_PKEY_decrypt(EVP_PKEY_CTX *ctx,
                             unsigned char *out, size_t *outlen,
                             const unsigned char *in, size_t inlen);

签名和验签

签名

        #include <openssl/evp.h>

        int EVP_PKEY_sign_init(EVP_PKEY_CTX *ctx);
        int EVP_PKEY_sign_init_ex(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[]);
        int EVP_PKEY_sign(EVP_PKEY_CTX *ctx,
                          unsigned char *sig, size_t *siglen,
                          const unsigned char *tbs, size_t tbslen);

验签

        #include <openssl/evp.h>

        int EVP_PKEY_verify_init(EVP_PKEY_CTX *ctx);
        int EVP_PKEY_verify_init_ex(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[]);
        int EVP_PKEY_verify(EVP_PKEY_CTX *ctx,
                            const unsigned char *sig, size_t siglen,
                            const unsigned char *tbs, size_t tbslen);