PFXExportCertStoreEx API 未将私钥导出到 PFX 文件

如何解决PFXExportCertStoreEx API 未将私钥导出到 PFX 文件

我正在尝试使用 PFXExportCertStoreEx API 为自签名证书及其相应的私钥创建 pfx 文件。

自签名证书导出到 pfx,但私钥不导出到 pfx 文件。我将私钥的导出策略设置如下。

 export_policy = NCRYPT_ALLOW_EXPORT_FLAG | NCRYPT_ALLOW_PLAINTEXT_EXPORT_FLAG;

我尝试了如下不同的方法,在两种情况下 PFXExportCertStoreEx API 都失败,错误代码为 0x80090016。

方法 1: 调用 API CertSetCertificateContextProperty 和 CERT_KEY_PROV_INFO_PROP_ID 作为提到的 here

方法 2: 使用 CERT_NCRYPT_KEY_HANDLE_PROP_ID 和 keyHandle 调用 API CertSetCertificateContextProperty

我正在使用以下代码创建私钥、自签名证书并导出到 pfx 文件。

#include <stdio.h>
#include <windows.h>
#include <wincrypt.h>
#include <strsafe.h>
#include<ncrypt.h>
#pragma comment (lib,"crypt32")
#pragma comment(lib,"ncrypt.lib") 

int main()
{
    CreateCert();
    return 0;
}

int CreateCert(void)
{
    int result = 0;
    CERT_NAME_BLOB nameBlob = {0,NULL};
    CERT_EXTENSIONS certExtensions = { 0 };
    NCRYPT_PROV_HANDLE providerHandle = { 0 };
    NCRYPT_KEY_HANDLE keyHandle = { 0 };
    PCCERT_CONTEXT certContext = NULL;
    ZeroMemory(&certExtensions,sizeof(certExtensions));
    
    CRYPT_KEY_PROV_INFO keyProvInfo;
    
    ZeroMemory(&keyProvInfo,sizeof(keyProvInfo));

    keyProvInfo.pwszContainerName = L"Label1_Key";
    keyProvInfo.dwProvType = PROV_RSA_FULL;
    keyProvInfo.dwFlags = CRYPT_MACHINE_KEYSET;
    keyProvInfo.dwKeySpec = AT_SIGNATURE;

    if (NCryptOpenStorageProvider(&providerHandle,MS_KEY_STORAGE_PROVIDER,0) != 0)
    {
        printf("\nFailed NCryptOpenStorageProvider");
        goto fail;
    }

    if (NCryptCreatePersistedKey(providerHandle,&keyHandle,BCRYPT_RSA_ALGORITHM,L"Label1_Key",AT_SIGNATURE,NCRYPT_OVERWRITE_KEY_FLAG) != 0)
    {
        printf("\nFailed NCryptCreatePersistedKey");
        goto fail;
    }
    NTSTATUS status = -1;
    DWORD dwBits = 2048;
    status = NCryptSetProperty(
                    keyHandle,NCRYPT_LENGTH_PROPERTY,(PBYTE) &dwBits,sizeof(dwBits),NCRYPT_PERSIST_FLAG
                );
    if( status )
    {
        printf("\nFailed NCryptSetProperty to key size");
        goto fail;
    }
    DWORD export_policy = NCRYPT_ALLOW_EXPORT_FLAG | NCRYPT_ALLOW_PLAINTEXT_EXPORT_FLAG;
    if (NCryptSetProperty(
                keyHandle,NCRYPT_EXPORT_POLICY_PROPERTY,(PBYTE)&export_policy,sizeof(export_policy),NCRYPT_PERSIST_FLAG))
    {
        printf("\nFailed NCryptSetProperty to export policy");
        goto fail;
    }
    
    if (NCryptFinalizeKey(keyHandle,NCRYPT_SILENT_FLAG) != 0)
    {
        printf("\nFailed NCryptFinalizeKey");
        goto fail;
    }

    if (!CertStrToNameW(X509_ASN_ENCODING,L"CN=Label1",NULL,nameBlob.pbData,&nameBlob.cbData,NULL))
    {
        printf("\nFailed CertStrToNameW 1");
        goto fail;
    }

    nameBlob.pbData = malloc(nameBlob.cbData);
    if (!CertStrToNameW(X509_ASN_ENCODING,NULL))
    {
        printf("\nFailed CertStrToNameW 2");
        goto fail;
    }
    SYSTEMTIME EndTime;
    SYSTEMTIME StartTime;
    GetSystemTime(&StartTime);
    GetSystemTime(&EndTime);

    EndTime.wYear += 10;
    
    certContext = CertCreateSelfSignCertificate(
                    keyHandle,&nameBlob,&keyProvInfo,&StartTime,&EndTime,&certExtensions
                );
    if (!certContext)
    {
        printf("\nFailed CertCreateSelfSignCertificate");
        goto fail;
    }
    CRYPT_DATA_BLOB  Friendly_Name_Blob;
    ZeroMemory( &Friendly_Name_Blob,sizeof(Friendly_Name_Blob) );
    

    Friendly_Name_Blob.pbData = (BYTE *)L"Temp Name";
    Friendly_Name_Blob.cbData =  (wcslen((LPWSTR)Friendly_Name_Blob.pbData)+1) * sizeof(WCHAR);;
    if(CertSetCertificateContextProperty(
                certContext,CERT_FRIENDLY_NAME_PROP_ID,&Friendly_Name_Blob))
    {
        printf("A name has been set.\n");
    }
    else
    {
        printf("The display name was not set.\n");
    }
    
    CRYPT_KEY_PROV_INFO kpi;
    ZeroMemory(&kpi,sizeof(kpi) );
    kpi.pwszContainerName = L"Label1_Key";
    kpi.dwProvType = PROV_RSA_FULL;
    kpi.dwKeySpec = AT_KEYEXCHANGE;
    kpi.dwFlags = CRYPT_MACHINE_KEYSET;

    if(CertSetCertificateContextProperty(certContext,CERT_KEY_PROV_INFO_PROP_ID,(const void *)&kpi))
    {
        printf("Key set.\n");
    }
    else
    {
        printf("Key set faile\n");
        goto fail;
    }
    
    // if(CertSetCertificateContextProperty(certContext,// CERT_NCRYPT_KEY_HANDLE_PROP_ID,// 0,// (const void *)&keyHandle))
    // {
        // printf("Key set.\n");
    // }
    // else
    // {
        // printf("Key set faile\n");
        // goto fail;
    // }
    
    
    PCCERT_CONTEXT pCertContext = NULL;
    HCERTSTORE hMemStore = NULL;
    CRYPT_DATA_BLOB Blob;
    hMemStore = CertOpenStore(CERT_STORE_PROV_MEMORY,(HCRYPTPROV_LEGACY)NULL,CERT_STORE_CREATE_NEW_FLAG,NULL);
    if(!hMemStore) 
    {
        printf("Error creating memory certificate store: %d\n",GetLastError());
        goto fail;
    }
    
    if(!CertAddCertificateContextToStore(hMemStore,certContext,CERT_STORE_ADD_ALWAYS,NULL)) 
    {
        printf("Error adding certificate to memory certificate store: %d\n",GetLastError());
        goto fail;
    }

    ZeroMemory(&Blob,sizeof(CRYPT_DATA_BLOB));
    if (!PFXExportCertStoreEx(hMemStore,&Blob,L"mypassword",EXPORT_PRIVATE_KEYS | 
                                REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY | 
                                PKCS12_INCLUDE_EXTENDED_PROPERTIES |
                                REPORT_NO_PRIVATE_KEY)) 
    {
        printf("Error sizing blob: 0x%x \n",GetLastError());
        goto fail;
    }

    Blob.pbData = (PBYTE)HeapAlloc(GetProcessHeap(),Blob.cbData);
    if(!Blob.pbData)
    {
        printf("Error allocating data blob: %d\n",GetLastError());
        goto fail;
    }

    if(!PFXExportCertStoreEx(hMemStore,EXPORT_PRIVATE_KEYS |
                                REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY |
                                PKCS12_INCLUDE_EXTENDED_PROPERTIES |
                                REPORT_NO_PRIVATE_KEY))
    {
        printf("Error exporting certificates: %d\n",GetLastError());
        goto fail;
    }
    HANDLE hFile = NULL;
    DWORD dwBytesWritten = 0;
    hFile = CreateFile("Certificate.pfx",GENERIC_WRITE,CREATE_ALWAYS,0);
    if(hFile == INVALID_HANDLE_VALUE) {
        printf("Error creating output file: %d\n",GetLastError());
        goto fail;
    }

    if(!WriteFile(hFile,Blob.pbData,Blob.cbData,&dwBytesWritten,0)) {
        printf("Error writing to file: %d\n",GetLastError());
        goto fail;
    }

    if (dwBytesWritten != Blob.cbData) {
        printf("Number of bytes written does not match requested!\n");
        goto fail;
    }
    printf("\nCertificate Created Successfully");
fail:
    free(nameBlob.pbData);
    if (providerHandle)
        NCryptFreeObject(providerHandle);
    if (certContext)
        CertFreeCertificateContext(certContext);
    if(hMemStore) 
        CertCloseStore(hMemStore,0);
    if(pCertContext) 
        CertFreeCertificateContext(pCertContext);
    if(hFile != INVALID_HANDLE_VALUE)
    {
        CloseHandle(hFile);
    }

    if(Blob.pbData) HeapFree(GetProcessHeap(),Blob.pbData);
    return result;

}

让我知道如何将私钥与自签名证书一起导出到 pfx 文件。

提前致谢。

解决方法

把上面的代码改成下面这样,私钥和证书就成功导出到pfx文件了。

调用 NCryptOpenStorageProvider 之前。

 memset(&keyProvInfo,sizeof(keyProvInfo));
 keyProvInfo.pwszContainerName = L"Label_key1";;
 keyProvInfo.pwszProvName = MS_KEY_STORAGE_PROVIDER;
 keyProvInfo.dwProvType = 0;
 keyProvInfo.dwKeySpec = 0;

调用 CertCreateSelfSignCertificate 后添加以下代码

if(CertSetCertificateContextProperty(certContext,CERT_NCRYPT_KEY_HANDLE_PROP_ID,(const void *)&keyHandle))
 {
 printf("Key set.\n");
 }
 else
 {
 printf("Key set faile\n");
 goto fail;
 }

查看下面的完整代码。

 #include <stdio.h>
 #include <windows.h>
 #include <wincrypt.h>
 #include <strsafe.h>
 #include<ncrypt.h>
 #pragma comment (lib,"crypt32")
 #pragma comment(lib,"ncrypt.lib") 
    
 int main()
 {
  CreateCert();
  return 0;
 }
    
 int CreateCert(void)
 {
  int result = 0;
  CERT_NAME_BLOB nameBlob = {0,NULL};
  CERT_EXTENSIONS certExtensions = { 0 };
  NCRYPT_PROV_HANDLE providerHandle = { 0 };
  NCRYPT_KEY_HANDLE keyHandle = { 0 };
  PCCERT_CONTEXT certContext = NULL;
  ZeroMemory(&certExtensions,sizeof(certExtensions));
    
  CRYPT_KEY_PROV_INFO keyProvInfo;
    
     memset(&keyProvInfo,sizeof(keyProvInfo));
     keyProvInfo.pwszContainerName = L"Label_key1";;
     keyProvInfo.pwszProvName = MS_KEY_STORAGE_PROVIDER;
     keyProvInfo.dwProvType = 0;
     keyProvInfo.dwKeySpec = 0;
    
  if (NCryptOpenStorageProvider(&providerHandle,MS_KEY_STORAGE_PROVIDER,0) != 0)
  {
  printf("\nFailed NCryptOpenStorageProvider");
  goto fail;
  }
    
  if (NCryptCreatePersistedKey(providerHandle,&keyHandle,BCRYPT_RSA_ALGORITHM,keyProvInfo.pwszContainerName,AT_SIGNATURE,NCRYPT_OVERWRITE_KEY_FLAG) != 0)
  {
  printf("\nFailed NCryptCreatePersistedKey");
  goto fail;
  }
  NTSTATUS status = -1;
  DWORD dwBits = 2048;
  status = NCryptSetProperty(
  keyHandle,NCRYPT_LENGTH_PROPERTY,(PBYTE) &dwBits,sizeof(dwBits),NCRYPT_PERSIST_FLAG
  );
  if( status )
  {
  printf("\nFailed NCryptSetProperty to key size");
  goto fail;
  }
  DWORD export_policy = NCRYPT_ALLOW_EXPORT_FLAG | NCRYPT_ALLOW_PLAINTEXT_EXPORT_FLAG;
  if (NCryptSetProperty(
  keyHandle,NCRYPT_EXPORT_POLICY_PROPERTY,(PBYTE)&export_policy,sizeof(export_policy),NCRYPT_PERSIST_FLAG))
  {
  printf("\nFailed NCryptSetProperty to export policy");
  goto fail;
  }
    
  if (NCryptFinalizeKey(keyHandle,NCRYPT_SILENT_FLAG) != 0)
  {
  printf("\nFailed NCryptFinalizeKey");
  goto fail;
  }
    
  if (!CertStrToNameW(X509_ASN_ENCODING,L"CN=Label1",NULL,nameBlob.pbData,&nameBlob.cbData,NULL))
  {
  printf("\nFailed CertStrToNameW 1");
  goto fail;
  }
    
  nameBlob.pbData = malloc(nameBlob.cbData);
  if (!CertStrToNameW(X509_ASN_ENCODING,NULL))
  {
  printf("\nFailed CertStrToNameW 2");
  goto fail;
  }
     SYSTEMTIME EndTime;
     SYSTEMTIME StartTime;
  GetSystemTime(&StartTime);
     GetSystemTime(&EndTime);
    
     EndTime.wYear += 10;
    
  certContext = CertCreateSelfSignCertificate(
  keyHandle,&nameBlob,&keyProvInfo,&StartTime,&EndTime,&certExtensions
  );
  if (!certContext)
  {
  printf("\nFailed CertCreateSelfSignCertificate");
  goto fail;
  }
    
  if(CertSetCertificateContextProperty(certContext,(const void *)&keyHandle))
  {
  printf("Key set.\n");
  }
  else
  {
  printf("Key set faile\n");
  goto fail;
  }
    
  CRYPT_DATA_BLOB  Friendly_Name_Blob;
  ZeroMemory( &Friendly_Name_Blob,sizeof(Friendly_Name_Blob) );
    
    
  Friendly_Name_Blob.pbData = (BYTE *)L"Temp Name";
  Friendly_Name_Blob.cbData =  (wcslen((LPWSTR)Friendly_Name_Blob.pbData)+1) * sizeof(WCHAR);;
  if(CertSetCertificateContextProperty(
  certContext,CERT_FRIENDLY_NAME_PROP_ID,&Friendly_Name_Blob))
  {
  printf("A name has been set.\n");
  }
  else
  {
  printf("The display name was not set.\n");
  }
    
    
  PCCERT_CONTEXT pCertContext = NULL;
  HCERTSTORE hMemStore = NULL;
  CRYPT_DATA_BLOB Blob;
  hMemStore = CertOpenStore(CERT_STORE_PROV_MEMORY,(HCRYPTPROV_LEGACY)NULL,CERT_STORE_CREATE_NEW_FLAG,NULL);
  if(!hMemStore) 
  {
  printf("Error creating memory certificate store: %d\n",GetLastError());
  goto fail;
  }
    
  if(!CertAddCertificateContextToStore(hMemStore,certContext,CERT_STORE_ADD_ALWAYS,NULL)) 
  {
  printf("Error adding certificate to memory certificate store: %d\n",GetLastError());
  goto fail;
  }
    
  ZeroMemory(&Blob,sizeof(CRYPT_DATA_BLOB));
  if (!PFXExportCertStoreEx(hMemStore,&Blob,L"mypassword",EXPORT_PRIVATE_KEYS | 
  REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY | 
  PKCS12_INCLUDE_EXTENDED_PROPERTIES |
  REPORT_NO_PRIVATE_KEY)) 
  {
  printf("Error sizing blob: 0x%x \n",GetLastError());
  goto fail;
  }
    
  Blob.pbData = (PBYTE)HeapAlloc(GetProcessHeap(),Blob.cbData);
  if(!Blob.pbData)
  {
  printf("Error allocating data blob: %d\n",GetLastError());
  goto fail;
  }
    
  if(!PFXExportCertStoreEx(hMemStore,EXPORT_PRIVATE_KEYS |
  REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY |
  PKCS12_INCLUDE_EXTENDED_PROPERTIES |
  REPORT_NO_PRIVATE_KEY))
  {
  printf("Error exporting certificates: %d\n",GetLastError());
  goto fail;
  }
  HANDLE hFile = NULL;
  DWORD dwBytesWritten = 0;
  hFile = CreateFile("Certificate.pfx",GENERIC_WRITE,CREATE_ALWAYS,0);
     if(hFile == INVALID_HANDLE_VALUE) {
         printf("Error creating output file: %d\n",GetLastError());
         goto fail;
     }
    
     if(!WriteFile(hFile,Blob.pbData,Blob.cbData,&dwBytesWritten,0)) {
         printf("Error writing to file: %d\n",GetLastError());
         goto fail;
     }
    
     if (dwBytesWritten != Blob.cbData) {
         printf("Number of bytes written does not match requested!\n");
         goto fail;
     }
  printf("\nCertificate Created Successfully");
 fail:
  free(nameBlob.pbData);
  if (providerHandle)
  NCryptFreeObject(providerHandle);
  if (certContext)
  CertFreeCertificateContext(certContext);
  if(hMemStore) 
  CertCloseStore(hMemStore,0);
  if(pCertContext) 
  CertFreeCertificateContext(pCertContext);
  if(hFile != INVALID_HANDLE_VALUE)
  {
  CloseHandle(hFile);
  }
    
  if(Blob.pbData) HeapFree(GetProcessHeap(),Blob.pbData);
  return result;
    
 }

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)&gt; insert overwrite table dwd_trade_cart_add_inc &gt; select data.id, &gt; data.user_id, &gt; data.course_id, &gt; date_format(
错误1 hive (edu)&gt; insert into huanhuan values(1,&#39;haoge&#39;); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive&gt; show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 &lt;configuration&gt; &lt;property&gt; &lt;name&gt;yarn.nodemanager.res