我有Microsoft的SST文件,我需要将其添加到java信任库。
问题是Microsoft提供的所有工具,将SST文件中的证书添加到Windows应用商店,因此很难从SST文件中获取PEM文件。如果我运行certmgr.exe(而不是certmgr.msc),我可以获得公钥和所有但没有证书(在pem或der中),我看到一堆VB脚本和powershell将它们使用SST文件加载到System.Security中。 Cryptography.X509Certificates.X509Certificate2Collection对象,但仍无法找到输出为PEM(或der)格式化证书的方法。
有什么建议吗?
取值
答案 0 :(得分:1)
您可以使用CAPI将SST文件作为证书存储打开,然后枚举文件中的证书。以下代码执行此操作,并使用证书的SHA1哈希作为文件名将DER格式的证书输出到文件。第一个参数是输出文件夹。剩下的一个或多个参数是您的SST文件。
#include <stdio.h>
#include <tchar.h>
#include "windows.h"
#include "wincrypt.h"
#include "atlbase.h"
#include <iostream>
#include <sstream>
#include <iomanip>
#include <algorithm>
std::string GetHexRepresentation(const unsigned char * Bytes, size_t Length)
{
std::ostringstream os;
os.fill('0');
os<<std::hex;
for(const unsigned char * ptr=Bytes;ptr<Bytes+Length;ptr++)
os<<std::setw(2)<<(unsigned int)*ptr;
std::string retval = os.str();
std::transform(retval.begin(), retval.end(),retval.begin(), ::toupper);
return retval;
}
BOOL WriteToFileWithHashAsFilename(PCCERT_CONTEXT pPrevCertContext, TCHAR* outputDir)
{
#undef RETURN
#define RETURN(rv) \
{ \
if( hHash ) CryptDestroyHash(hHash); \
if( hProv ) CryptReleaseContext(hProv, 0); \
return rv; \
}
HCRYPTPROV hProv = 0;
HCRYPTHASH hHash = 0;
BYTE byteFinalHash[20];
DWORD dwFinalHashSize = 20;
if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
{
std::cout << "CryptAcquireContext failed: " << GetLastError() << std::endl;
RETURN(FALSE);
}
if (!CryptCreateHash(hProv, CALG_SHA1, 0, 0, &hHash))
{
std::cout << "CryptCreateHash failed: " << GetLastError() << std::endl;
RETURN(FALSE);
}
if (!CryptHashData(hHash, pPrevCertContext->pbCertEncoded, pPrevCertContext->cbCertEncoded, 0))
{
std::cout << "CryptHashData failed: " << GetLastError() << std::endl;
RETURN(FALSE);
}
if (!CryptGetHashParam(hHash, HP_HASHVAL, byteFinalHash, &dwFinalHashSize, 0))
{
std::cout << "CryptGetHashParam failed: " << GetLastError() << std::endl;
RETURN(FALSE);
}
std::string strHash = GetHexRepresentation(byteFinalHash, dwFinalHashSize);
std::wostringstream filename;
filename << outputDir << strHash.c_str() << ".der" <<std::ends;
FILE* f = _wfopen(filename.str().c_str(), L"wb+");
if(!f)
{
std::wcout << "Failed to open file for writing: " << filename.str().c_str() << std::endl;
RETURN(FALSE);
}
int bytesWritten = fwrite(pPrevCertContext->pbCertEncoded, 1, pPrevCertContext->cbCertEncoded, f);
fclose(f);
if(bytesWritten != pPrevCertContext->cbCertEncoded)
{
std::cout << "Failed to write file" << std::endl;
RETURN(FALSE);
}
RETURN(TRUE);
}
//usage: DumpCertsFromSst <output directory> <SST file 1> ... <SST file n>
int _tmain(int argc, _TCHAR* argv[])
{
SECURITY_ATTRIBUTES sa;
memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES));
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle = FALSE;
if(argc < 3)
{
std::cout << "At least two arguments must be provided: outputDirectory sstFile1 ... sstFileN etc" << std::endl;
return 0;
}
TCHAR* outputDir = argv[1];
for(int ii = 2; ii < argc; ++ii)
{
HANDLE hFile = NULL;
HCERTSTORE hFileStore = NULL;
LPCWSTR pszFileName = argv[ii];
//Open file
hFile = CreateFile(pszFileName, GENERIC_READ, 0, &sa, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if(INVALID_HANDLE_VALUE == hFile)
{
std::wcout << "Failed to open file: " << pszFileName << std::endl;
continue;
}
else
{
std::wcout << "Processing file: " << pszFileName << std::endl;
}
//open certificate store
hFileStore = CertOpenStore(CERT_STORE_PROV_FILE, 0, NULL, CERT_STORE_READONLY_FLAG, hFile);
if(NULL == hFileStore)
{
CloseHandle(hFile);
continue;
}
int count = 0;
PCCERT_CONTEXT pPrevCertContext = NULL;
pPrevCertContext = CertEnumCertificatesInStore(hFileStore, pPrevCertContext);
while(NULL != pPrevCertContext)
{
if(WriteToFileWithHashAsFilename(pPrevCertContext, outputDir))
++count;
pPrevCertContext = CertEnumCertificatesInStore(hFileStore, pPrevCertContext);
}
std::wcout << "Wrote " << count << " certificates" << std::endl;
CloseHandle(hFile);
CertCloseStore(hFileStore, 0);
}
return 1;
}