Inom juridiska, finansiella och hälsovårdssektorer är generering av stora volymer PDF-dokument standardpraxis. Att producera dokumenten är dock bara halva striden; att säkra dem är lika kritiskt. När du har en arkiveringspipeline som bearbetar hundratals gigabyte PDF-filer dagligen kan tillämpningen av AES-256-kryptering snabbt bli en prestandaflaskhals.
I den här artikeln kommer vi att utforska hur man uppnår höghastighets AES-256 PDF-kryptering i Delphi genom att undvika minnesutmattning och optimera de kryptografiska looparna.
PDF-krypteringsspecifikationen
PDF-säkerhet har utvecklats avsevärt. Tidiga versioner använde 40-bitars RC4, vilket är trivialt att knäcka idag. Den nuvarande standarden (PDF 1.7 Extension Level 3 och PDF 2.0) kräver AES-256-kryptering.
I en PDF krypterar du inte hela filblocket. Dokumentstrukturen (XRef-tabellen och strukturen för ordböcker) förblir i klartext. Istället krypterar du strömmar (rådata för bilder och sidinnehåll) och strängar (t.ex. metadatatext). Detta kräver att tolkaren extraherar datan, tillämpar AES CBC (Cipher Block Chaining) och skriver tillbaka den.
Flaskhalsen: Inläsning till minnet
Ett vanligt misstag när man krypterar en massiv PDF (t.ex. ett skannat arkiv på 2 GB) är att läsa in hela strömmen i en TMemoryStream innan den skickas till den kryptografiska motorn. Detta leder till Out-Of-Memory-undantag (OOM) i 32-bitarsprocesser och massiva sidfel (page faulting) i 64-bitarsprocesser.
Strömmande kryptering i Delphi
Lösningen är att använda en uppdelad (chunked), strömmande metod. Med hjälp av Windows Cryptography API: Next Generation (CNG) eller ett bibliotek som OpenSSL kan du läsa PDF-strömmen i block på 64 KB, kryptera blocket och skriva det direkt till utdataströmmen på disken.
Här är ett konceptuellt Delphi-exempel som demonstrerar en buffrad krypteringsloop för en ström:
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;
Optimera den kryptografiska backend-motorn
Delphi-utvecklare har flera val för AES backend-motorn:
- Inbyggda Delphi-implementeringar: Enkla att distribuera, men ofta långsammare eftersom de enbart körs i mjukvara.
- Windows CNG (BCrypt): Mycket optimerad och kan utnyttja hårdvaruacceleration (AES-NI-instruktioner på moderna Intel/AMD-processorer).
- OpenSSL (libcrypto): Branschstandarden, otroligt snabb, men kräver distribution av externa DLL-filer.
För serverapplikationer med hög genomströmning är hårdvaruaccelererad AES-NI obligatoriskt. Vid användning av Windows CNG i Delphi tillåter mappning av funktionen BCryptEncrypt din applikation att flytta det tunga arbetet till processorns dedikerade kryptografiska kisel, vilket i praktiken minskar krypteringskostnaden (overhead) till nära noll.
Slutsats
När du krypterar PDF-filer i gigabyte-skala ska du förlita dig på strömuppdelning i stället för fullständig minnesbuffring, och se till att din kryptografiska backend utnyttjar hårdvaruacceleration med AES-NI. Denna kombination garanterar att din arkiveringspipeline körs i hastigheten hos dina NVMe-enheter, i stället för att vara CPU-bunden.
Obs: Höghastighets AES-256-kryptering med hjälp av uppdelad strömning stöds inbyggt i HotPDF VCL Component.