您好,我正在尝试使用OpenSSL(evp)生成一对私钥和公钥,但是我的代码遇到很多问题,如下所示:

EVP_PKEY_CTX *ctx = NULL;

     if(!EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, NID_secp256k1))
     {
          std::cout << "error 1 " << std::endl;
     }
     else
     {
         EVP_PKEY *pkey = NULL;
         ENGINE *e = NULL;
        if(*pkey != NULL)
         {
           if(!(ctx = EVP_PKEY_CTX_new(pkey, e)))
           {
               std::cout << "bien 1" << std::endl;
           }
         }
          else
         {
             int id{0};
             id++;
            if(!(ctx = EVP_PKEY_CTX_new_id(id, e)))
            {
                std::cout << "bien 2" << std::endl;
            }
         }

         EVP_PKEY *ppkey = NULL;
         if (1 != EVP_PKEY_keygen(ctx, &ppkey))
         {
            std::cout << "error 2" << std::endl;
         }
         else
         {
               std::cout << *ppkey << std::endl;
         }
     }


密钥通常应该在ppkey中,但是我无法访问其内容。
这是出现的错误:

main.cpp | 20 |错误:'operator!='不匹配(操作数类型为'EVP_PKEY'{aka'evp_pkey_st'}和'long long int')|

最佳答案

根据EVP_PKEY_keygen() man page EVP_PKEY_keygen()功能界面是

int EVP_PKEY_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey);


您可以通过ppkey参数的地址来调用此API;

EVP_PKEY **ppkey;
if (! EVP_PKEY_keygen (ctx, &ppkey))
{

}


由于其类型为EVP_PKEY **,因此实际上您正在向函数传递EVP_PKEY ***参数,这会导致您遇到错误。

试试看

EVP_PKEY **ppkey;
if (! EVP_PKEY_keygen (ctx, ppkey))
{

}


甚至更好

EVP_PKEY *ppkey;
if (! EVP_PKEY_keygen (ctx, &ppkey))
{

}


这样,您的指针将包含所需键结构的地址。


  EVP_PKEY_keygen()函数执行密钥生成操作,
  生成的密钥被写入ppkey。


然后,您将能够像在C中的每个struct字段一样访问其字段。例如,在EVP_PKEY *ppkey;的情况下,您将具有ppkey->ameth(访问结构指针的字段)或(*ppkey).ameth(直接访问以下字段)递归指针后的结构)。

仅出于完整性考虑,这是EVP_PKEY结构的定义(git版本_OpenSSL_1_1_1-2526-gdc8de3e_):


从include / openssl / types.h中:


typedef struct evp_pkey_st EVP_PKEY;



从include / crypto / evp.h:


/*
 * 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 {
    /* == Legacy attributes == */
    int type;
    int save_type;
    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;

    /* == Common attributes == */
    CRYPTO_REF_COUNT references;
    CRYPTO_RWLOCK *lock;
    STACK_OF(X509_ATTRIBUTE) *attributes; /* [ 0 ] */
    int save_parameters;

    /* == Provider attributes == */
    /*
     * To support transparent export/import between providers that
     * support the methods for it, and still not having to do the
     * export/import every time a key or domain params are used, we
     * maintain a cache of imported key / domain params, indexed by
     * provider address.  pkeys[0] is *always* the "original" data.
     */
    struct {
        EVP_KEYMGMT *keymgmt;
        void *provdata;
        /* 0 = provdata is a key, 1 = provdata is domain params */
        int domainparams;
    } pkeys[10];
    /*
     * If there is a legacy key assigned to this structure, we keep
     * a copy of that key's dirty count.
     */
    size_t dirty_cnt_copy;

    /* Cache of domain parameter / key information */
    struct {
        int bits;
        int security_bits;
        int size;
    } cache;
} /* EVP_PKEY */ ;

09-07 08:28