原文鏈接:http://support.microsoft.com/kb/925521/zh-cn
創建一個命令行程序集更新證書。若要執行此操作,請執行以下步驟。
Microsoft 提供的編程示例僅用於說明,沒有任何明示或暗示的擔保。這包括但不限於適銷性或特定用途適用性的暗示保證。本文假定您熟悉所演示的編程語言和用於創建和調試過程的工具。Microsoft 的支持工程師可以幫助解釋某個特定過程的功能。但是,他們不會修改這些示例以提供額外的功能或構建過程以滿足您的特定要求。
- 在 Visual Studio 2005 中,在文件菜單上,單擊新建,然後單擊項目。
- 單擊Visual C++ Win32 控制檯應用程序中的名稱框中,鍵入RenewCert和,然後單擊確定。
- 在Win32 應用程序嚮導對話框中,單擊完成。
- 在 RenewCert.cpp 文件中,將現有代碼替換爲以下代碼:
#include "stdafx.h" void ReadPFXFile(LPCWSTR fileName, CRYPT_DATA_BLOB *pPFX) { HANDLE hCertFile = NULL; DWORD cbRead = 0; DWORD dwFileSize = 0, dwFileSizeHi = 0; hCertFile = CreateFile(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); dwFileSize = GetFileSize(hCertFile, &dwFileSizeHi); pPFX->pbData = (BYTE *) CryptMemAlloc(dwFileSize*sizeof(BYTE)); pPFX->cbData = dwFileSize; ReadFile(hCertFile, pPFX->pbData, pPFX->cbData, &cbRead, NULL); CloseHandle(hCertFile); } void GetPrivateKey(CRYPT_DATA_BLOB pPFX, LPCWSTR szPassword, HCRYPTPROV *hCPContext) { HCERTSTORE hCertStore = NULL; PCCERT_CONTEXT hCertContext = NULL; DWORD dwKeySpec = AT_SIGNATURE; BOOL bFreeCertKey = TRUE; hCertStore = PFXImportCertStore(&pPFX, szPassword, CRYPT_EXPORTABLE); hCertContext = CertEnumCertificatesInStore(hCertStore, NULL); CryptAcquireCertificatePrivateKey(hCertContext, 0, NULL, hCPContext, &dwKeySpec, &bFreeCertKey); CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG); } void PrintContainerName(HCRYPTPROV hCPContext) { DWORD containerNameLen = 0; CHAR *szContainerName = NULL; CryptGetProvParam(hCPContext, PP_CONTAINER, NULL, &containerNameLen, 0); szContainerName = (CHAR *)CryptMemAlloc(sizeof(BYTE)*containerNameLen); CryptGetProvParam(hCPContext, PP_CONTAINER, (BYTE *)szContainerName, &containerNameLen, 0); printf("This certificate's container name is: %s", szContainerName); } void MakeNewCert(HCRYPTPROV hCPContext, LPCWSTR szCertName, LPCWSTR szPassword, CRYPT_DATA_BLOB *pPFX) { CERT_NAME_BLOB certNameBlob = {0,NULL}; PCCERT_CONTEXT hCertContext = NULL; SYSTEMTIME certExpireDate; HCERTSTORE hTempStore = NULL; CertStrToName(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, szCertName, CERT_OID_NAME_STR, NULL, NULL, &certNameBlob.cbData, NULL); certNameBlob.pbData = (BYTE *)CryptMemAlloc(sizeof(BYTE)*certNameBlob.cbData); CertStrToName(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, szCertName, CERT_OID_NAME_STR, NULL, certNameBlob.pbData, &certNameBlob.cbData, NULL); GetSystemTime(&certExpireDate); certExpireDate.wYear += 5; hCertContext = CertCreateSelfSignCertificate(hCPContext, &certNameBlob, 0, NULL, NULL, NULL, &certExpireDate, NULL); hTempStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, NULL, CERT_STORE_CREATE_NEW_FLAG, 0); CertAddCertificateContextToStore(hTempStore, hCertContext, CERT_STORE_ADD_NEW, NULL); PFXExportCertStoreEx(hTempStore, pPFX, szPassword, NULL, EXPORT_PRIVATE_KEYS); pPFX->pbData = (BYTE *)CryptMemAlloc(sizeof(BYTE)*pPFX->cbData); PFXExportCertStoreEx(hTempStore, pPFX, szPassword, NULL, EXPORT_PRIVATE_KEYS); CryptMemFree(certNameBlob.pbData); CertCloseStore(hTempStore, CERT_CLOSE_STORE_FORCE_FLAG); CertFreeCertificateContext(hCertContext); } void WritePFX(CRYPT_DATA_BLOB pPFX, LPCWSTR szOutputFile) { HANDLE hOutputFile = NULL; DWORD cbWritten = 0; hOutputFile = CreateFile(szOutputFile, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_SEQUENTIAL_SCAN, NULL); WriteFile(hOutputFile, pPFX.pbData, pPFX.cbData, &cbWritten, NULL); CloseHandle(hOutputFile); } int _tmain(int argc, _TCHAR* argv[]) { LPCWSTR szCertFileName = NULL; CRYPT_DATA_BLOB pPFX; LPCWSTR szPassword = NULL; HCRYPTPROV hCPContext = NULL; LPCWSTR szCertName = L"CN=NewCert"; CRYPT_DATA_BLOB pPfxOutputBlob = {0,NULL}; LPCWSTR szOutFile = NULL; // Parse the command line. if(argc == 1) { printf("renewcert <PFX File> <new cert filename> <new cert friendly name> [optional]<password>\n"); printf("Example: renewcert oldcert.pfx newcert.pfx \"CN=MyNewCert\" MySuperSecretPassword"); return 0; } if(argc >= 2) szCertFileName = argv[1]; if(argc >= 5) szPassword = argv[4]; // Uncomment this block to add <new cert filename> and <new cert friendly name> as parameters // NOTE: <new cert friendly name> must be of format "CN=<name>" if(argc >= 3) szOutFile = argv[2]; if(argc >= 4) szCertName = argv[3]; ReadPFXFile(szCertFileName, &pPFX); GetPrivateKey(pPFX, szPassword, &hCPContext); //PrintContainerName(hCPContext); // Uncomment this section to make a new PFX rather than just printing the container name. // Make sure you also uncomment the command line parameter section above. MakeNewCert(hCPContext, szCertName, szPassword, &pPfxOutputBlob); WritePFX(pPfxOutputBlob, szOutFile); // Clean up. CryptReleaseContext(hCPContext, 0); CryptMemFree(pPfxOutputBlob.pbData); CryptMemFree(pPFX.pbData); return 0; }
- 在 stdafx.h 文件中,將現有代碼替換爲以下代碼:
// stdafx.h : include file for standard system include files, // or project specific include files that are used frequently, but // are changed infrequently. // #pragma once #define WIN32_LEAN_AND_MEAN // Exclude rarely used material from Windows headers. #include <stdio.h> #include <tchar.h> #include <windows.h> #include <wincrypt.h>
- 在項目菜單上,單擊屬性以打開屬性頁中的爲此項目。
- 展開鏈接器節點,然後單擊輸入。
- 在空白窗口右側的附加依賴項,請單擊,然後單擊省略號按鈕 (...) 在附加依賴項對話框中打開。
- 在空白的窗口中,鍵入Crypt32.lib,然後單擊確定。
- 單擊應用,然後單擊確定以關閉屬性頁。
- 在生成菜單中,單擊生成解決方案。
- 生成解決方案後,執行以下命令,以更新證書,請:
renewcert <OldCertificate>.pfx <NewCertificate>.pfx \"CN=<NewCertificateName>\" <Password>