PDFiumPas כותב הצפנת ISO/TS 32003 דרך SaveAsEncrypted: הגדירו Revision ל-erR7 וכל מחרוזת וזרם מוגנים עם AES-256 במצב GCM, הצופן המאומת ש-PDF 2.0 קיבל ב-2023. הגדירו גם EnableIntegrityProtection והמסמך נושא גם אסימון PDF MAC עצמאי, ש-ValidatePdfMac בודק בצד הקריאה
אלו שתי הגנות שונות שאנשים בשגרה מבלבלים ביניהן. GCM מאמת כל ערך מוצפן. ה-MAC מאמת את המסמך בכללותו. אתם רוצים את שניהם, מסיבות שונות
מה GCM מוסיף שמעולם לא ניתן ב-CBC?
אימות של הצופן. AES-256 במצב CBC, סכמת AESV3 ב-ISO 32000-2, שומר על סודיות תוכן ולא אומר דבר על האם הוא הגיע ללא שינוי. CBC ניתן למניפולציה בדרכים ספציפיות ומחקרות היטב: תוקף שיכול להפוך ביטים בצופן מפיק שינויים צפויים בתוכן הגלוי של הבלוק הבא, ושום דבר בפורמט לא שם לב
GCM סוגר את זה. כל ערך מוצפן נושא תג אימות בן 16 בייטים, מסודר במלואו כפי ש-ISO/TS 32003 דורש, והפענוח נכשל במקום להחזיר תוכן גלוי שהשתנה כשהתג לא תואם. במונחי PDF, מחרוזת או זרם מזויפים במסמך AESV4 הם שגיאה קשה בנקודת השימוש, לא ערך מוזר שמתפשט ליישום שלכם. מילון ה-Encrypt מסמן זאת עם /CFM /AESV4 ו-V 6 / R 7, לצד רשומת הרחבות שמצהירה /ExtensionLevel 32003 ו-/ExtensionRevision (:2023)
שלוש גרסאות, שלוש מערכות אקולוגיות
TPdfEncryptionRevision מציע את erR5, erR6 ו-erR7, והבחירה היא החלטת תאימות יותר מהחלטה קריפטוגרפית. R5 היא סכמת ה-AES-256 המקורית שפורסמה כהרחבה ל-PDF 1.7, עם גיבוב סיסמה יחיד של SHA-256, והיא נפתחת כמעט בכל דבר מחמש-עשרה השנים האחרונות. R6 היא גזירת המפתח המוקשחת שהוסדרה ב-ISO 32000-2, באמצעות בניית האיטרציה של SHA-256/384/512 של אלגוריתם 2.B, וזה מה שתהליך עבודה נוכחי של PDF 2.0 או PDF/A-4 מצפה לו. R7 היא ISO/TS 32003, המשתמשת באותה גזירת 2.B עם AES-GCM כצופן
תמיכת קוראים פועלת בדיוק באותו סדר, ותמיכת R7 עדיין דלה מחוץ לצופנים המרכזיים הנוכחיים. זה אותו איזון שמנהל כל תכונת PDF 2.0: האפשרות החדשה ביותר היא ההנדסה הטובה ביותר והקהל הצר ביותר. החליטו לפי מי שצריך לפתוח את הקובץ, ואם התשובה היא "מערכת רשומות שאף אחד לא עדכן מאז 2019", התשובה היא R5 ללא קשר למה שמדיניות האבטחה מעדיפה
uses
PDFium, FPdfEncrypt;
var
Pdf: TPdf;
Opts: TPdfEncryptOptions;
begin
Pdf := TPdf.Create(nil);
try
Pdf.FileName := 'quarterly-report.pdf';
Pdf.LoadDocument;
Opts := TPdfEncryptOptions.Default;
Opts.UserPassword := 'open-secret';
Opts.OwnerPassword := 'admin-secret';
Opts.EncryptMetadata := True;
Opts.Revision := erR7; // ISO/TS 32003 AESV4-GCM
Opts.EnableIntegrityProtection := True; // אסימון PDF MAC עצמאי
if not Pdf.SaveAsEncrypted('quarterly-report.enc.pdf', Opts) then
raise Exception.Create('Encrypted save failed');
finally
Pdf.Free;
end;
end;
מדוע MAC על המסמך בנוסף לצופן מאומת?
מפני שתגי GCM מגנים על הערכים, לא על הסידור של הערכים. כל מחרוזת וזרם במסמך AESV4 מאומתים בנפרד, ובכל זאת טבלת ההפניות הצולבות, מספור האובייקטים והtrailer הם מבנה, לא תוכן מוצפן. תוקף לא יכול לזייף זרם, אבל שום דבר בצופן לבדו לא מונע ממנו לסדר מחדש למה המסמך מצביע, או להדביק אובייקטים מגרסה קודמת של אותו קובץ
אסימון ה-PDF MAC העצמאי מטפל בשכבה הזו. PDFiumPas גוזר אותו ממפתח הצפנת הקובץ עם /KDFSalt ייעודי בן 32 בייטים הרשום במילון ה-Encrypt, כך שהחזקת הסיסמה היא מה שמאפשר לקורא לאשר את האסימון. התוצאה היא תשובה אחת לשאלה אחת: האם המסמך הזה, בכללותו, הוא המסמך שנכתב
var
Pdf: TPdf;
Mac: TPdfMacValidationResult;
begin
Pdf := TPdf.Create(nil);
try
Pdf.Password := 'open-secret';
Pdf.FileName := 'quarterly-report.enc.pdf';
Pdf.LoadDocument;
Mac := Pdf.ValidatePdfMac('open-secret');
case Mac.Status of
pmvsValid: ProcessDocument(Pdf);
pmvsNotPresent: ProcessWithWarning(Pdf); // אין אסימון בקובץ הזה
pmvsInvalid: Quarantine(Mac.MessageText); // מזויף או קטוע
pmvsUnsupported: RouteForManualReview(Mac.MessageText);
end;
finally
Pdf.Free;
end;
end;
ארבעת ערכי הסטטוס דורשים ארבע תגובות שונות, וצמצומם לבוליאני מאבד את ההבחנה החשובה. pmvsNotPresent אומר שלקובץ פשוט אין אסימון, מה שמתאר כמעט כל PDF מוצפן שנכתב לפני 2024 ואינו עדות לכלום. pmvsInvalid אומר שאסימון נוכח ולא מאמת, שזה ממצא אמיתי וצריך לעצור עיבוד. pmvsUnsupported אומר שהאסימון קיים בצורה שהבנייה הזו לא מממשת, שזה פער תאימות, לא התקפה. התייחסות ל"לא נוכח" כ"מזויף" הייתה משמת בהסגר את כל הארכיון שלכם ביום הראשון
מה ההצפנה עדיין לא עושה
דגלי ההרשאה נשארים מה שהם תמיד היו: בקשה לתוכנה תואמת, לא פקד. הביטים /P מטבלה 22 של ISO 32000-1 שאוסרים הדפסה או חילוץ מכובדים על ידי צופנים שמתנהגים היטב ומתעלמים בכל השאר, וכל מי שמחזיק את סיסמת המשתמש כבר מחזיק את התוכן המפוענח. ההצפנה היא הגבול; ההרשאות מתארות כוונה בתוכו
שני פרטים תפעוליים שווים תכנון. ראשית, הצפנה ושינוי מאוחר יותר משפיעים זה על זה: הוספת עדכון מצטבר למסמך מוצפן יש לה כללים משלה, המכוסים בעדכונים מצטברים ב-PDF מוצפן, ואסימון MAC הוא הצהרה ברמת המסמך שהוספה לא זהירה תבטל. שנית, בניית ה-GCM משתמשת במונה IV דטרמיניסטי, ו-PDFiumPas מעלה חריגה במקום למחזר ערך מונה אם המרחב הזה אי-פעם היה מתרוקן, מפני ששימוש חוזר ב-nonce ב-GCM הרסני בדרך שגלישה שקטה הייתה מסתירה
בחירה בין שלוש הגרסאות בפועל
רשמו מי פותח את הקובץ, ואז בחרו. להפצה פנימית שבה כל קורא הוא צופה נוכחי בשליטתכם, R7 עם הגנת שלמות היא האפשרות החזקה ביותר הזמינה ואין סיבה לא להשתמש בה. למסמכים שעוזבים את הארגון, R6 היא ברירת המחדל הניתנת להצדקה: היא מוסדרת ב-ISO 32000-2 ולא במפרט טכני שמעליו, והתמיכה רחבה. לארכיונים וצרכנים ותיקים, R5 היא הבחירה היחידה שנפתחת באמינות, וכדאי לרשום למה באותו מקום שבו רושמים את שאר מדיניות השימור שלכם
לא משנה מה תבחרו, אמתו את הפלט במקום לסמוך על כך שהקריאה הצליחה. פתחו מחדש את הקובץ המוצפן, בדקו ValidatePdfMac, ואשרו שהגרסה המוצהרת היא מה שציפיתם לו, באמצעות בדיקות תאימות הגרסה בתאימות גרסת PDF מדויקת. רשימת בדיקה רחבה יותר למסמכים לא מהימנים נמצאת בביקורת סיכוני אבטחת PDF
PDFiumPas הוא רכיב ל-Delphi ול-Lazarus סביב מנוע PDFium עם מחסנית ההצפנה של PDF 2.0 ממומשת באופן טבעי ב-Pascal, כך ש-AES-256, GCM ואסימון ה-MAC לא זקוקים ל-DLL קריפטוגרפי חיצוני. ה-API של ההצפנה מתועד בדף רכיב PDFium ל-Delphi