Метод THotPDF.ValidatePDFMACChain
Проверяет каждую ревизию PDF MAC от самой старой cross-reference-секции до активной ревизии и возвращает диагностику целостности по конкретной ревизии
Объявление
function ValidatePDFMACChain(const FileName: TFileName; const Password: AnsiString; out ValidationInfo: THPDFPDFMACChainValidationInfo): boolean; overload;
function ValidatePDFMACChain(const FileName: TFileName; const Password: AnsiString; const Options: THPDFPDFMACOptions; out ValidationInfo: THPDFPDFMACChainValidationInfo): boolean; overload;
Модель проверки
- Индексы ревизий нумеруются с нуля и идут от исходной ревизии к активной
- Первая ревизия, содержащая
AuthCode, становится якорем цепочки, а каждая последующая ревизия обязана содержать валидный PDF MAC - Каждый MAC проверяется по точному байтовому префиксу, который заканчивается на границе
startxrefи%%EOFэтой ревизии - Валидатор отклоняет подменённый исторический MAC, даже если MAC более новой активной ревизии остаётся валидным
KDFSaltдолжен оставаться стабильным после якоря, а сила digest не должна уменьшаться между проверенными MAC-ревизиями- Аутентифицированные значения
/Pи/Permsпроверяются по каждой ревизии, включая бит разрешения, требующий PDF MAC
Записи результата
THPDFPDFMACChainValidationInfo сообщает RevisionCount, FirstMACRevisionIndex, ValidatedRevisionCount, FailureRevisionIndex, FailureXRefOffset, покрытие разрешений, стабильность salt, монотонность digest и по одной записи THPDFPDFMACRevisionValidation на каждую ревизию
THPDFPDFMACChainFailure различает ошибки на границе ревизии, отсутствие MAC, невалидный или подменённый MAC, изменившийся KDFSalt, понижение силы digest и понижение аутентифицированных разрешений
Реализация перечисляет цепочку ревизий один раз и обновляет одно накопительное состояние cross-reference, избегая временных копий PDF и повторной индексации объектов, но сохраняя независимую криптографическую проверку каждой защищённой ревизии
Пример для Delphi
var
ChainInfo: THPDFPDFMACChainValidationInfo;
begin
if not PDF.ValidatePDFMACChain('authenticated.pdf', 'user-password',
ChainInfo) then
raise Exception.CreateFmt('Revision %d at xref %d failed: %s',
[ChainInfo.FailureRevisionIndex, ChainInfo.FailureXRefOffset,
ChainInfo.Message]);
end;
Preflight
CreatePreflightReport открывает тот же результат в виде PDFMACRevisionChain, что позволяет автоматизированным процессам отличать валидность активной ревизии от валидности всей цепочки ревизий
Если нужно проверить только активную ревизию, обратитесь к ValidatePDFMAC, а за семантикой digest-политики — к PDF MAC Algorithm Agility и профилям политики