Техническа статия

AES-256 PDF криптиране в Delphi: настройка на HotPDF и клопки

Флагът за разрешения в PDF не е заключване. Това е искане, което файлът отправя към всичко, което го отваря, и зрителят е свободен да го игнорира. Този единствен факт решава как трябва да разсъждавате за всеки друг избор на тази страница. Истинската конфиденциалност идва само от едно място: AES-256 криптиране, заключено с парола, която читателят няма. Всичко останало, квадратчетата „без печат“ и „без копиране“, е политика, която съвместимият софтуер обещава да спазва, а враждебният софтуер не. Смесете тези два слоя и ще изпратите нещо, което изглежда сигурно в демо, но изтича на практика

HotPDF е нативен VCL PDF компонент за Delphi и C++Builder и излага модела за защита от ISO 32000 чрез малък набор свойства. Свойствата са лесни за задаване. Трудната част е да знаете кое от тях носи криптографска защита и кое носи само учтива препоръка, както и да подредите присвояванията в правилния ред, така че криптирането, което сте поискали, наистина да бъде криптирането, което получавате

Какво всъщност обещават двете пароли

PDF криптирането дефинира два идентификатора с различни задачи и смесването им е най-честата грешка при защитен изход. Потребителската парола отключва декриптирането. Без нея, или без собственическата парола, съвместимият четец не може да възстанови ключа на файла и съдържанието остава криптографски нечетимо. Собственическата парола, от своя страна, управлява флаговете за разрешения: четецът, който я получи, получава пълен достъп независимо какво казват ограниченията

Битовете за разрешения стоят на по-слаба основа. Печат, извличане на съдържание, попълване на формуляри: това са флагове, които зрителят прочита и избира дали да спазва (ISO 32000-2 §7.6.4). Криптирането защитава байтовете. Флаговете за разрешения само инструктират съвместимия софтуер и го правят след факта. Всеки, който отвори документа с потребителската парола, вече държи декриптираното съдържание в паметта си, така че „без копиране“ и „без печат“ означават нещо за добросъвестен зрител и нищо за решителен такъв. Изградете модела на заплахите около тази граница. Конфиденциалността живее в потребителската парола. Разрешенията оформят какво предлагат масовите зрители и това е всичко, което правят

Редът на конфигурация: всичко преди BeginDoc

HotPDF изгражда речника за криптиране и извежда ключа на файла в момента, в който се изпълни BeginDoc. Каквото и да съдържат свойствата за защита в този момент, това получава документът, а промяната им след това не променя нищо. Най-важното свойство тук е CryptKeyLength, което избира схемата от стойностите THPDFKeyType k40, k128, aes128 и aes256. Задайте го след BeginDoc и няма да получите изключение, нито предупреждение, а само файл, който тихо е запазил старото си състояние. Такъв мълчалив разнобой е най-лошият вид: минава през всички локални тестове и се появява месеци по-късно като проблем за съответствие при клиент

var
  Pdf: THotPDF;
begin
  Pdf := THotPDF.Create(nil);
  try
    Pdf.FileName := 'statement.pdf';
    Pdf.ActivateProtection := True;
    Pdf.CryptKeyLength := aes256;        // must be set before BeginDoc
    Pdf.UserPassword := 'open-secret';
    Pdf.OwnerPassword := 'admin-secret';
    Pdf.UseAES256R6 := False;            // R=5: widest viewer support
    Pdf.BeginDoc;
    Pdf.CurrentPage.SetFont('Arial', [], 11);
    Pdf.CurrentPage.TextOut(50, 720, 0, 'Account statement, June 2026');
    Pdf.EndDoc;
  finally
    Pdf.Free;
  end;
end;

Паролите са UTF-8 и са ограничени до 127 байта, което е лимитът на ISO 32000-2 за схемите AES-256. Ако политиката ви за пароли ви дава по-дълги секрети, съкратете ги сами, от своя страна и на място, където контролирате точно къде пада отсечката. Оставете това на случайността и на библиотеката и някой бъдещ зрител може да реши друго място за прекъсване, което води до файл, който се отваря при вас, но отказва същата парола другаде

Revision 5 или Revision 6: един булев флаг, две екосистеми

UseAES256R6 избира между двете AES-256 ръкостискания и изборът е по-важен, отколкото подсказва булевият му тип. Оставете го False и HotPDF записва revision 5, AES-256 схемата, която се появява като разширение към PDF 1.7 и която може да бъде отворена от нещо като петнадесет години зрители. Задайте го на True и получавате revision 6, укрепеното извеждане на ключове, стандартизирано в ISO 32000-2 за PDF 2.0, което затваря известна слабост в начина, по който revision 5 проверява паролата

Криптографски revision 6 е по-доброто решение. Той е и това, което чупи нещата. Файл с revision 6 изисква зрител, изграден за PDF 1.7 Extension Level 3 или PDF 2.0, а доста разпространен софтуер не е нито едно от двете: архиви за управление на записи, вградени рендеръри в други продукти, бизнес инструменти, до които никой не е посягал от години. Те ще откажат файла директно и ще го направят на машината на клиента, никога на вашата. Практическият default е revision 5. Посягайте към revision 6 само когато политика за сигурност назовава ISO 32000-2 по revision и когато сте потвърдили, че всеки потребител може да го чете. Какъвто и вариант да изберете, запишете защо, защото следващият човек, който пипне този код, ще се чуди

По-старите типове ключове заслужават едно изречение, за да знаете да ги пропускате. THPDFKeyType все още изброява k40, k128 и aes128, но те съществуват, за да възпроизвеждат исторически архиви, а не да защитават нови файлове. 40-битовият RC4 пада пред обикновен хардуер, а 128-битовите схеми предхождат AES-256 ревизиите, които всяка съвременна проверка за сигурност очаква. За документ, който създавате през 2026, реалният въпрос е само revision 5 срещу revision 6; ако се хванете да посягате към старите типове за нов дизайн, значи нещо нагоре по веригата е сбъркано

Флагове за разрешения без парола за отваряне

Често изискването е обратното на секретност. Всеки трябва да може да чете документа, но печатът или извличането трябва да са ограничени. Това се изразява с празна потребителска парола и непразна собственическа парола, което PDF нарича open-password mode, и се изброяват операциите, които искате да позволите в ProtectOptions

Pdf.ActivateProtection := True;
Pdf.CryptKeyLength := aes256;
Pdf.UserPassword := '';                      // anyone can open the file
Pdf.OwnerPassword := 'rotate-me-quarterly';  // guards the permission set
Pdf.ProtectOptions := [prPrint, prPrint12bit, prExtractContent];
Pdf.BeginDoc;
// ... page content ...
Pdf.EndDoc;

Наборът THPDFProtectOptions се картографира към ISO битовете за разрешения: prPrint и prPrint12bit за висококачествен печат, prInformationCopy за общо копиране и извличане, prExtractContent за извличане за помощни технологии, плюс prModifyStructure, prEditAnnotations, prFillAnnotations и prAssemble. Два от тях заслужават предупреждение. Оставяйте prExtractContent включен в почти всеки профил, който правите. Това е битът, от който четец на екран се нуждае, за да достигне текста, а изключването му тихо превръща решение за права в дефект за достъпност, който човек с увреждане усеща, а вие никога не виждате. Другият капан е prPrint сам по себе си, без prPrint12bit: няколко зрители отговарят с понижено качество на печат и потребителите ви ще го докладват като рендериращ бъг, а не като действителната настройка за разрешение

Проверката отнема пет минути и принадлежи в списъка ви за release. Отворете пример от всеки профил в Acrobat, отворете Document Properties и прочетете Security таба, който изписва алгоритъма („AES 256-bit“) и изброява позволените операции една по една. После отворете същия файл в най-стария зрител, който клиентите ви реално ползват, а не в най-новия на вашата машина. Тази втора проверка е евтина застраховка срещу това revision 6 файлът да мине през разработката и да умре при клиент, който никога не е ъпдейтвал

Премахване на защита от съществуващи файлове

Декриптирането работи със същия модел от свойства, но в обратна посока. Заредете документа с валиден credential, изключете защитата и запишете резултата без нея

var
  Pdf: THotPDF;
  PageCount: Integer;
begin
  Pdf := THotPDF.Create(nil);
  try
    PageCount := Pdf.LoadFromFile('encrypted.pdf', 'open-secret');
    if PageCount > 0 then
    begin
      Pdf.ActivateProtection := False;   // drop encryption on save
      Pdf.SaveLoadedDocument('plain.pdf');
    end;
  finally
    Pdf.Free;
  end;
end;

Този път парсва целия документ в паметта, което е добре за обикновени файлове и неефективно за огромни. Когато входът е стотици мегабайти, DecryptFile е по-евтиният вариант: той декриптира по време на file-level copy и използва директен AES-256 rewrite път, който пропуска изграждането на пълното object tree, когато входът го позволява. Това е част от Direct File API, разгледан в съпътстващата статия за обработка на големи PDF файлове от Delphi

Ограничения, които се преплитат с криптирането

Два лимита си струва да знаете, преди да проектирате около криптирането, а не след това. Първият е архивната съвместимост. ISO 19005 забранява криптиране в PDF/A, така че работен поток, който едновременно криптира документ и твърди PDF/A съответствие, е противоречив по конструкция; HotPDF няма да ви позволи да имате и двете в един файл. Когато наистина ви трябват и двете, отговорът са два артефакта: криптирано копие за разпространение и отделно некриптирано копие за архива

Вторият лимит е по-рязък. PDF криптирането няма escrow и няма recovery. Загубите ли потребителската парола на файл с R5 или R6, опциите ви са brute force или отказване. Затова третирайте собственическите и потребителските секрети както третирате всякакъв продукционен credential. Генерирайте ги, съхранявайте ги във vault и ги въртете по график. Единственото, което никога не трябва да правите, е да ги hard-code-нете като константи в unit, където те отиват направо във version control и стоят във всяко developer копие завинаги

Един последен рефлекс, който си струва да изградите. Промяната на защитата на файл, който не сте създали, използва същата механика като декриптирането, а не отделна функция: заредете го с паролата му чрез LoadFromFile, редактирайте ProtectOptions или паролите на място и го запишете обратно с SaveLoadedDocument. Ако можете да декриптирате файл, можете да му промените правата и кодът изглежда почти същият като примера по-горе

Свойствата за защита, показани тук, са част от стандартния HotPDF Component за Delphi и C++Builder; продуктовата страница съдържа пълната документация за криптирането, включително пълното изброяване на разрешенията