При работе с HTTPS-запросами в Delphi с использованием компонентов Indy (TIdHTTP и TIdSSLIOHandlerSocketOpenSSL) разработчики часто сталкиваются с ошибками загрузки SSL-сертификатов. Одна из распространенных проблем - ошибка EIdOSSLLoadingCertError с сообщением "Could not load certificate. error:0906D06C:PEM routines:PEM_read_bio:no start line".
Причины ошибки
Основные причины возникновения ошибки "no start line":
Неправильное форматирование PEM-файлов: OpenSSL ожидает строго определенный формат для сертификатов и приватных ключей.
Наличие BOM (Byte Order Mark): При сохранении файлов в UTF-8 может добавляться BOM, который мешает корректному чтению сертификата.
Проблемы с путями к файлам: Неправильно указанные пути или отсутствие прав доступа к файлам.
Решение проблемы
1. Устранение проблемы с BOM
Основное решение - отключить запись BOM при сохранении PEM-файлов:
2. Альтернативное решение: использование TMemoryStream
Вместо сохранения во временные файлы можно использовать TMemoryStream для загрузки сертификата напрямую:
function TAPI.LoadCertificateFromMemory: TIdSSLIOHandlerSocketOpenSSL;
var
CertStream, KeyStream: TMemoryStream;
begin
if Assigned(SSLIOHandler) then
SSLIOHandler := nil;
SSLIOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
CertStream := TMemoryStream.Create;
try
KeyStream := TMemoryStream.Create;
try
// Преобразуем строки в потоки
StringToStream(const_cert, CertStream);
StringToStream(const_private_key, KeyStream);
// Устанавливаем позицию в начало потоков
CertStream.Position := 0;
KeyStream.Position := 0;
// Загружаем сертификат и ключ из потоков
SSLIOHandler.SSLOptions.CertStream := CertStream;
SSLIOHandler.SSLOptions.KeyStream := KeyStream;
// Остальные настройки
SSLIOHandler.SSLOptions.Method := sslvTLSv1_2;
SSLIOHandler.SSLOptions.SSLVersions := [sslvTLSv1_2];
SSLIOHandler.SSLOptions.Mode := sslmClient;
SSLIOHandler.SSLOptions.VerifyMode := [];
SSLIOHandler.SSLOptions.VerifyDepth := 0;
SSLIOHandler.Host := 'place.holder.com';
except
KeyStream.Free;
raise;
end;
except
CertStream.Free;
raise;
end;
Result := SSLIOHandler;
end;
procedure StringToStream(const AString: string; AStream: TStream);
var
Bytes: TBytes;
begin
Bytes := TEncoding.UTF8.GetBytes(AString);
AStream.WriteBuffer(Bytes[0], Length(Bytes));
end;
3. Проверка формата сертификата
Убедитесь, что ваши сертификаты имеют правильный формат:
function ValidatePEMFormat(const APEMString: string): Boolean;
begin
Result := (Pos('-----BEGIN CERTIFICATE-----', APEMString) > 0) and
(Pos('-----END CERTIFICATE-----', APEMString) > 0) and
(Pos('-----BEGIN PRIVATE KEY-----', APEMString) > 0) and
(Pos('-----END PRIVATE KEY-----', APEMString) > 0);
end;
Оптимизация кода для HTTP-запросов
Вот улучшенная версия метода GetToken:
function TAPI.GetToken: string;
var
IdHTTP: TIdHTTP;
Params: TStringList;
ResponseStream: TStringStream;
begin
IdHTTP := TIdHTTP.Create(nil);
try
// Настраиваем обработчик SSL
IdHTTP.IOHandler := LoadCertificate;
ResponseStream := TStringStream.Create('', TEncoding.UTF8);
try
Params := TStringList.Create;
try
Params.Add('client_id=' + FAAuthorization);
Params.Add('client_secret=' + FAAuthorizationSecret);
Params.Add('grant_type=client_credentials');
IdHTTP.Request.ContentType := 'application/x-www-form-urlencoded';
try
IdHTTP.Post(URLBasic, Params, ResponseStream);
Result := ResponseStream.DataString;
except
on E: EIdHTTPProtocolException do
LogHttpClientError(E, IdHTTP.ResponseCode, False);
on E: Exception do
raise;
end;
finally
Params.Free;
end;
finally
ResponseStream.Free;
end;
finally
IdHTTP.Free;
end;
end;
Заключение
Ошибка "no start line" при работе с SSL-сертификатами в Delphi чаще всего связана с проблемами форматирования PEM-файлов. Основные решения включают:
Отключение BOM при сохранении файлов
Использование потоков памяти вместо временных файлов
Тщательную проверку формата сертификатов
Представленные решения помогут вам успешно выполнять HTTPS-запросы с аутентификацией по SSL-сертификатам в Delphi. Всегда проверяйте формат ваших сертификатов и учитывайте особенности работы OpenSSL с различными кодировками файлов.
Контекст описывает решение ошибки "No start line" при загрузке SSL-сертификатов в Delphi с компонентами Indy, предлагая методы устранения проблем с форматированием, BOM и путями к файлам.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.