Как экспортировать сертификат из хранилища сертификатов Windows через CryptoAPI в виде строки Base64

У меня есть следующий код 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 ответ

Решение

Документация для CryptBinaryToString говорит это о pszString параметр.

Указатель на буфер, который получает преобразованную строку. Чтобы рассчитать количество символов, которое должно быть выделено для хранения возвращаемой строки, установите для этого параметра значение NULL. Функция поместит необходимое количество символов, включая завершающий символ NULL, в значение, на которое указывает pcchString.

Вы обязаны выделить буфер так, чтобы функция 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,

Другие вопросы по тегам