Подпис върху PDF не забранява по-късни промени; Той фиксира байтов диапазон, а инкрементална актуализация добавя нови байтове след него, така че подписът остава математически валиден, докато документът придобива ново съдържание; Дали това съдържание е приемливо е политически въпрос, а DocMDP е мястото, където авторът заявява политиката: изобщо без промени, само попълване на формуляри и подписване, или тези плюс анотации; Прилагането ѝ означава класифициране на това, което действително е променило, което е това, което прави AnalyzeModifications; Насочете го към по-ранна ревизия, после прочетете GetModificationLevel за общата присъда и accessors за отделните находки за нивото, номера на обекта и описанието на всяка разлика
С това на място прилагането на DocMDP се свива до сравнение: дали изчисленото ниво е на или под нивото, което политиката позволява
Защо се очаква подписаният PDF да се променя
Три легитимни случая и те покриват по-голямата част от това, което ще видите; Втори подписващ добавя своя подпис; Получател попълва полетата на формуляр, които авторът е оставил отворени; И дългосрочен validation материал се добавя: OCSP отговори и CRL, записани в document security store на документа, така че подписът остава проверим, след като респондерите са си отишли; Последният не е просто позволен, той е това, което добре управляван архив прави с подписани документи нарочно
Така че „файлът порасна след подписването“ не носи информация; Въпросът винаги е какво е добавено, а отговорът трябва да идва от сравняване на състояния на документа, а не от наблюдение на байтове; Самата механика на добавянето е разгледана в статията за инкрементална актуализация
Класифицирайте по формата на обекта, не по пътя, който го е произвел
Класификаторът гледа какво обектът е след промяната, не кое библиотечно извикване го е създало; Това е нарочно, защото анализът върви върху файлове, произведени от друг софтуер, където няма наличен път на извикване за инспектиране
Разпознават се четири форми; Document security store и validation-related information речници, cross-reference stream обекти, catalog metadata записа и signature речници, носещи байтов диапазон, са материал за дългосрочен архив; Обект, носещ едновременно field тип и field стойност, е попълване на формуляр; Обект, чийто тип е annotation, или чийто subtype е един от изброените в ISO 32000-2 Table 168, е промяна на анотация; Всичко останало е некласифицирано
Премахванията се третират по-строго от добавянията; Премахнат обект е whitelisted само когато обектът на старата страна е самият той архивен материал, което покрива нормалния случай на security store, заменен с по-нов; Всяко друго премахване е некласифицирано, защото изтриването на съдържание от подписан документ не е нещо, което ниво на разрешение упълномощава; Разликите на ниво документ са още по-строги: промяна в броя на страниците отива направо в некласифицирано без инспектиране на отделни обекти, тъй като никое DocMDP ниво не позволява добавяне или премахване на страници
Whitelist-ът греши в посока отказ
Това е дизайн правилото, което управлява всяко гранично решение; Промяна, погрешно класифицирана като позволена, е подпис, който валидира върху съдържание, което авторът никога не е упълномощил; Промяна, погрешно класифицирана като некласифицирана, е документ, който бива маркиран и прегледан от човек; Тези две грешки не са симетрични, така че whitelist-ът остава тесен и неразпознати форми падат в некласифицирано, вместо да се гадае
Това има практическа последица, която си заслужава да се предвиди: файлове от необичайни производители понякога ще докладват некласифицирани промени, които при инспекция са безобидни; Правилният отговор е да се погледне детайлът на находката и номерът на обекта, а не да се разшири whitelist-ът, защото whitelist, който расте, за да замълчи отделни доклади, спира да е контрол за сигурността
uses
PDFlibrary, PDFlibCompare;
var
Pdf: TPDFlib;
I, Level: Integer;
begin
Pdf := TPDFlib.Create(nil);
try
Pdf.LoadFromFile('contract-countersigned.pdf', '');
if Pdf.AnalyzeModifications('contract-as-signed.pdf', '') < 0 then
raise Exception.Create('the earlier revision could not be loaded');
// TPLModificationLevel е подреден mlNone, mlLTAUpdates, mlFormFilling,
// mlAnnotations, mlUnclassified; getter-ът връща неговия ordinal
Level := Pdf.GetModificationLevel;
// Прилагането на DocMDP вече е едно сравнение с политиката
if Level > Ord(mlFormFilling) then
for I := 0 to Pdf.GetModificationFindingCount - 1 do
Report.Add(Format('object %d, level %d: %s',
[Pdf.GetModificationFindingObjNum(I),
Pdf.GetModificationFindingLevel(I),
Pdf.GetModificationFindingDetail(I)]));
finally
Pdf.Free;
end;
end;
Общото ниво е максимумът върху всички находки, което е единствената защитима агрегация: документ, съдържащ деветдесет и девет archive добавяния и една некласифицирана промяна, е една некласифицирана промяна
Отдолу: fingerprints, не криптографски хешове
Сравняващият engine, който CompareWith излага и върху който е изграден анализът на модификации, идентифицира обектите по fingerprint на тяхното нормализирано тяло, използвайки некриптографски 64-битов hash вместо SHA-256; Това е обмислен избор; Това, от което се нуждае структурното сравнение, е детерминизъм: едно и също тяло на обект винаги трябва да произвежда един и същ fingerprint в рамките на изпълнение; То не се нуждае от устойчивост на сблъсъци, защото нападател, който контролира и двете страни на сравнението, вече е спечелил по други средства, а плащането за пълен криптографски hash върху всеки обект в документ с милион обекти е реална цена без полза
Две правила за нормализация имат повече значение от избора на hash; Indirect references се свиват до placeholder токен, вместо да бъдат разширявани в реферираното съдържание: разширяването би копирало тялото на споделен обект във всеки рефериращ, така че една малка редакция на споделен font descriptor би обезсмислила fingerprint на всеки обект, който го достига, а докладът би станал нечетим; И номерата на обектите сами са изключени от fingerprint, защото преписване може да преномерира обекти, без да променя нищо семантично
Съпоставянето после тича в два прохода, подравнявайки по fingerprint първо и сдвоявайки остатъка по номер на обекта, за да идентифицира промени, а не добавяне плюс премахване; Евтините проверки идват първо навсякъде: разлика в броя на страниците се докладва, преди каквото и да е обхождане на обекти да започне
Капан: самосравнението не е гарантирано идентично
Естественият първи тест за diff engine е да сравни файл със самия него и да assert-не, че резултатът е идентичен; Това предположение не важи тук, а причината е поучителна; Публичният load път и по-ниското ниво на document load път не конфигурират декодирането идентично, така че същият файл, зареден през двата маршрута, може да произведе fingerprints, различни за някои обекти; Engine-ът не е грешен; двете зареждания наистина произвеждат различни in-memory състояния
Вместо да бъдат насилвани двата пътя заедно, семантиката на сравнението е заявена тясно: анализът сравнява текущото състояние на документа с по-ранна ревизия и докладва идентично само когато двете fingerprint множества съвпадат точно; Това е въпросът, който потребителите действително задават и той не изисква двата loader-а да са взаимозаменяеми; Когато проектирате функция за сравнение, дефинирането какво значи „същото“ е по-голяма част от работата, отколкото самото изчисление
Къде да се използва
Две места; В доклад за валидация, до проверката на подписи, така че прегледащият вижда не само дали подписът е криптографски непокътнат, а и какво се е случило с документа след това; страната на подписите е разгледана в PAdES подписване и валидация; И във входна порта, където документ, пристигащ отвън, се проверява спрямо копието, което сте изпратили, така че върнат договор с добавена анотация се третира различно от такъв с редактирана страница
Една уговорка за обхвата; Този анализ ви казва какво се е променило между две ревизии на същата документна линия; Той не ви казва дали видимото съдържание е подвеждащо, дали appearance stream на form поле съответства на стойността му или дали текст, скрит под overlay, все още е наличен в content stream; Това се нуждае от отделно третиране, а страната за премахване на съдържание е разгледана в статията за истинско redaction; Входните точки за анализ и сравнение са документирани на продуктовата страница losLab PDF Developer Library