如何通过CryptoAPI将证书从Windows证书存储区导出为Base64字符串

时间:2013-02-09 19:57:40

标签: delphi certificate cryptoapi

我已经按照C#代码执行了我在主题中要求的内容:

public static void ExportCertificatesToFile(string FileName)
{
    stringBuilder builder = new StringBuilder();

    X509Store storeMy = new X509Store(StoreName.My);
    storeMy.Open(OpenFlags.ReadOnly);

    foreach (X509Certificate2 cert in storeMy.Certificates)
    {
        builder.AppendLine("-----BEGIN CERTIFICATE-----");   
              builder.AppendLine(Convert.ToBase64String(cert.Export(X509ContentType.Cert),  Base64FormattingOptions.InsertLineBreaks));
        builder.AppendLine("-----END CERTIFICATE-----");
    }

    storeMy.Close();

    File.WriteAllText(FileName, builder.ToString());
}

正是我想用Delphi使用CryptoAPI(JwaWinCrypt.pas) 我试过以下代码:

procedure TForm1.Button1Click(Sender: TObject);
var
  hStore: HCERTSTORE;
  CertContext: PCertContext;
  pszString: PAnsiChar;
  pchString: Cardinal;
begin
  hStore := CertOpenSystemStore(0, PChar('MY'));

  try
    CertContext := CertEnumCertificatesInStore(hStore, nil);
    while CertContext <> nil do
    begin
      pszString := '';
      pchString := 0;
      CryptBinaryToString(CertContext.pbCertEncoded, CertContext.cbCertEncoded,  CRYPT_STRING_BASE64, pszString, pchString);

      ShowMessage(StrPas(pszString));

      CertContext := CertEnumCertificatesInStore(hStore, CertContext);
    end;
  finally
    CertCloseStore(hStore, 0);
  end;
end;

问题是ShowMessage什么都没显示,字符串是空的。 有人知道我做错了吗?

1 个答案:

答案 0 :(得分:1)

CryptBinaryToString的文档说明了pszString参数。

  

指向接收转换后的字符串的缓冲区的指针。要计算必须分配以保存返回字符串的字符数,请将此参数设置为NULL。该函数将在pcchString指向的值中放置所需数量的字符,包括终止NULL字符。

您必须分配缓冲区,以便API函数可以填充它。你没有这样做。为了继续,您必须仔细阅读文档并遵守API的要求。

所以你需要调用这样的函数:

szString: AnsiString;
....
chString := 0;
CryptBinaryToString(CertContext.pbCertEncoded, CertContext.cbCertEncoded,  
    CRYPT_STRING_BASE64, nil, chString);
SetLength(szString, chString-1);
CryptBinaryToString(CertContext.pbCertEncoded, CertContext.cbCertEncoded,  
    CRYPT_STRING_BASE64, PAnsiChar(szString), chString);

您还应该检查CryptBinaryToString的返回值以检测故障。为简洁起见,我省略了它。

我还假设你的是ANSI Delphi。我认为是因为您使用了PAnsiChar