Прапорець дозволу PDF — це не замок. Це прохання, яке файл адресує будь-чому, що його відкриває, і переглядач вільний його ігнорувати. Саме цей факт визначає, як варто міркувати про кожен інший вибір на цій сторінці. Справжня конфіденційність походить лише з одного джерела: шифрування AES-256 з ключем на основі пароля, якого читач не має. Усе інше — прапорці "заборонити друк" і "заборонити копіювання" — це політика, яку сумісне програмне забезпечення погоджується дотримуватися, а ворожа програма — ні. Переплутайте ці два рівні, і ви випустите щось, що виглядає безпечним на демонстрації, а в польових умовах протікає
HotPDF — це нативний VCL-компонент PDF для Delphi та C++Builder, який відкриває модель захисту ISO 32000 через невеликий набір властивостей. Встановити ці властивості нескладно. Складніше — знати, яка з них дає криптографічний захист, а яка — лише ввічливу пропозицію, і дотримуватися правильного порядку присвоєння, щоб шифрування, яке ви замовили, справді стало шифруванням, яке ви отримали
Що насправді обіцяють два паролі
Шифрування PDF визначає два облікові дані з різними завданнями, і їх сплутування — найпоширеніша помилка проєктування в коді захищеного виводу. Пароль користувача (user password) відкриває доступ до дешифрування. Без нього, або без пароля власника, сумісний читач не може відновити ключ файлу, і вміст лишається криптографічно нечитабельним. Пароль власника (owner password) натомість відкриває доступ до налаштувань дозволів: читач, який отримує пароль власника, отримує повний доступ незалежно від того, що кажуть прапорці обмежень
Біти дозволів стоять на хиткішому ґрунті. Друк, вилучення вмісту, заповнення форм: кожен із них — це прапорець, який переглядач читає й вирішує дотримуватися (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; // має бути встановлено до BeginDoc
Pdf.UserPassword := 'open-secret';
Pdf.OwnerPassword := 'admin-secret';
Pdf.UseAES256R6 := False; // R=5: найширша підтримка переглядачів
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, а чимало розгорнутого програмного забезпечення не відповідає жодному з них: архіви систем керування записами, вбудовані рендерери в інших продуктах, галузеві інструменти, яких роками ніхто не торкався. Вони просто відмовляться відкривати файл, і зроблять це на машині клієнта, а не на вашій. Тож практичним значенням за замовчуванням є revision 5. Звертайтеся до revision 6 лише тоді, коли політика безпеки прямо називає ревізію ISO 32000-2, і коли ви справді підтвердили, що кожен споживач може її прочитати. У будь-якому разі запишіть, який варіант ви обрали і чому, бо наступна людина, яка торкнеться цього коду, захоче знати
Старіші типи ключів заслуговують на одне речення, щоб ви знали, що їх слід пропускати. 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 := ''; // будь-хто може відкрити файл
Pdf.OwnerPassword := 'rotate-me-quarterly'; // захищає набір дозволів
Pdf.ProtectOptions := [prPrint, prPrint12bit, prExtractContent];
Pdf.BeginDoc;
// ... вміст сторінки ...
Pdf.EndDoc;
Набір THPDFProtectOptions відображається на біти дозволів ISO: prPrint і prPrint12bit для друку високої роздільної здатності, prInformationCopy для звичайного копіювання й вилучення, prExtractContent для вилучення технологіями доступності, а також prModifyStructure, prEditAnnotations, prFillAnnotations і prAssemble. Два з них заслуговують на попередження. Залишайте prExtractContent увімкненим майже в кожному профілі, який ви будуєте. Це той біт, який потрібен програмі зчитування з екрана, щоб дістатися тексту, і його вимкнення мовчки перетворює рішення про права на дефект доступності, який зачепить людину з інвалідністю, а ви цього ніколи не побачите. Друга пастка — prPrint сам собою, без prPrint12bit: кілька переглядачів реагують на це погіршенням якості друку, а ваші користувачі зафіксують це як ваду рендерингу, а не як налаштування дозволу, яким воно насправді є
Перевірка займає п'ять хвилин і має бути в чеклісті релізу. Відкрийте зразок кожного профілю в Acrobat, відкрийте Document Properties і прочитайте вкладку Security, яка прямо називає алгоритм ("AES 256-bit") і по черзі перелічує дозволені операції. Потім відкрийте той самий файл у найстарішому переглядачі, яким справді користуються ваші клієнти, а не в найновішому на вашій машині. Це друге відкриття — дешева страховка від ситуації, коли файл revision 6 безперешкодно проходить розробку, а потім гине в клієнта, який ніколи не оновлювався
Видалення захисту з наявних файлів
Дешифрування прогонює ту саму модель властивостей у зворотному напрямку. Завантажте документ із дійсними обліковими даними, вимкніть захист і збережіть результат уже без нього
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; // прибрати шифрування під час збереження
Pdf.SaveLoadedDocument('plain.pdf');
end;
finally
Pdf.Free;
end;
end;
Цей шлях розбирає весь документ у пам'ять, що прийнятно для звичайних файлів і марнотратно для величезних. Коли вхідні дані сягають сотень мегабайтів, дешевший варіант — DecryptFile: він дешифрує під час копіювання на рівні файлу, використовуючи прямий шлях перезапису AES-256, що уникає побудови повного дерева об'єктів, коли це дозволяють вхідні дані. Це частина Direct File API, розглянутого в суміжній статті про обробку великих PDF з Delphi
Обмеження, що взаємодіють із шифруванням
Варто знати два обмеження до того, як проєктувати навколо шифрування, а не після. Перше — архівна відповідність. ISO 19005 забороняє шифрування в PDF/A, тож будь-який робочий процес, що шифрує документ і водночас заявляє про відповідність PDF/A, суперечливий за самою конструкцією; HotPDF не дозволить мати обидва в одному файлі. Коли вам справді потрібно і те, й інше, відповідь — два артефакти: зашифрована копія для розповсюдження й окрема незашифрована копія для архіву
Друге обмеження суворіше. Шифрування PDF не має ні депонування ключів, ні відновлення. Втратьте пароль користувача для файлу R5 чи R6 — і ваші варіанти зводяться до перебору або відмови від спроб. Тож ставтеся до секретів власника й користувача так само, як до будь-яких промислових облікових даних. Генеруйте їх, зберігайте у сховищі, регулярно ротуйте. Єдине, чого ніколи не варто робити, — жорстко прописувати їх як константи в модулі, звідки вони прямісінько потрапляють у систему контролю версій і назавжди осідають у робочій копії кожного розробника
Останній рефлекс, вартий вироблення. Зміна захисту файлу, який ви не створювали, — це той самий механізм, що й дешифрування, а не окрема функція: завантажте його з відповідним паролем через LoadFromFile, відредагуйте ProtectOptions або паролі на місці й запишіть назад через SaveLoadedDocument. Якщо ви можете дешифрувати файл, ви можете й переналаштувати його дозволи, і код виглядає майже ідентично до прикладу вище
Показані тут властивості захисту є частиною стандартного HotPDF Delphi Component для Delphi та C++Builder; сторінка продукту містить повний довідник із шифрування, зокрема повний перелік дозволів