EPdfKeychainError = class(Exception);
TPdfKeychainSignerProvider = class(TInterfacedObject, IPadesSignerProvider)
function BackendName: string;
function Resolve(const Options: TPadesSignerOptions): TPadesResolvedSigner;
end;
TPdfKeychainCmsVerifier = class(TInterfacedObject, IPdfCmsVerifier)
function BackendName: string;
function VerifyDetached(const CmsDer: TBytes; Segment1: Pointer; Segment1Length: Cardinal; Segment2: Pointer; Segment2Length: Cardinal; const Options: TPdfCmsVerifyOptions): TPdfCmsVerifyResult;
function VerifyAttached(const CmsDer: TBytes; const Options: TPdfCmsVerifyOptions): TPdfCmsVerifyResult;
end;
function KeychainAvailable: Boolean;
function KeychainMissingSymbols: string;
function KeychainVerificationAvailable: Boolean;
function ConfigureKeychainSignerProvider: IPadesSignerProvider;
function ConfigureKeychainCmsVerifier: IPdfCmsVerifier;
FPdfCryptoMac — криптографический бэкенд macOS, используемый FPdfCrypto и FPdfCms, и он охватывает обе половины интеграции с платформой: подпись PAdES через идентичность Keychain и проверку CMS через системный декодер CMS и оценку доверия. Security.framework и CoreFoundation загружаются и разрешаются по имени во время выполнения, а не линкуются, поэтому модуль компилируется для любой целевой платформы и во время выполнения сообщает, доступны ли сервисы платформы на самом деле
Со стороны подписи TPdfKeychainSignerProvider реализует IPadesSignerProvider. Его метод Resolve перечисляет идентичности Keychain, выбирает ту, чей сертификат совпадает с отпечатком SHA-1 из TPadesSignerOptions, читает DER сертификата и ссылку на соответствующий закрытый ключ и возвращает TPadesResolvedSigner, чей ICmsSigner подписывает CMS signed attributes через Security.framework, так что закрытый ключ никогда не покидает Keychain. Запрошенная в опциях схема дополнения согласуется с тем, что ключ реально умеет, а параметры RSASSA-PSS те же, что выдают другие бэкенды, поэтому документ, подписанный на macOS, несёт идентичный AlgorithmIdentifier. ConfigureKeychainSignerProvider создаёт провайдера и устанавливает его активным бэкендом подписи PAdES, возвращая зарегистрированный интерфейс
Со стороны проверки TPdfKeychainCmsVerifier реализует IPdfCmsVerifier поверх CMSDecoder и SecTrust. VerifyDetached соединяет два подписанных диапазона байт по обе стороны от разрыва подписи в отсоединённое содержимое, которое ожидает декодер, и затем проверяет значение CMS против него; VerifyAttached проверяет значение CMS, которое несёт собственное содержимое, — именно это нужно токену метки времени. Оба возвращают TPdfCmsVerifyResult, где отдельно сообщаются статус подписи, статус доверия и статус отзыва, опционально собираются сертификат подписанта и вычисленная цепочка, и оба учитывают настройки отзыва, онлайн-получения и контрольных точек в TPdfCmsVerifyOptions. ConfigureKeychainCmsVerifier создаёт верификатор и устанавливает его активным бэкендом проверки CMS
Действительность подписи и доверие к сертификату остаются независимыми результатами, поэтому подлинная подпись под недоверенной или самоподписанной цепочкой остаётся отличимой от подделанного содержимого
Для присоединённого токена RFC 3161 ограниченный разбор DER передаёт исходные инкапсулированные октеты TSTInfo нативному декодеру, не меняя их тип содержимого или signed attributes. Обычный проход проверки CMS исключает неподписанные атрибуты из своего нативного ввода, поэтому автоматическая обработка меток времени не может подменить собственную целостность или результат цепочки внешней подписи. Этот проход не проверяет встречные подписи и другие неподписанные атрибуты; ValidatePadesTrust отдельно проверяет каждый исходный токен метки времени, отпечаток сообщения, роль сертификата TSA, доверие и результат отзыва
Передайте путь к файлу Keychain в TPdfKeychainSignerProvider.Create, чтобы ограничить поиск идентичностей этим Keychain через локальный для запроса список поиска, затем зарегистрируйте провайдера через ConfigurePadesSignerProvider. Пустой путь использует текущую область поиска пользователя. Открытие или поиск в выбранном Keychain не изменяет Keychain по умолчанию, список поиска пользователя или системную конфигурацию доверия; некорректные пути и недоступные символы поиска по области возбуждают EPdfKeychainError
Resolve также экспортирует доступную цепочку издателей сертификата подписи через автономный, локальный для запроса поиск сертификатов и нативное построение цепочки. Сертификаты-кандидаты ограничены 4096 элементами, 1 МиБ каждый и 16 МиБ суммарно; построенная цепочка ограничена 32 сертификатами, включая лист, который возвращается отдельно от ChainCertDer. Экспорт данных сертификата не устанавливает доверие и не ставит якорь доверия, а недоступного издателя нельзя синтезировать
| Function | Description |
|---|---|
KeychainAvailable | Возвращает True, когда Security.framework и CoreFoundation загружены и все символы, необходимые для подписи, разрешены |
KeychainMissingSymbols | Возвращает имена, которые не удалось разрешить, разделённые пробелами, либо пустую строку, если всё связалось |
ConfigureKeychainSignerProvider | Создаёт TPdfKeychainSignerProvider, устанавливает его бэкендом подписи PAdES и возвращает как IPadesSignerProvider |
TPdfKeychainSignerProvider.Create | Выбирает необязательный существующий файл Keychain для поиска идентичностей по области, отклоняя встроенные символы NUL и пути длиннее 4096 строковых элементов |
TPdfKeychainSignerProvider.BackendName | Возвращает идентификатор бэкенда, сообщаемый для провайдера подписи |
TPdfKeychainSignerProvider.Resolve | Сопоставляет TPadesSignerOptions с идентичностями Keychain и возвращает TPadesResolvedSigner с подписантом, DER сертификата и цепочкой |
| Function | Description |
|---|---|
KeychainVerificationAvailable | Возвращает True, когда разрешены символы декодера CMS, политики доверия и оценки доверия |
ConfigureKeychainCmsVerifier | Создаёт TPdfKeychainCmsVerifier, устанавливает его бэкендом проверки CMS и возвращает как IPdfCmsVerifier |
ConfigureKeychainTrustAnchors | Клонирует явные якоря DER для каждой последующей оценки доверия, дополняя системные якоря без изменения Keychain; лимиты — 64 сертификата, 4 МиБ каждый и 16 МиБ суммарно, а пустой массив очищает их |
ConfigureKeychainOcspResponses | Клонирует явные свидетельства OCSP в DER для нативной оценки Security.framework; лимиты — 8 ответов, 1 МиБ каждый и 4 МиБ суммарно, а пустой массив очищает их |
TPdfKeychainCmsVerifier.BackendName | Возвращает идентификатор бэкенда, сообщаемый для бэкенда проверки |
TPdfKeychainCmsVerifier.VerifyDetached | Проверяет отсоединённое значение CMS против двух сегментов содержимого, принадлежащих вызывающему коду и описываемых Segment1, Segment1Length, Segment2 и Segment2Length, используя переданные TPdfCmsVerifyOptions |
TPdfKeychainCmsVerifier.VerifyAttached | Проверяет присоединённое значение CMS, которое несёт собственное подписанное содержимое, используя переданные TPdfCmsVerifyOptions |
| Type | Members and purpose |
|---|---|
EPdfKeychainError | Исключение, возникающее, когда Security.framework недоступен, когда ни одна идентичность Keychain не совпадает с запрошенным подписантом или когда вызов подписи платформы завершается ошибкой |
TPdfKeychainSignerProvider | Бэкенд подписи PAdES, реализующий IPadesSignerProvider, с BackendName и Resolve |
TPdfKeychainCmsVerifier | Бэкенд проверки CMS, реализующий IPdfCmsVerifier, с BackendName, VerifyDetached и VerifyAttached |
KeychainAvailable и KeychainVerificationAvailable сообщают о подписи и проверке отдельно, потому что двум половинам нужны разные символы фреймворков, поэтому система может связать одну половину и не связать другуюKeychainMissingSymbols называет каждый символ, который не удалось разрешить — именно это отличает отсутствующий фреймворк от проблемы связывания: пустой результат означает, что всё связалось, результат с путями фреймворков означает, что фреймворки не загрузились, а результат с отдельными точками входа означает, что фреймворки загрузились, но какое-то имя не разрешилосьKeychainAvailable и KeychainVerificationAvailable, пустой KeychainMissingSymbols и возбуждают EPdfKeychainError из функций настройкиTPadesSignerOptions не несёт отпечатка сертификата, выбирается первая пригодная идентичность в Keychain — это подходит для теста, но не для производственной подписиpcvsUnsupported, сохраняя нативную диагностику, вместо сообщения о действительной или недействительной целостности. Для таких значений используйте верификатор CMS OpenSSL; диагностика смешанных подписантов сохраняет отдельный результат алгоритма для каждого подписантаFreshOcspResponse, затем нативные проверки подписи ответчика, полномочий и сертификата. Допустимое расхождение — 300 секунд, а producedAt и thisUpdate ограничены возрастом в один деньOnlineRetrieval=False отключает нативное получение из сети доверия. Нативная онлайн-оценка Security.framework следует поведению платформы; UrlRetrievalTimeoutMs не даёт на этом бэкенде ограниченного транспортного дедлайна OpenSSLCollectSignerDiagnostics=True возвращает отдельные снимки подписантов, ограниченные MaxSignerCount и жёстким пределом 64. Возвращаемые данные сертификатов ограничены 4 МиБ на сертификат и 64 МиБ суммарно; неполный сбор сообщает pcvsIndeterminateSignerDiagnosticsStatus=pcvsValid означает, что сбор завершён, включая вердикты по сбойным подписантам. RevocationError несёт нативный статус Security.framework, а RevocationCertificate на этом бэкенде остаётся пустым