Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/14.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++ 从windows证书存储导出PFX文件_C++_Windows_Openssl_Ssl Certificate_Cryptoapi - Fatal编程技术网

C++ 从windows证书存储导出PFX文件

C++ 从windows证书存储导出PFX文件,c++,windows,openssl,ssl-certificate,cryptoapi,C++,Windows,Openssl,Ssl Certificate,Cryptoapi,我们的应用程序使用OpenSSL保护客户端设备和服务器之间的通信。证书由客户CA生成,我们必须将服务器证书和私钥上载到基于Windows操作系统的计算机 到目前为止,我们指导客户将包含服务器证书和私钥的PEM文件保存在服务器文件系统的特定目录中,并从该目录上传应用程序。最近,客户要求我们从本地windows证书商店读取PFX证书 我可以想到两个选项,它们都结合使用CAPI库从WCS导出PFX文件(根据友好的名称),序列化文件,然后使用OpenSSL API上载文件 第一个选项将其保存为服务器文件

我们的应用程序使用OpenSSL保护客户端设备和服务器之间的通信。证书由客户CA生成,我们必须将服务器证书和私钥上载到基于Windows操作系统的计算机

到目前为止,我们指导客户将包含服务器证书和私钥的PEM文件保存在服务器文件系统的特定目录中,并从该目录上传应用程序。最近,客户要求我们从本地windows证书商店读取PFX证书

我可以想到两个选项,它们都结合使用CAPI库从WCS导出PFX文件(根据友好的名称),序列化文件,然后使用OpenSSL API上载文件

第一个选项将其保存为服务器文件系统上的临时文件,然后使用OpenSSL API像以前一样读取

第二个选项使用内存,即传递指针,而不是使用临时文件

我的团队花了很多时间搜索web(主要是堆栈溢出)和尝试代码片段,但没有找到有效的解决方案。我知道在将文件导入WCS期间,私钥应该是可导出的

当我尝试以下简单导出证书并将其保存到文件的代码时(基于MS示例代码的选项#1的前半部分),它只向文件写入一个字符

我错过了什么?我需要重新格式化证书吗

你知道什么是错误的,什么是正确的方法吗

可以用这种方法提取私钥吗

提前感谢您的评论

//-----------------------------------------

#pragma comment(lib, "crypt32.lib")

#include <stdio.h>
#include <windows.h>
#include <Wincrypt.h>
#define MY_ENCODING_TYPE  (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
void MyHandleError(char *s);

void main(void)
{
//-------------------------------------------------------------------
// Declare and initialize variables.
HCERTSTORE         hSystemStore;
PCCERT_CONTEXT     pCertContext = NULL;
Char pszStoreName[256] = "root";
char               pszNameString[256] = "CARootTest"; 
BYTE              pbElement[3000];
DWORD              cbElement;
//-------------------------------------------------------------------
// Open a system certificate store.
if(hSystemStore = CertOpenSystemStore(
    0,
    pszStoreName))
{
  printf("The %s system store is open. Continue.\n", pszStoreName );
}
else
{
  MyHandleError("The first system store did not open.");
}
//-------------------------------------------------------------------
// Get a certificate that has the desired friendly name. 
if(pCertContext=CertFindCertificateInStore(
      hSystemStore,
      MY_ENCODING_TYPE,             // Use X509_ASN_ENCODING
      0,                            // No dwFlags needed 
      CERT_NAME_FRIENDLY_DISPLAY_TYPE,        // Find a certificate
      pszNameString, // The Unicode string to be found
                                    // in a certificate's subject
      NULL))                        // NULL for the first call 
{
  printf("The %s certificate was found. \n", pszNameString);
}
else
{
   MyHandleError("Could not find the %s certificate.");
}
//-------------------------------------------------------------------
// Find out how much memory to allocate for the serialized element.

if(CertSerializeCertificateStoreElement(
    pCertContext,      // The existing certificate.
    0,                 // Accept default for dwFlags, 
    NULL,              // NULL for the first function call.
    &cbElement))       // Address where the length of the 
                       // serialized element will be placed.
{
     printf("The length of the serialized string is %d.\n",
         cbElement);
}
else
{
     MyHandleError("Finding the length of the serialized "
         "element failed.");
}
//-------------------------------------------------------------------
// Allocate memory for the serialized element.

if(pbElement = (BYTE*)malloc(cbElement+1))
{
     printf("Memory has been allocated. Continue.\n");
}
else
{
     MyHandleError("The allocation of memory failed.");
}
//-------------------------------------------------------------------
// Create the serialized element from a certificate context.

if(CertSerializeCertificateStoreElement(
    pCertContext,        // The certificate context source for the 
                         // serialized element.
    0,                   // dwFlags. Accept the default.
    pbElement,           // A pointer to where the new element will
                         // be stored.
    &cbElement))         // The length of the serialized element,
{
     printf("The encoded element has been serialized. \n");
}
else
{
     MyHandleError("The element could not be serialized.");
}
//-------------------------------------------------------------------
//  pbElement could be written to a file ??

FILE *fp;
errno_t err;
if ((err = fopen_s(&fp, "cert.p12", "wb")) != 0)
    printf("File was not opened\n");
else
    fprintf(fp, "%s", pbElement);
fclose(fp);

//-------------------------------------------------------------------
// Free memory.

free(pbElement);
CertCloseStore(hSystemStore,0);
printf("The program ran without error to the end.\n");
} // End of main

//-------------------------------------------------------------------
void MyHandleError(char *s)
{
    fprintf(stderr,"An error occurred in running the program. \n");
    fprintf(stderr,"%s\n",s);
    fprintf(stderr, "Error number %x.\n", GetLastError());
    fprintf(stderr, "Program terminating. \n");
    exit(1);
} // End of MyHandleError
//-----------------------------------------
#pragma注释(lib,“crypt32.lib”)
#包括
#包括
#包括
#定义MY_ENCODING_类型(PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
无效MyHandleError(字符*s);
真空总管(真空)
{
//-------------------------------------------------------------------
//声明和初始化变量。
HCERTSTORE hsystore;
PCCERT_CONTEXT pCertContext=NULL;
Char pszStoreName[256]=“根目录”;
char pszNameString[256]=“CARootTest”;
字节pbElement[3000];
德沃德元素;
//-------------------------------------------------------------------
//打开系统证书存储。
if(hssystemstore=CertOpenSystemStore(
0,
pszStoreName)
{
printf(“已打开%s系统存储。继续。\n”,pszStoreName);
}
其他的
{
MyHandleError(“第一个系统存储未打开”);
}
//-------------------------------------------------------------------
//获取具有所需友好名称的证书。
如果(pCertContext=CertFindCertificateInstaller(
系统商店,
MY_ENCODING_TYPE,//使用X509_ASN_编码
0,//不需要dwFlags
证书名称\u友好\u显示\u类型,//查找证书
pszNameString,//要找到的Unicode字符串
//在证书的主题中
NULL))//第一次调用为NULL
{
printf(“找到%s证书。\n”,pszNameString);
}
其他的
{
MyHandleError(“找不到%s证书。”);
}
//-------------------------------------------------------------------
//找出要为序列化元素分配多少内存。
如果(证书)重新发布(
pCertContext,//现有证书。
0,//接受dwFlags的默认值,
NULL,//第一个函数调用为NULL。
&cbElement))//地址,其中
//将放置序列化的元素。
{
printf(“序列化字符串的长度为%d。\n”,
Cb元素);
}
其他的
{
MyHandleError(“查找序列化文件的长度”
“元素失败。”);
}
//-------------------------------------------------------------------
//为序列化元素分配内存。
if(pbElement=(字节*)malloc(cbElement+1))
{
printf(“内存已分配。继续。\n”);
}
其他的
{
MyHandleError(“内存分配失败”);
}
//-------------------------------------------------------------------
//从证书上下文创建序列化元素。
如果(证书)重新发布(
pCertContext,//证书的证书上下文源
//序列化元素。
0,//dwFlags。接受默认值。
pbElement,//指向新元素所在位置的指针
//被储存。
&cbElement))//序列化元素的长度,
{
printf(“编码元素已序列化。\n”);
}
其他的
{
MyHandleError(“元素无法序列化”);
}
//-------------------------------------------------------------------
//pbElement是否可以写入文件??
文件*fp;
错误没有错误;
如果((err=fopen_s(&fp,“cert.p12”,“wb”))!=0)
printf(“文件未打开\n”);
其他的
fprintf(fp,“%s”,pbElement);
fclose(fp);
//-------------------------------------------------------------------
//释放内存。
自由元素(PBE);
CertCloseStore(hSystemStore,0);
printf(“程序运行到最后没有错误。\n”);
}//主管道末端
//-------------------------------------------------------------------
无效MyHandleError(字符*s)
{
fprintf(stderr,“运行程序时出错。\n”);
fprintf(标准字符,“%s\n”,s);
fprintf(stderr,“错误号%x.\n”,GetLastError());
fprintf(stderr,“程序终止。\n”);
出口(1);
}//MyHandleError的结尾

为什么不使用
PFXExportCertStoreEx
在pfx文件中保存证书?我们的应用程序作为服务运行,并使用PFXExportCertStore所需的密码“此函数创建的pfx BLOB受密码保护。”。我们不希望用户输入,硬编码密码应为Sequerity-breech。此外,如果我正确理解此命令,则会导出存储中的所有证书,而不仅仅是所需的证书。是的