Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/71.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 从内存中读取证书文件,而不是使用OpenSSL读取文件_C_Openssl_Certificate - Fatal编程技术网

C 从内存中读取证书文件,而不是使用OpenSSL读取文件

C 从内存中读取证书文件,而不是使用OpenSSL读取文件,c,openssl,certificate,C,Openssl,Certificate,我有一个使用OpenSSL在HTTPS上侦听的服务器。为此,我必须提供证书才能使用。但是,当前的实现使用要提供给OpenSSL API的文件名 我希望从内存中读取证书信息,这样我就不必打开证书文件。我试着用谷歌搜索,但没有任何选择 有可能吗?如果是这样,我如何从内存中读取证书文件,而不是使用OpenSSL读取文件 编辑:以下内容已从评论移至问题 // CURRENT void start_server() { const char *fileName = "cert_and_key.p

我有一个使用OpenSSL在HTTPS上侦听的服务器。为此,我必须提供证书才能使用。但是,当前的实现使用要提供给OpenSSL API的文件名

我希望从内存中读取证书信息,这样我就不必打开证书文件。我试着用谷歌搜索,但没有任何选择

有可能吗?如果是这样,我如何从内存中读取证书文件,而不是使用OpenSSL读取文件


编辑:以下内容已从评论移至问题

// CURRENT
void start_server()
{
    const char *fileName = "cert_and_key.pem";
    set_server_ssl_file(fileName);
}
set_server_ssl_file(const char *fileName)
{
    //initialize context
    SSL_CTX_use_certificate_file(CTX, pem, SSL_FILETYPE_PEM); 
    SSL_CTX_use_PrivateKey_file(CTX, pem, SSL_FILETYPE_PEM);
}

//REQUIRED
void start_server()
{
    const char *cert = "--BEGIN CERTIFICATE--............";
    const char *key = "--BEGIN RSA PRIVATE KEY--.......";
    set_server_ssl_options(cert, key);
}
set_server_ssl_options(const char *cert, const char *key)
{
    //IMPLEMENTATION REQUIRED
}

不要忘记
&
证书数据
pkey_数据
之前,请注意OpenSSL修改了这些指针。

以下代码为我完成了任务:


SSL_CTX *CTX;
X509 *cert = NULL;
RSA *rsa = NULL;
BIO *cbio, *kbio;
const char *cert_buffer = "";
const char *key_buffer = "";

cbio = BIO_new_mem_buf((void*)cert_buffer, -1);
cert = PEM_read_bio_X509(cbio, NULL, 0, NULL);
assert(cert != NULL);
SSL_CTX_use_certificate(CTX, cert);

kbio = BIO_new_mem_buf((void*)key_buffer, -1);
rsa = PEM_read_bio_RSAPrivateKey(kbio, NULL, 0, NULL);
assert(rsa != NULL);
SSL_CTX_use_RSAPrivateKey(CTX, rsa);

其他代码段将只加载一个证书。像这样包含许多不同证书的文件的内容需要一种新的方法。这是从openssl 1.0.1p(主要是openssl-1.0.1p\crypto\x509\by_file.c,char*buf包含*.pem文件的内容,ctx是boost::asio::ssl::context)改编而来的,您可以自己添加错误处理:

BIO *cbio = BIO_new_mem_buf((void*)buf, (int)length);
X509_STORE  *cts = SSL_CTX_get_cert_store(ctx.native_handle());
if(!cts || !cbio)
   return false;
X509_INFO *itmp;
int i, count = 0, type = X509_FILETYPE_PEM;
STACK_OF(X509_INFO) *inf = PEM_X509_INFO_read_bio(cbio, NULL, NULL, NULL);

if (!inf)
{
    BIO_free(cbio);//cleanup
    return false;
}
//itterate over all entries from the pem file, add them to the x509_store one by one
for (i = 0; i < sk_X509_INFO_num(inf); i++) {
    itmp = sk_X509_INFO_value(inf, i);
    if (itmp->x509) {
          X509_STORE_add_cert(cts, itmp->x509);
          count++;
    }
    if (itmp->crl) {
          X509_STORE_add_crl(cts, itmp->crl);
          count++;
    }
}
sk_X509_INFO_pop_free(inf, X509_INFO_free); //cleanup
BIO_free(cbio);//cleanup
BIO*cbio=BIO_new_mem_buf((void*)buf,(int)长度);
X509_STORE*cts=SSL_CTX_get_cert_STORE(CTX.native_handle());
如果(!cts | |!cbio)
返回false;
X509_信息*itmp;
int i,count=0,type=X509\u FILETYPE\u PEM;
堆栈(X509\u INFO)*inf=PEM\u X509\u INFO\u read\u bio(cbio,NULL,NULL,NULL);
如果(!inf)
{
无生物(cbio);//清除
返回false;
}
//将pem文件中的所有条目逐一添加到x509_存储中
对于(i=0;ix509){
X509存储添加证书(cts、itmp->X509);
计数++;
}
如果(itmp->crl){
X509存储添加crl(cts、itmp->crl);
计数++;
}
}
sk_X509_信息_流行_免费(inf,X509信息_免费)//清理
无生物素(cbio)//清理

另一个响应使用了
X509\u STORE\u add\u cert
,该响应的票数较高,但不正确。这个答案是一种在内存中执行
SSL\u CTX\u加载\u验证\u位置的方法,但不加载服务器证书链。对该评论的答复还表明,它不起作用

以下代码是基于OpenSSL中该函数的实现的
SSL\u CTX\u use\u certificate\u chain\u file
的内存加载实现:

bool load_cert_chain_from_shared_mem(SSL_CTX *context, const char *cert_buffer)
{
    BIO *cbio = BIO_new_mem_buf((void*)cert_buffer, -1);
    if (!cbio)
        return false;

    X509_INFO *itmp;
    int i, count = 0, type = X509_FILETYPE_PEM;
    STACK_OF(X509_INFO) *inf = PEM_X509_INFO_read_bio(cbio, NULL, NULL, NULL);

    if (!inf)
    {
        BIO_free(cbio);
        return false;
    }

    /* Iterate over contents of the PEM buffer, and add certs. */
    BOOL first = TRUE;
    for (i = 0; i < sk_X509_INFO_num(inf); i++) {
        itmp = sk_X509_INFO_value(inf, i);
        if (itmp->x509)
        {
            /* First cert is server cert. Remaining, if any, are intermediate certs. */
            if (first)
            {
                first = FALSE;

                /*
                 * Set server certificate. Note that this operation increments the
                 * reference count, which means that it is okay for cleanup to free it.
                 */
                if (!SSL_CTX_use_certificate(context, itmp->x509))
                    goto Error;

                if (ERR_peek_error() != 0)
                    goto Error;

                /* Get ready to store intermediate certs, if any. */
                SSL_CTX_clear_chain_certs(context);
            }
            else
            {
                /* Add intermediate cert to chain. */
                if (!SSL_CTX_add0_chain_cert(context, itmp->x509))
                    goto Error;

                /*
                 * Above function doesn't increment cert reference count. NULL the info
                 * reference to it in order to prevent it from being freed during cleanup.
                 */
                itmp->x509 = NULL;
            }
        }
    }

    sk_X509_INFO_pop_free(inf, X509_INFO_free);
    BIO_free(cbio);

    return true;

Error:
    sk_X509_INFO_pop_free(inf, X509_INFO_free);
    BIO_free(cbio);

    return false;
}
bool从共享内存加载证书链(SSL\u CTX*上下文,const char*证书缓冲区)
{
BIO*cbio=BIO_new_mem_buf((void*)证书缓冲区,-1);
如果(!cbio)
返回false;
X509_信息*itmp;
int i,count=0,type=X509\u FILETYPE\u PEM;
堆栈(X509\u INFO)*inf=PEM\u X509\u INFO\u read\u bio(cbio,NULL,NULL,NULL);
如果(!inf)
{
无生物素(cbio);
返回false;
}
/*迭代PEM缓冲区的内容,并添加证书*/
BOOL first=TRUE;
对于(i=0;ix509)
{
/*第一个证书是服务器证书。剩余的证书(如果有)是中间证书*/
如果(第一)
{
第一个=假;
/*
*设置服务器证书。请注意,此操作会增加
*引用计数,这意味着清理可以释放它。
*/
如果(!SSL\u CTX\u使用\u证书(上下文,itmp->x509))
转到错误;
如果(ERR_peek_error()!=0)
转到错误;
/*准备好存储中间证书(如果有)*/
SSL_CTX_clear_chain_证书(上下文);
}
其他的
{
/*将中间证书添加到链*/
如果(!SSL\u CTX\u add0\u chain\u cert(上下文,itmp->x509))
转到错误;
/*
*上述函数不增加证书引用计数。请将信息设为NULL
*引用它,以防止在清理过程中释放它。
*/
itmp->x509=NULL;
}
}
}
sk_X509_信息_流行_免费(inf,X509信息_免费);
无生物素(cbio);
返回true;
错误:
sk_X509_信息_流行_免费(inf,X509信息_免费);
无生物素(cbio);
返回false;
}

“我希望从内存中读取证书信息,这样我就不必打开证书文件了”-你能澄清一下吗?不知道你在这里是什么意思。代码首先在哪里获得证书?我现在随身携带证书文件。服务器必须使用它们。通常的做法是为OpenSSL提供证书文件的文件名。OpenSSL将在内部处理剩余的事情。但是我不能直接发送证书文件。我必须将它们硬编码到源代码中。这就是要求。因此,我正在研究将证书放在内存缓冲区中的选项,并以某种方式使OpenSSL使用该证书信息。您能否指定使用一些示例代码执行的操作?证书SSL上下文可以从内存中创建,但是如果您可以通过一些代码共享您想要实现的内容,这将非常有用。您不应该忘记相应地释放分配的缓冲区。非常感谢@oliver zendel,它完美地完成了这项工作:)但是,我后来遇到了一个错误,因此我在最后移动了行“BIO_free(cbio);”。我在curl中的CURLOPT_SSL_CTX_函数回调中使用了您的代码来读取带有2个证书的PEM文件。感谢Kervala,我更改了代码片段以确保;)我不知道这是否是假设的,或者我是否遗漏了什么,但除非我在调用此代码之前先添加“主”证书(如回答中所述),否则调用代码不会提供任何证书,因此SSL握手失败。请注意,仅应以这种方式添加受信任的证书。而非行政长官的锁链
bool load_cert_chain_from_shared_mem(SSL_CTX *context, const char *cert_buffer)
{
    BIO *cbio = BIO_new_mem_buf((void*)cert_buffer, -1);
    if (!cbio)
        return false;

    X509_INFO *itmp;
    int i, count = 0, type = X509_FILETYPE_PEM;
    STACK_OF(X509_INFO) *inf = PEM_X509_INFO_read_bio(cbio, NULL, NULL, NULL);

    if (!inf)
    {
        BIO_free(cbio);
        return false;
    }

    /* Iterate over contents of the PEM buffer, and add certs. */
    BOOL first = TRUE;
    for (i = 0; i < sk_X509_INFO_num(inf); i++) {
        itmp = sk_X509_INFO_value(inf, i);
        if (itmp->x509)
        {
            /* First cert is server cert. Remaining, if any, are intermediate certs. */
            if (first)
            {
                first = FALSE;

                /*
                 * Set server certificate. Note that this operation increments the
                 * reference count, which means that it is okay for cleanup to free it.
                 */
                if (!SSL_CTX_use_certificate(context, itmp->x509))
                    goto Error;

                if (ERR_peek_error() != 0)
                    goto Error;

                /* Get ready to store intermediate certs, if any. */
                SSL_CTX_clear_chain_certs(context);
            }
            else
            {
                /* Add intermediate cert to chain. */
                if (!SSL_CTX_add0_chain_cert(context, itmp->x509))
                    goto Error;

                /*
                 * Above function doesn't increment cert reference count. NULL the info
                 * reference to it in order to prevent it from being freed during cleanup.
                 */
                itmp->x509 = NULL;
            }
        }
    }

    sk_X509_INFO_pop_free(inf, X509_INFO_free);
    BIO_free(cbio);

    return true;

Error:
    sk_X509_INFO_pop_free(inf, X509_INFO_free);
    BIO_free(cbio);

    return false;
}