标签:
原文地址:http://www.cnblogs.com/xuhaibiao/archive/2009/06/23/1509692.html
场景:用于生产环境的项目进行系统升级,在发布ClickOnce过程中发现签名已过期,现场工程师重新生成了一个签名,然后进行发布,发布完成后,所有客户端无法更新,提示签名错误。
问题:VS2005做年签名只有一年期限,所以很容易在维护期内就过期了,如果新做签名结果会造成客户端验证签名出错无法更新。
解决办法:
1、新做一个签名,使用新的签名做ClickOnce,所有客户端将原来程序删除,重新使用新的ClickOnce安装程序进行安装。
(此方法太可耻了,如果再有升级的话,可能还会有这问题,同时ClickOnce也得改名叫ClickOneYear了)。
2、利用原有签名,延长有效时间。
(中文)http://support.microsoft.com/kb/925521/zh-cn
(英文)http://support.microsoft.com/kb/925521/en-us





#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 : 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>
renewcert <OldCertificate>.pfx <NewCertificate>.pfx \"CN=<NewCertificateName>\" <Password>
更多信息
有此朋友发现过这样的问题,也知道解决办法,但如果机器上没装VC++可能操作起来也不方便,现编译完成一份,各位可以下载:
http://files.cnblogs.com/spymaster/RenewCert.rar
使用方法:到命令窗口,输入
renewcert <OldCertificate>.pfx <NewCertificate>.pfx \"CN=<NewCertificateName>\" <Password>
好了,新签名的有限期是5年。
3、项目之初就做一个长效的签名。
http://www.cnblogs.com/xuhaibiao/archive/2009/06/22/1508317.html
打开Microsoft .NET Framework 的SDK命令提示,按以下步骤操作:
1、创建一个自我签署的X.509证书(.cer)和一个.pvk私钥文件,用到makecert工具,命令如下:
makecert -r -n "CN= cncxz " -b 01/01/2005 -e 01/01/2018 -sv myselfName.pvk myselfName.cer
按提示设置私钥密码(也可以不使用密码)即可在当前目录生成相关文件
2、利用X.509证书(.cer)创建发行者证书 (.spc),用到cert2spc工具,命令如下:
cert2spc myselfName.cer myselfName.spc
3、从.pvk和.spc格式转换成.pfx格式,用到pvkimprt工具,命令如下:
pvkimprt -pfx myselfName.spc myselfName.pvk
按提示操作可导出.pfx证书,若第1步设置了私钥密码,此处需要输入验证
4、在vs项目的ClickOnce清单签名的证书设置处点击“从文件选择”浏览定位到第3步导出的.pfx证书,此处需要验证第3步中设置的证书私钥密码。
makecert工具和cert2spc工具.NET Framework自带,pvkimprt工具下载地址如下
http://download.microsoft.com/download/vba50/Utility/1.0/NT5/EN-US/pvkimprt.exe
如果以上下载链接有失效的,请到该地址下载:
http://download.csdn.net/detail/u012373717/8726827
标签:
原文地址:http://www.cnblogs.com/felixzh/p/4521521.html