关于i2d_X509_REQ() api从版本1.1.1升级到3.0.5的openssl升级

问题描述 投票:0回答:1

我已从 openssl 1.1.1 升级到 opessl 3.0.5。我在 i2d_X509_REQ(X509_REQ* req, nullptr) api 中获取 openssl 3.0.5 中内容的长度时遇到错误。我得到的长度错误为-1。谁能指导我解决这个兼容性问题?提前谢谢了。另外,是否可以打印由于 openssl api 导致的错误原因?它将用于查找发生的确切错误。

#include <iostream>
#include <openssl/evp.h>
#include <openssl/rsa.h>
#include <openssl/bio.h>
#include <openssl/pem.h>
#include <openssl/engine.h>
#include <filesystem>
#include <openssl/x509.h>
using namespace std;


int main()
{
    EVP_PKEY_CTX *ctx;
    EVP_PKEY *pkey = NULL;
    ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
    if (!ctx) {
        std::cout<<"ctx error"<<std::endl;
    }
        /* Error occurred */
    if (EVP_PKEY_keygen_init(ctx) <= 0) {
        std::cout<<"EVP_PKEY_CTX_new_id error"<<std::endl;
    }

    if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, 4096) <= 0) {
        std::cout<<"EVP_PKEY_CTX_set_rsa_keygen_bits error"<<std::endl;
    }

    /* Generate key */
    if (EVP_PKEY_keygen(ctx, &pkey) <= 0) {
        std::cout<<"EVP_PKEY_keygen error"<<std::endl;
    }

    /* Writes the generated key to file*/
    FILE *fp;
    fp = fopen("/home/tpb1cob/1day/openssl/public_key.txt","w");
    if (0 == PEM_write_PUBKEY(fp,pkey)) {
        std::cout<<"file write fail"<<std::endl;
    }
    fclose(fp);

    /*Encode the key and write to buffer*/
    unsigned char* p;
    int ret = -1;
    ret = i2d_PublicKey(pkey,&p);
    if(ret < 0) {
        std::cout<<"i2d_PublicKey returns negative value"<<ret<<std::endl;
    }
    std::cout<<"i2d_PublicKey returns value "<<ret<<std::endl;
    std::cout<<p<<std::endl;

    /*Decodes buffer contents and assign to EVP_Key structure*/
    EVP_PKEY *pkey1 = NULL;
    if(NULL == d2i_PublicKey(EVP_PKEY_RSA,&pkey1,(const unsigned char**)&p,526)) {
        std::cout<<"d2i_PrivateKey_fp returns NULL pointer"<<std::endl;
    }

    /* Writes the decoded key to file*/
    FILE *fpq;
    fpq = fopen("/home/tpb1cob/1day/openssl/public_key_decoded.txt","w");
    if (0 == PEM_write_PUBKEY(fpq,pkey1)) {
        std::cout<<"file write fail"<<std::endl;
    }
    fclose(fpq);
    
    /* checks the parameters of keys pkey and pkey1 for equality */
    if(1 == EVP_PKEY_eq(pkey,pkey1)) {
        std::cout<<"EVP_PKEY_eq success"<<std::endl;
    }
    

    //"C=UK, O=Disorganized Organization, CN=Joe Bloggs"

    X509_NAME *nm;
    X509_REQ *CR;

    nm = X509_NAME_new();
    CR = X509_REQ_new();    
    if (nm == NULL) {
        std::cout<<"X509_NAME_new failed"<<std::endl;
    }
        /* Some error */

    int ii = -1;

     if (1 == X509_NAME_add_entry_by_txt(nm, "C", MBSTRING_ASC,(const unsigned char*)"UK", -1, -1, 0)) {
        std::cout<<"X509_NAME_add_entry_by_txt country success"<<std::endl;
    }
        /* Error */
    if (1 == X509_NAME_add_entry_by_txt(nm, "O", MBSTRING_ASC,(const unsigned char*)"Disorganized Organization", -1, -1, 0)) {
        std::cout<<"X509_NAME_add_entry_by_txt organization success"<<std::endl;
    }
    
    if (1 == X509_NAME_add_entry_by_txt(nm, "OU", MBSTRING_ASC,(const unsigned char*)"Organization Unit", -1, -1, 0)) {
        std::cout<<"X509_NAME_add_entry_by_txt organization unit success"<<std::endl;
    }
        /* Error */
    if (1 == X509_NAME_add_entry_by_txt(nm, "CN", MBSTRING_ASC,(const unsigned char*)"Joe Bloggs", -1, -1, 0)) {
        std::cout<<"X509_NAME_add_entry_by_txt common name success"<<std::endl;
    }

    if (1 == X509_REQ_set_subject_name(CR, nm)) {
        std::cout<<"X509_REQ_set_subject_name success"<<std::endl;
    }
    
    X509_NAME_free(nm);

    if(1 == X509_REQ_set_pubkey(CR, pkey)) {
        std::cout<<"X509_REQ_set_pubkey success"<<std::endl;
    }

    int length = i2d_X509_REQ(CR, NULL);
    const char** file;
    int* line;

    if (length <= 0) {
        std::cout<<"i2d_X509_REQ fail"<<length<<std::endl;
    }
    
    return 0;
}

我尝试获取证书请求的长度,但它总是返回-1。

openssl x509certificate x509
1个回答
0
投票

反问你的问题:

另外,是否可以打印由于 openssl api 导致的错误原因?

是的。请参阅常见问题解答手册页。在某些情况下,您可能需要使用更基本的方法更详细地查看代码,但我不会从这里开始。 (但是请注意,下一个常见问题解答 PROG9 已过时;在 OpenSSL 1.1.0 中,错误字符串始终会自动加载,您不再需要为它们编写代码。此外,虽然 libcrypto 例程的所有失败都应提供错误队列信息,libssl 则不同;像

SSL_connect
SSL_read
这样的例程在非阻塞模式或 EOF 下可能会“失败”而不会出现任何错误,您应该在查看 SSL_get_error
 之前调用 
ERR_*
 来解决这些问题。)

有人可以指导我解决这个兼容性问题吗?

在代码中调用

ERR_print_errors_fp
失败后执行
i2d_X509_REQ
给出

{thread}:error:068000DE:asn1 encoding routines:(unknown function):illegal zero content:crypto/asn1/tasn_enc.c:374:

虽然不完全明显,但这是因为您没有签署请求,因此签名算法和签名的值(它们是实际 PKCS10 结构的必需部分)丢失了。

解决方案:首先调用

X509_REQ_sign[_ctx]
(使用您生成的
EVP_PKEY
,其中包含私钥和公钥)。

另请注意,您正在写出密钥对的公共部分(带有

PEM_write_PUBKEY
),而不是私有部分。如果你不将私钥保存在某个地方,你的 CSR 基本上就没用了,因为从该 CSR 获得的任何证书只能与私钥结合使用才能成功使用。

最后,你的“编码然后解码公钥”代码是不安全的;它声明

unsigned char * p
然后使用它而不进行初始化。 可能您在您使用的系统上使用的编译器碰巧以包含 0/null 的方式创建它,这(或多或少)有效,但您不应该依赖于此。

© www.soinside.com 2019 - 2024. All rights reserved.