Inden for juridiske, finansielle og sundhedsrelaterede sektorer er generering af store mængder PDF-dokumenter standardpraksis. At producere dokumenterne er dog kun det halve af kampen; at sikre dem er lige så kritisk. Når du har en arkiveringspipeline, der behandler hundredvis af gigabyte PDF'er dagligt, kan anvendelse af AES-256 kryptering hurtigt blive en flaskehals for ydeevnen.
I denne artikel vil vi se på, hvordan man opnår højhastigheds AES-256 PDF-kryptering i Delphi ved at undgå hukommelsesudmattelse og optimere de kryptografiske sløjfer.
PDF-krypteringsspecifikationen
PDF-sikkerhed har udviklet sig betydeligt. Tidlige versioner brugte 40-bit RC4, som er trivielt at bryde i dag. Den nuværende standard (PDF 1.7 Extension Level 3 og PDF 2.0) påkræver AES-256 kryptering.
I en PDF krypterer du ikke hele filblokken. Dokumentstrukturen (XRef-tabellen og strukturen af ordbøger) forbliver i klartekst. I stedet krypterer du Streams (de rå data til billeder og sideindhold) og Strings (såsom metadatatekst). Dette kræver, at parseren udtrækker dataene, anvender AES CBC (Cipher Block Chaining) og skriver det tilbage.
Flaskehalsen: Indlæsning til hukommelsen
En almindelig fejl ved kryptering af en massiv PDF (f.eks. et 2 GB scannet arkiv) er at indlæse hele streamen i en TMemoryStream, før den sendes til den kryptografiske motor. Dette fører til Out-Of-Memory (OOM) undtagelser i 32-bit processer og massiv sidefejl (page faulting) i 64-bit processer.
Streaming-kryptering i Delphi
Løsningen er at bruge en opdelt (chunked) streaming-tilgang. Ved hjælp af Windows Cryptography API: Next Generation (CNG) eller et bibliotek som OpenSSL kan du læse PDF-streamen i 64 KB-blokke, kryptere blokken og skrive den direkte til output-disk-streamen.
Her er et konceptuelt Delphi-eksempel, der demonstrerer en bufret krypteringssløjfe for en stream:
uses
System.Classes, System.SysUtils;
const
BUFFER_SIZE = 65536; // 64KB chunks
// This represents your AES-256 encryption routine
procedure EncryptStreamChunk(const InBuffer; var OutBuffer; BytesRead: Integer; const Key: TBytes; const IV: TBytes);
begin
// Call to Windows CNG (BCryptEncrypt) or OpenSSL (EVP_EncryptUpdate)
// ...
end;
procedure EncryptLargePDFStream(InputStream, OutputStream: TStream; const Key, IV: TBytes);
var
InBuffer, OutBuffer: array of Byte;
BytesRead: Integer;
begin
SetLength(InBuffer, BUFFER_SIZE);
// AES CBC requires padding, so the output buffer must be slightly larger
SetLength(OutBuffer, BUFFER_SIZE + 16);
InputStream.Position := 0;
OutputStream.Position := 0;
repeat
BytesRead := InputStream.Read(InBuffer[0], BUFFER_SIZE);
if BytesRead > 0 then
begin
EncryptStreamChunk(InBuffer[0], OutBuffer[0], BytesRead, Key, IV);
// Write the encrypted cipher text directly to disk
OutputStream.Write(OutBuffer[0], BytesRead); // Note: padding logic omitted for brevity
end;
until BytesRead < BUFFER_SIZE;
end;
Optimering af den kryptografiske backend
Delphi-udviklere har flere valgmuligheder til AES-backenden:
- Indfødte Delphi-implementeringer: Nemme at udrulle, men ofte langsommere, da de udelukkende udføres i software.
- Windows CNG (BCrypt): Meget optimeret og kan udnytte hardwareacceleration (AES-NI instruktioner på moderne Intel/AMD CPU'er).
- OpenSSL (libcrypto): Industristandarden, utroligt hurtig, men kræver distribution af eksterne DLL'er.
For højtydende serverapplikationer er hardwareaccelereret AES-NI obligatorisk. Ved brug af Windows CNG i Delphi tillader kortlægning af BCryptEncrypt-funktionen din applikation at overlade det tunge arbejde til CPU'ens dedikerede kryptografiske silicium, hvilket effektivt reducerer krypteringsomkostningerne til næsten nul.
Konklusion
Når du krypterer PDF'er i gigabyte-skala, skal du stole på stream-opdeling (chunking) i stedet for fuld hukommelsesbufring og sikre, at din kryptografiske backend udnytter hardware AES-NI acceleration. Denne kombination garanterer, at din arkiveringspipeline kører med samme hastighed som dine NVMe-drev, frem for at være CPU-begrænset.
Bemærk: Højhastigheds AES-256 kryptering ved hjælp af opdelt streaming (chunked streaming) understøttes indbygget i HotPDF VCL Component.