Technisch artikel

PDF 2.0 AES-GCM-versleuteling in Delphi: ISO/TS 32003

PDFiumPas schrijft ISO/TS 32003-versleuteling via SaveAsEncrypted: zet Revision op erR7 en elke string en stream wordt beschermd met AES-256 in GCM-modus, het geauthenticeerde cijfer dat PDF 2.0 in 2023 kreeg. Zet ook EnableIntegrityProtection en het document draagt bovendien een zelfstandig PDF MAC-token, dat ValidatePdfMac aan de leeskant controleert

Dat zijn twee verschillende beschermingen die mensen routinematig door elkaar halen. GCM authenticeert elke versleutelde waarde. De MAC authenticeert het document als geheel. U wilt beide, om verschillende redenen

Wat voegt GCM toe dat CBC nooit bood?

Authenticatie van de ciphertext. AES-256 in CBC-modus, het AESV3-schema in ISO 32000-2, houdt inhoud vertrouwelijk en zegt niets over of ze ongewijzigd aankwam. CBC is kneedbaar op specifieke, goed bestudeerde manieren: een aanvaller die bits in de ciphertext kan omdraaien, produceert voorspelbare veranderingen in de plaintext van het volgende blok, en niets in het formaat merkt dat op

GCM sluit dat. Elke versleutelde waarde draagt een authenticatietag van 16 bytes, volledig geserialiseerd zoals ISO/TS 32003 vereist, en ontsleuteling faalt in plaats van gewijzigde plaintext terug te geven wanneer de tag niet klopt. In PDF-termen is een gemanipuleerde string of stream in een AESV4-document een harde fout op het moment van gebruik, geen vreemde waarde die zich door uw applicatie voortplant. De Encrypt-dictionary markeert dit met /CFM /AESV4 en V 6 / R 7, naast een extensies-item dat /ExtensionLevel 32003 en /ExtensionRevision (:2023) declareert

Drie revisies, drie ecosystemen

TPdfEncryptionRevision biedt erR5, erR6 en erR7, en de keuze is meer een compatibiliteitsbeslissing dan een cryptografische. R5 is het originele AES-256-schema gepubliceerd als een PDF 1.7-uitbreiding, met één enkele SHA-256-wachtwoordhash, en het opent in vrijwel alles van de afgelopen vijftien jaar. R6 is de verharde sleutelafleiding gestandaardiseerd in ISO 32000-2, met de iterende SHA-256/384/512-constructie van algoritme 2.B, en het is wat een actuele PDF 2.0- of PDF/A-4-workflow verwacht. R7 is ISO/TS 32003, met dezelfde 2.B-afleiding maar met AES-GCM als cijfer

Readerondersteuning loopt in precies die volgorde, en R7-ondersteuning is nog altijd dun buiten de huidige mainstream viewers. Dit is dezelfde afweging die elke PDF 2.0-functie beheerst: de nieuwste optie is de beste techniek en het smalste publiek. Beslis op basis van wie het bestand moet openen, en als dat antwoord "een archiefsysteem dat niemand sinds 2019 heeft bijgewerkt" is, dan is het antwoord R5, ongeacht wat het beveiligingsbeleid liever ziet

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;   // zelfstandig PDF MAC-token

    if not Pdf.SaveAsEncrypted('quarterly-report.enc.pdf', Opts) then
      raise Exception.Create('Encrypted save failed');
  finally
    Pdf.Free;
  end;
end;

Waarom een documentMAC bovenop een geauthenticeerd cijfer?

Omdat GCM-tags de waarden beschermen, niet de rangschikking van de waarden. Elke string en stream in een AESV4-document is individueel geauthenticeerd, en toch zijn de cross-referentietabel, de objectnummering en de trailer structuur, geen versleutelde inhoud. Een aanvaller kan geen stream vervalsen, maar niets in het cijfer alleen weerhoudt hem ervan om te herschikken naar welke objecten het document verwijst, of om objecten uit een eerdere revisie van hetzelfde bestand samen te voegen

Het zelfstandige PDF MAC-token pakt die laag aan. PDFiumPas leidt het af van de bestandsversleutelingssleutel met een toegewijde /KDFSalt van 32 bytes vastgelegd in de Encrypt-dictionary, dus het bezit van het wachtwoord is wat een reader in staat stelt het token te bevestigen. Het resultaat is één antwoord op één vraag: is dit document, als geheel, het document dat geschreven werd

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);       // geen token in dit bestand
      pmvsInvalid:     Quarantine(Mac.MessageText);   // gemanipuleerd of afgekapt
      pmvsUnsupported: RouteForManualReview(Mac.MessageText);
    end;
  finally
    Pdf.Free;
  end;
end;

De vier statuswaarden vragen om vier verschillende reacties, en ze samenvoegen tot een boolean laat precies het onderscheid verloren gaan dat ertoe doet. pmvsNotPresent betekent dat het bestand simpelweg geen token heeft, wat vrijwel elke vóór 2024 geschreven versleutelde PDF beschrijft en geen bewijs van iets is. pmvsInvalid betekent dat er een token aanwezig is dat niet verifieert, wat een echte bevinding is en de verwerking zou moeten stoppen. pmvsUnsupported betekent dat het token bestaat in een vorm die deze build niet implementeert, wat een compatibiliteitsgat is, geen aanval. "not present" als "invalid" behandelen zou uw hele back-catalogus op de eerste dag in quarantaine plaatsen

Wat versleuteling nog altijd niet doet

Toestemmingsvlaggen blijven wat ze altijd al waren: een verzoek aan conforme software, geen controle. De /P-bits uit ISO 32000-1 Table 22 die afdrukken of extractie verbieden, worden nageleefd door goed gedragende viewers en genegeerd door al het andere, en iedereen die het gebruikerswachtwoord bezit, heeft de ontsleutelde inhoud al in handen. Versleuteling is de grens; toestemmingen beschrijven de intentie erbinnen

Twee operationele details zijn de moeite waard om op voor te bereiden. Ten eerste, versleuteling en latere wijziging beïnvloeden elkaar: een incrementele update toevoegen aan een versleuteld document heeft zijn eigen regels, behandeld in incrementele updates op versleutelde PDF's, en een MAC-token is een uitspraak op documentniveau die een onzorgvuldige toevoeging ongeldig zal maken. Ten tweede, de GCM-constructie gebruikt een deterministische IV-teller, en PDFiumPas gooit een exceptie in plaats van een tellerwaarde te hergebruiken als die ruimte ooit uitgeput zou raken, omdat nonce-hergebruik in GCM catastrofaal is op een manier die stille overloop zou verhullen

Kiezen tussen de drie revisies in de praktijk

Schrijf op wie het bestand opent, en kies dan. Voor interne verspreiding waar elke lezer een actuele viewer onder uw eigen beheer is, is R7 met integriteitsbescherming de sterkste beschikbare optie en er is geen reden om die niet te gebruiken. Voor documenten die de organisatie verlaten, is R6 de verdedigbare standaard: het is gestandaardiseerd in ISO 32000-2 in plaats van in een technische specificatie erbovenop, en de ondersteuning is breed. Voor archieven en legacy-consumenten is R5 de enige keuze die betrouwbaar opent, en u moet vastleggen waarom op dezelfde plek waar u de rest van uw bewaarbeleid vastlegt

Welke u ook kiest, verifieer de output in plaats van erop te vertrouwen dat de aanroep slaagde. Open het versleutelde bestand opnieuw, controleer ValidatePdfMac, en bevestig dat de gedeclareerde versie is wat u verwacht, met de versieconformiteitscontroles in exacte PDF-versieconformiteit. Een bredere intakechecklist voor niet-vertrouwde documenten staat in het auditen van PDF-beveiligingsrisico's

PDFiumPas is een Delphi- en Lazarus-component rond de PDFium-engine met de PDF 2.0-versleutelingsstack native in Pascal geïmplementeerd, dus AES-256, GCM en het MAC-token hebben geen externe crypto-DLL nodig. De versleutelings-API staat gedocumenteerd op de PDFium Delphi-componentpagina