How to export certificate from Windows certificate store via CryptoAPI as Base64 string

倖福魔咒の 提交于 2019-12-23 19:29:36

问题


i've got following C# code for doing what i asked for in subject:

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());
}

Exactly that i want to archieve with Delphi using CryptoAPI (JwaWinCrypt.pas) I've tried following code:

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;

Problem is that ShowMessage shows nothing, the string is empty. Has someone an idea what i do wrong?


回答1:


The documentation for CryptBinaryToString says this about the pszString parameter.

A pointer to a buffer that receives the converted string. To calculate the number of characters that must be allocated to hold the returned string, set this parameter to NULL. The function will place the required number of characters, including the terminating NULL character, in the value pointed to by pcchString.

You are obliged to allocate the buffer so that the API function can populate it. You are failing to do so. In order to proceed you must read the documentation carefully and abide by the requirements of the API.

So you need to call the function like this:

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);

You should also check the return value of CryptBinaryToString to detect failures. I omitted that for brevity.

I'm also assuming that yours is an ANSI Delphi. I assumed that because you used PAnsiChar.



来源:https://stackoverflow.com/questions/14790930/how-to-export-certificate-from-windows-certificate-store-via-cryptoapi-as-base64

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!