PDF, който току-що сте подписали, е B-B подпис и нищо повече; Той доказва кой е подписал и че байтовете не са се местили, но не носи доказателство, че сертификатът на подписващия е бил валиден в момента на подписване, така че валидатор години по-късно трябва да търси revocation данни, които може вече да не съществуват; Затварянето на тази дупка означава писане на OCSP отговори и CRL в document-level Document Security Store, а в HotPDF това е едно извикване: PopulatePAdESLTVEvidence обхожда всеки зареден подпис, извежда revocation заявките от набора сертификати, изпълнява ги чрез transport, който вие доставяте, и записва изтегления материал плюс CMS веригата в DSS; Той връща броя на подписите, чиито доказателства са кацнали, или минус едно, когато документът изобщо няма поле за подпис
Дизайн решението, което си заслужава да се разбере, преди да го използвате, е, че библиотеката никога не отваря socket; Всеки байт, който пристига от мрежата, пристига през callback, който вие сте написали; Това не е предпазливост заради самата нея; това е единственият начин тази функция да работи вътре в средите, които действително изискват дългосрочна валидация
Защо библиотеката отказва да прави собствения си HTTP?
Защото местата, които изискват B-LT подписи, са местата, където на библиотека не може да се вярва с мрежата; Услуги за подписване тичат зад автентикиращи proxy-та с корпоративни root-ове; Air-gapped подписващи слоеве нямат маршрут до responder и трябва да бъдат хранени с кеширани доказателства; Audit режими изискват всяка изходяща заявка да бъде логвана от приложението, а не закопана в зависимост; И тестови набори се нуждаят от детерминистични отговори, което е невъзможно, ако библиотеката звъни навън сама
Transport-ът е обикновена функция референция с фиксирана форма, така че политиката остава ваша; HotPDF ви подава request запис, описващ точно какво да се изтегли, включително content типа и таван за размера на отговора, а вие връщате байтовете плюс статус
function FetchEvidence(const Request: THPDFSignatureEvidenceRequest;
Attempt: Integer; CancellationToken: THPDFCancellationToken;
out Response: TBytes; out RetryAfterMS: Cardinal;
out ErrorMessage: UnicodeString): THPDFSignatureEvidenceTransportStatus;
begin
RetryAfterMS := 0;
try
// Request.Kind казва дали това е OCSP POST или CRL GET;
// Request.ContentType и Request.Body са вече подготвени,
// а Request.MaxResponseBytes е таванът, който трябва да спазвате
Response := HttpExchange(Request.URI, Request.ContentType,
Request.Body, Request.MaxResponseBytes);
Result := setsSucceeded;
except
on E: Exception do
begin
ErrorMessage := E.Message;
// setsRetry позволява на retry политиката да се отдръпне;
// използвайте setsPermanentFailure за 404 или лош URL
Result := setsRetry;
end;
end;
end;
// Надграждане с едно извикване от B-B към B-LT за всеки подпис
// в заредения файл
var
Pdf: THotPDF;
Upgraded: Integer;
begin
Pdf := THotPDF.Create(nil);
try
Pdf.BeginIncrementalUpdate('signed.pdf');
Upgraded := Pdf.PopulatePAdESLTVEvidence(FetchEvidence,
THPDFSignatureEvidenceRetryPolicy.Default);
if Upgraded > 0 then
// Append-only запис: байтовете, които съществуващите подписи
// покриват, се запазват дословно
Pdf.SaveIncrementalUpdate('signed-lt.pdf');
finally
Pdf.Free;
end;
end;
Отказите са за подпис, не за документ; Responder, който отнема timeout за един подписващ, прескача материала на този подписващ и оставя остатъка от прохода непокътнат, което е поведението, което искате в пакет: частични доказателства бият прекъснато изпълнение, а return стойността ви казва колко подписа действително са се подобрили
Веригата, която CMS забрави да включи
Revocation проверката се нуждае от сертификата на издателя и изненадващ брой подписващи стекове пропускат intermediates от CMS контейнера; Маршрутът за възстановяване е разширението Authority Information Access, access метод 1.3.6.1.5.5.7.48.2, който рекламира URL, откъдето сертификатът на издателя може да бъде изтеглен; HPDFFetchAIAIntermediates обхожда тези URL-и през същия transport, парсва DER от всеки отговор и връща само сертификатите, които CMS вече не носеше, ключувани по DER hash, така че дубликати и цикли не могат да се въртят
Два детайла решават дали това работи срещу реални сертификатни авторитети; Първият е кодирането: CA крайните точки сервират сертификата като гол DER приблизително толкова често, колкото го сервират PEM облечен и няма надежден content тип, който да ги разграничи; Здравата сонда е текстова, после структурна; Потърсете маркера -----BEGIN CERTIFICATE-----, съблечете бронята и декодирайте base64, ако е налична, и в двата пътя потвърдете, че първият байт на резултата е $30, DER тагът за SEQUENCE; Вторият е дълбочината: изтеглен intermediate може сам да рекламира AIA URL за собствения си издател, така че обходът добавя нови кандидати към опашката и доизгражда вериги, които са с две-три стъпки къси; Това трябва да бъде ограничено, за което е параметърът MaxFetch
Какво е seed стойност на подпис и защо се проваля мълшиво?
Seed стойност е ограничение, което авторът на документа прикрепя към поле за подпис, за да каже на подписващия какъв вид подпис е приемлив: кой SubFilter, кой digest алгоритъм, кои причини, коя минимална PDF версия, дали revocation информация трябва да бъде вграждана; Тя живее в речник /SV на полето и е дефинирана в ISO 32000-1 §12.7.5.5; HotPDF я записва с AttachPAdESSeedValue и я проверява с CheckLoadedSignatureSeedValue, която връща True, когато полето е без ограничения или всяко налично ограничение минава, а при False назова първото провалящо се ограничение чрез output параметър, който можете да сложите направо в съобщение за грешка
Механизмът, който прави seed стойностите лесни за объркване, е записът с флагове /Ff, описан в §12.7.5.5.3; Установен бит маркира неговото ограничение като задължително: разминаване е грешка и подписващият трябва да откаже; Изчистен бит маркира същото ограничение като предпочитание: стойността филтрира какво UI-то трябва да предлага и нищо повече; Оттам следват два капана; Първо, /Ff живее вътре в речника /SV, не върху widget анотацията, така че код, който чете field-ниво /Ff, получава празен отговор завинаги и заключава, че нищо не е наложено; Второ, разпределението на битовете не е проста поредица едно, две, четири, осем; в HotPDF writer-ът излъчва 2 за SubFilter, 4 за MinVersion, 32 за AddRevInfo и 64 за DigestMethod; Четец, който предполага последователни битове, декодира всяко ограничение като опционално и минава всеки тест освен онзи, който има значение
var
Violation: AnsiString;
begin
// Попитайте полето дали профилът, с който ще подписваме, е позволен
if not Pdf.CheckLoadedSignatureSeedValue(0, 'ETSI.CAdES.detached',
'SHA256', 'Approved for payment', 1, Violation) then
raise Exception.Create('Signature field rejects this profile: ' +
String(Violation));
// Ограничението е удовлетворено: продължете с подписващия проход
end;
Тестът, който извади оригиналния декодиращ дефект, не беше позитивен тест; Той беше предположението, че наложено разминаване трябва да бъде отхвърлено и е единственият вид тест, който може да хване този клас дефекти: декодер, четещ грешния речник или грешните битови позиции, произвежда „нищо не е нарушено“ за всеки вход, което изглежда точно като правилно поведение, докато нарочно не нарушите едно
Къде това стои на LTV стълбата
Четири степени и всяка се нуждае от долната; B-B е голият подпис; B-T добавя доверено времево клеймо, което фиксира времето на подписване, така че валидатор знае към кой момент да оцени revocation; B-LT добавя revocation доказателствата към DSS, което е това, което PopulatePAdESLTVEvidence автоматизира; B-LTA добавя документни времеви клейма, които се подновяват, преди предишното да отслабне, удължавайки валидността неопределено; HotPDF излага това като RenewPAdESLTATimestamp, който добавя ново времево клеймо като инкрементална ревизия и запазва всеки по-ранен подпис, времево клеймо и DSS запис недокоснати
Моделът инкрементална актуализация е единственият правилен начин да се добавят доказателства към подписан документ, защото преписването на файла би счупило байтовите диапазони, които съществуващите подписи покриват; Ако трябва да разсъждавате какво се е променило между ревизии и дали тези промени са от рода, който подпис позволява, този анализ е разгледан отделно в анализа на ревизии DocMDP и FieldMDP; Самият подписващ конвейер, включително източници на сертификати и капани с байтов ред, е в прошетката за PAdES подписване, а страната за валидация е в верифициране на подписи върху заредени документи
Едно практично предупреждение за подредбата; Събирайте доказателствата възможно най-скоро след подписването, в идеалния случай в същата задача; Responders, които могат да отговорят за сертификат, са онлайн, докато сертификатът е текущ и изчезват години по-късно, така че документ, който напуска вашия конвейер като B-B, може никога повече да не може да бъде надграден; HotPDF тича като нативен VCL компонент за Delphi и C++Builder и целият проход за доказателства е in-process, освен вашия собствен transport; поддържаните профили са изброени на продуктовата страница HotPDF Delphi PDF component