3

我有来自 Microsoft 的 SST 文件,我需要将其添加到 java 信任库。

问题是微软提供的所有工具,将 SST 文件中的证书添加到 Windows 商店,因此很难从 SST 文件中获取 PEM 文件。如果我运行 certmgr.exe(不是 certmgr.msc),我可以获得公钥和所有这些,但没有证书(pem 或 der),我看到一堆 VB 脚本和 powershell 使用 SST 文件将它们加载到 System.Security 中。 Cryptography.X509Certificates.X509Certificate2Collection 对象,但仍然找不到输出为 PEM(或 der )格式证书的方法。

有什么建议么?

小号

4

1 回答 1

1

您可以使用 CAPI 将 SST 文件作为证书存储打开,然后枚举文件中的证书。以下代码执行此操作并将 DER 形式的证书输出到使用证书的 SHA1 哈希作为文件名的文件。第一个参数是输出文件夹。剩下的一个或多个参数是您的 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;
    }
于 2013-01-29T16:06:49.153 回答