Как экспортировать сертификат из хранилища сертификатов 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
,