Net-Base Maġazin

30.05.2026

AES-kriptazzjoni f'Delphi: snippet tal-kodiċi robust bil-IV, salt, header u streaming

Snippet tal-kodiċi prattiku Delphi għall-enkriptazzjoni AES bi-salt u IV każwali, struttura ċara tal-header tal-fajl, PBKDF2-derivazzjoni tal-ċavetta u streaming — inkluż l-ostakli tipici f'formatijiet legacy, integrità u operazzjoni.

30.05.2026

Minn suġġett tar-rivista għall-prattika tal-proġett

Paġni ta' servizz u paġni tekniċi relevanti għall-artiklu

Fuq enkrizzjoni AES Delphi fil-prattika mhux dejjem ikun problema l‑„AES per se“, iżda l‑kundizzjonijiet tal‑kuntest: id‑dejta trid tiġi pproċessata bħala stream (fajls, BLOBs, backups), il‑formati antiki jridu jibqgħu jinreadu, u fil‑produzzjoni għandek bżonn debbuġjar (header, verżjoni) u defaults sigur (Salt/IV każwali, mingħajr ri‑użu). Din il‑biċċa kodiċi tidher mhux biss l‑“Encrypt/Decrypt”, iżda format żgħir u affidabbli b’header, verżjoni, Salt u IV – inkluż PBKDF2 għall‑derivazzjoni tal‑key u punt fejn l‑integrità tista’ tiġi miżjuda b’mod sensibbli.

Għaliex „enkrizzjoni ta‘ string b’AES“ kważi qatt ma tkun biżżejjed

Fi softwer aziendali individwalizzat, enkrizzjoni tipikament tidher f’tlett postijiet: (1) konfigurazzjoni/Secrets (eż. kredenzjali ta’ aċċess), (2) fajls ta’ skambju/esportazzjoni u (3) dejta statika (eż. arkivji, kontenituri ta’ dokumenti). L‑approċċ naiv „password → AES‑Key → string in/out“ jisfrutta malajr:

  • Ri‑użu tal‑IV: F’modi bħal CBC jew GCM vettur ta’ inizjalizzazzjoni (IV) għandu jkun uniku għal kull enkrizzjoni. IV kostanti huwa twessigħa ta’ sigurtà, anke jekk il‑password ikun robust.
  • Key minn password mingħajr KDF: L‑użu ta’ password direttament bħala key (jew hash wieħed biss) jinvita attakki offline. KDF (Key Derivation Function) bħal PBKDF2 jżid it‑tul tal‑ħin meħtieġ u jagħmilha ħafna iktar diffiċli għall‑attakkanti.
  • L‑ebda verżjoni tal‑format: Mingħajr header/verżjoni mhux faċli tbiddel in‑numru ta’ iterazzjonijiet, l‑algoritmu jew il‑parametri aktar tard mingħajr ma tħalli d‑dejta l‑qadima inkompatibbli jew maqtugħa mill‑verżjonijiet ġodda.
  • L‑ebda integrità: AES‑CBC jinkripta, imma ma jipprevjenix manipulazzjoni. Mingħajr awtentikazzjoni (eż. HMAC jew AEAD bħal GCM) tirċievi problemi ta’ bitflipping/padding u manifestazzjonijiet ta’ żball difficli biex jiġu d‑dijanjostikati.

Il‑pint ewlieni ta’ dan il‑test: format żgħir ta’ kontenitur li jappoġġja streaming, li jista’ jiġi verżjoni u li jevita l‑żbalji standard.

Enkrizzjoni AES Delphi b’Header, Salt, IV u PBKDF2

Niddedefinixxu format sempliċi ta’ kontenitur li jista’ jintuża wkoll f’BLOBs ta’ database jew bħala message‑payloads:

  • Magic: 4 Bytes, eż. NBAE (kontroll mgħaġġel „Hu dan il‑format tagħna?”)
  • Verżjoni: 1 Byte (jippermetti migrazzjoni)
  • Parametri KDF: numru ta’ iterazzjonijiet (4 Bytes)
  • Salt: 16 Bytes (każwali għal kull fajl)
  • IV: 16 Bytes (każwali għal kull fajl għal AES‑CBC)
  • Ciphertext: dejta utli enkritpata (appoġġjata għal streaming)

Importanti: Salt u IV mhumiex sigrieti. Għandhom biss ikunu ġodda għal kull enkrizzjoni. Il‑password jibqa’ sigriet; il‑key derivat minn dak m’għandux jiġi maħżun.

Enkrizzjoni AES Delphi fil‑Stream: tikteb/taqra l‑kontenitur

Il‑kodiċi huwa skritt intenzjonalment bħala «pjan ta’ kostruzzjoni»: funzjonijiet separati b’mod ċar, header li jistgħu jiġu vverifikati, l‑ebda globals moħbija. Għall‑AES u PBKDF2 ħafna timijiet jużaw libreriji kripto stabbiliti (eż. DEC). Il‑biċċa kodiċi turi l‑format u l‑mudell tas‑streaming; is‑sejħiet għall‑AES/PBKDF2 huma kapsulati b’tali mod li tista’ tbiddilhom skont il‑librerija li tuża.

Delphi
unit Nb.AesContainer;

interface

uses
  System.SysUtils, System.Classes, System.NetEncoding;

type
  ENbCryptoError = class(Exception);

  TNbAesContainer = class
  public
    class procedure EncryptStreamToStream(const AIn: TStream; const AOut: TStream;
      const APassword: string; const AIterations: Cardinal = 200000);

    class procedure DecryptStreamToStream(const AIn: TStream; const AOut: TStream;
      const APassword: string);

    class function EncryptBytesToBase64(const APlain: TBytes; const APassword: string): string;
    class function DecryptBase64ToBytes(const ACipherB64: string; const APassword: string): TBytes;
  end;

implementation

const
  CMagic: array[0..3] of AnsiChar = ('N','B','A','E');
  CVersion: Byte = 1;
  CSaltLen = 16;
  CIvLen   = 16;

type
  TNbHeaderV1 = packed record
    Magic: array[0..3] of AnsiChar;
    Version: Byte;
    Iterations: Cardinal; // little endian
    Salt: array[0..CSaltLen-1] of Byte;
    IV: array[0..CIvLen-1] of Byte;
  end;

// --- Abhängigkeiten, die Sie je nach Crypto-Stack implementieren ---

procedure FillRandomBytes(var B: TBytes);
begin
  // Għall-istriming ta' ġenerazzjoni kriptografika: uża CSPRNG tal-OS
  // (Windows BCryptGenRandom, Linux getrandom/urandom).
  // Hawnhekk intenzjonalment bħala placeholder.
  raise ENbCryptoError.Create('FillRandomBytes: CSPRNG mhux imqabbad');
end;

function PBKDF2_HMAC_SHA256(const APassword: string; const ASalt: TBytes;
  const AIterations, AKeyLen: Cardinal): TBytes;
begin
  // Implementazzjoni eż. bil-DEC (PBKDF2) jew librerija oħra.
  // Riżultat: AKeyLen bytes.
  raise ENbCryptoError.Create('PBKDF2_HMAC_SHA256: mhux imqabbad');
end;

procedure AES256_CBC_EncryptStream(const AKey, AIV: TBytes; const AIn, AOut: TStream);
begin
  // Implementazzjoni permezz ta' librerija:
  // - KeyLen = 32 Bytes
  // - IVLen  = 16 Bytes
  // - PKCS#7 Padding
  // Importanti: ipproman b'mod orjentat lejn il-stream, mhux kollox fil-memorja.
  raise ENbCryptoError.Create('AES256_CBC_EncryptStream: mhux imqabbad');
end;

procedure AES256_CBC_DecryptStream(const AKey, AIV: TBytes; const AIn, AOut: TStream);
begin
  raise ENbCryptoError.Create('AES256_CBC_DecryptStream: mhux imqabbad');
end;

// --- Helper ---

procedure WriteHeaderV1(const AOut: TStream; const H: TNbHeaderV1);
begin
  if AOut.Write(H, SizeOf(H)) <> SizeOf(H) then
    raise ENbCryptoError.Create('Ma setax jinkiteb il-header');
end;

function ReadHeaderV1(const AIn: TStream): TNbHeaderV1;
var
  H: TNbHeaderV1;
begin
  if AIn.Read(H, SizeOf(H)) <> SizeOf(H) then
    raise ENbCryptoError.Create('Header mhux sħiħ');

  if (H.Magic[0] <> CMagic[0]) or (H.Magic[1] <> CMagic[1]) or
     (H.Magic[2] <> CMagic[2]) or (H.Magic[3] <> CMagic[3]) then
    raise ENbCryptoError.Create('Mhuwiex container validu (Magic ma taqbilx)');

  if H.Version <> CVersion then
    raise ENbCryptoError.CreateFmt('Verżjoni tal-container mhux magħrufa: %d', [H.Version]);

  if (H.Iterations < 10000) or (H.Iterations > 5000000) then
    raise ENbCryptoError.Create('In-numru ta iterazzjonijiet huwa barra mill-limiti raġonevoli');

  Result := H;
end;

class procedure TNbAesContainer.EncryptStreamToStream(const AIn, AOut: TStream;
  const APassword: string; const AIterations: Cardinal);
var
  H: TNbHeaderV1;
  Salt, IV, Key: TBytes;
begin
  if APassword = '' then
    raise ENbCryptoError.Create('Il-password ma tistax tkun vojta');

  // Salt/IV erzeugen
  // Ġenerazzjoni ta' Salt u IV
  SetLength(Salt, CSaltLen);
  SetLength(IV, CIvLen);
  FillRandomBytes(Salt);
  FillRandomBytes(IV);

  // Header befüllen
  Move(CMagic[0], H.Magic[0], Length(CMagic));
  H.Version := CVersion;
  H.Iterations := AIterations;
  Move(Salt[0], H.Salt[0], CSaltLen);
  Move(IV[0], H.IV[0], CIvLen);

  WriteHeaderV1(AOut, H);

  // Key ableiten (32 Bytes für AES-256)
  // Iddderiva l-key (32 bytes għal AES-256)
  Key := PBKDF2_HMAC_SHA256(APassword, Salt, AIterations, 32);

  // Nutzdaten verschlüsseln (Ciphertext folgt direkt nach Header)
  // Il-madwar tad-dejta jiġu kriptati (il-ciphertext isegwi direttament wara l-header)
  AES256_CBC_EncryptStream(Key, IV, AIn, AOut);
end;

class procedure TNbAesContainer.DecryptStreamToStream(const AIn, AOut: TStream;
  const APassword: string);
var
  H: TNbHeaderV1;
  Salt, IV, Key: TBytes;
begin
  if APassword = '' then
    raise ENbCryptoError.Create('Il-password ma tistax tkun vojta');

  H := ReadHeaderV1(AIn);

  SetLength(Salt, CSaltLen);
  SetLength(IV, CIvLen);
  Move(H.Salt[0], Salt[0], CSaltLen);
  Move(H.IV[0], IV[0], CIvLen);

  Key := PBKDF2_HMAC_SHA256(APassword, Salt, H.Iterations, 32);

  // Entschlüsseln ab aktueller Stream-Position (nach Header)
  // Id-dekriptaġġ jibda mill-pożizzjoni attwali tas-stream (wara l-header)
  AES256_CBC_DecryptStream(Key, IV, AIn, AOut);
end;

class function TNbAesContainer.EncryptBytesToBase64(const APlain: TBytes;
  const APassword: string): string;
var
  InS, OutS: TBytesStream;
begin
  InS := TBytesStream.Create(APlain);
  try
    OutS := TBytesStream.Create;
    try
      EncryptStreamToStream(InS, OutS, APassword);
      Result := TNetEncoding.Base64.EncodeBytesToString(OutS.Bytes, 0, OutS.Size);
    finally
      OutS.Free;
    end;
  finally
    InS.Free;
  end;
end;

class function TNbAesContainer.DecryptBase64ToBytes(const ACipherB64,
  APassword: string): TBytes;
var
  Cipher: TBytes;
  InS, OutS: TBytesStream;
begin
  Cipher := TNetEncoding.Base64.DecodeStringToBytes(ACipherB64);
  InS := TBytesStream.Create(Cipher);
  try
    OutS := TBytesStream.Create;
    try
      DecryptStreamToStream(InS, OutS, APassword);
      Result := OutS.Bytes;
      SetLength(Result, OutS.Size);
    finally
      OutS.Free;
    end;
  finally
    InS.Free;
  end;
end;

end.

Skop: Kontenitur minimali adattat għal fajls u BLOBs, inkluż verżjoni u parametri KDF. Kundizzjonijiet: Trid toħloq konnessjoni reali ma‘ CSPRNG (ġeneratur ta‘ numri pseudo każwali kryptografikament sigur mill-operating system) u twaħħal taħt implementazzjoni robusta ta‘ AES/PBKDF2. Perikli: Ma tużax „xi“ Random (ebda Random()), ebda IVs stabbiliti, u plana għal immaniġġjar ċar tal-iżbalji waqt id-decrypt (password ħażin vs. data maqduma). Varjanti: minflok CBC preferibbli AEAD (ara hawn taħt), jew iezzi header b’ID tal-algoritmu u HMAC.

Integrità: għaliex AES-CBC waħdu fil-operazzjoni huwa riskjuż

AES-CBC għadu preżenti f’ħafna kuntesti legacy u jista‘ jaħdem jekk tuża bħala komplement mekanizmu ta‘ assegurar l-integrità. Mingħajr integrità attakkant jista‘ jmaniġġja l-ciphertext; anke mingħajr attakkant attiv żbalji fil-ħruġ jew livelli tal-iskalata tal-ħażna jistgħu joħolqu żbalji tal-„Padding“ li huma diffiċli biex jiġu diagnostikati.

Għażliet pragmatiċi:

  • Encrypt-then-HMAC: Wara l-ciphertext ikteb HMAC (per eż., HMAC-SHA-256) fuq Header+Ciphertext. Meta taqra, iċċekkja l-ewwel l-HMAC, imbagħad id-dekrijpja. Għal dan, ideali tkun taderiva żewġ keys minn PBKDF2 (eż., 64 Bytes: 32 għall-AES, 32 għall-HMAC), minflok tuża l-istess key darbtejn.
  • AES-GCM: Modalità AEAD (Authenticated Encryption with Associated Data). Tipprovdi Ciphertext + Auth-Tag. Spiss din hi l-għażla l-iktar nadifa illum, jekk il-librerija Delphi tiegħek tappoġġja GCM b’mod stabbli. Il-kampijiet tal-header jistgħu jiġu awtentikati bħala „AAD“ mingħajr ma jkunu maħżuna b’kif encrypted.

Jekk trid tibqa‘ ma‘ CBC (pereżempju għal interoperabbiltà), Encrypt-then-HMAC hija l-komplement robust. Għall-format ġodda jiswa li tuża GCM, peress li tibgħat awtentikazzjoni mill-bidu u tagħti mudelli ta‘ żball aktar ċari.

Straordinarjament importanti: „Kryptografischer Zufall“ u għaliex System.Hash mhuwiex biżżejjed

Reflex legacy komuni f’proġetti Delphi: „Aħna sempliċement nieħdu SHA256 fuq timestamp + xi ħaġa u jkollna Random.“ Dan mhux bażi affidabbli. Għal salt u IV għandek bżonn CSPRNG (ġeneratur ta‘ numri pseudo każwali kryptografikament sigur) tal-system operattiv. Sotto Windows tipikament huwa l-API BCrypt (CNG), u sotto Linux ġeneratur tal-kernel bħall-getrandom() jew /dev/urandom. Id-differenza fil-prattika hi li CSPRNG huwa mfassal b’mod li minn valuri osservati ma jkun jista’ jsir previzjoni ta’ valuri futuri.

Trik tal-arkitettura: Kapsla dan f’unità żgħira „RandomProvider“ li tista‘ tmockja fit-tests. B’dan issolvi żewġ każijiet f’daqqa: testijiet riproduċibbli (bi seed fiss fil-mock) u sigurtà vera fil-produzzjoni (bi OS-CSPRNG). B’hekk tevita li f’hotfix wieħed jerġa‘ jidħol Random() sempliċement għax hu mgħaġġel.

Debugging u migrazzjoni legacy: ġestjoni tal-verżjonijiet mhix lussu

Il-header mhuwiex biss għal „estetika“ krittografika, iżda għall-manutenzjoni:

  • Tuning tal-Iterazzjonijiet: In-numri ta‘ iterazzjonijiet tal-PBKDF2 jinbidlu maż-żmien. Bi qasam fil-header tista‘ iżżid il-kumplessità aktar tard mingħajr ma tagħmel id-dejta antika mhux aċċessibbli.
  • Bidla tal-format: Eż., Verżjoni 2 tista‘ tivvjaġġa għal AES-GCM jew iżżid HMAC.
  • Dijanjosi fil-post: Magic/Version jippermettu kontrolli malajr fil-logs u fl-għodod mingħajr ma jkollok bżonn tid-dekrijpja d-dejta.

Suggeriment prattiku: Implimenta „Inspector“ żgħir li jaqra biss il-header (Magic/Version/Iterations) u jikteb fil-log. B’dan tissolvu ħafna każijiet ta’ appoġġ („Liema verżjoni hawn?“) mingħajr maniġġjar ta’ passwords.

Sauber migrieren: „Read old, write new“ statt Big Bang

Jekk trid tbiddel format antik (eż. IV fiss, l-ebda KDF, Blowfish/3DES, jew XOR mibni personalment), f’proġetti Delphi irreġistra mudell prattiku: waqt il-qar tiskopri diversi formati (Magic/Version jew euristika ta’ fallback), waqt il-ktieb tinħoloq biss il-format il-ġdid. Barra minn hekk, jekk jixraq lill-proċess, tista’ fuq suċċess ta’ dekrizzjoni terġa’ t-inkripta fil-background („lazy migration“). B’hekk tnaqqas ir-riskju ta’ rollout u tevita l-obbligu ta’ „kollox jerġa’ jiżħar“ bħala fenestra ta’ manutenzjoni.

Threading und Streaming: typische Kanten in Delphi

Il-kriptar normalment jiffunzjona f’worker-threads (eż. waqt l-esportazzjoni, waqt l-upload f’portal tal-klijent, waqt il-kitba ta’ arkivji kbar). Żewġ punti li jidhru regolarment f’proġetti Delphi:

  • Pożizzjonijiet tal-stream: Qabel tikkodifika/jiddeċodifika jkollok kuntratti ċari: l-input-stream jinqara mill-pożizzjoni kurrenti, l-output-stream jinkiteb mill-pożizzjoni kurrenti. Meta tirriutilizza streams kun żgur li tissettja Position := 0 b’mod konxju.
  • Spikes fil-memorja: Evita “kollox f’TBytes”. L-approċċ b’stream huwa kruċjali għal fajls kbar. Jekk il-librerija crypto tiegħek taċċetta biss byte-arrays, jiswa l-isforz addizzjonali biex tivverifika implimentazzjoni li tappoġġja streams jew biex toħloq adapter bufferjat.

Jekk tikkripta f’servizzi (Windows- jew Linux-Services), innota wkoll logging nadif tal-eċċezzjonijiet: „password żbaljat“, „header imkisser“, „tag/HMAC mhux validu“ huma każijiet operattivi differenti u għandhom ikunu distingwibbli. Importanti: il-messaġġi ta’ żball ma jridx ikun eċċessivament dettaljat lejn il-barra (ebda „padding żbaljat fil-block 7″ bħala żball API), imma internament fil-log jistgħu jkunu dettaljati.

Meta dan l-approċċ jiswa – u fejn jista’ jonqos

Jiswa, jekk inti: (a) taħżen b’mod lonġev dejta ta’ esportazzjoni/import imirkeb, (b) topera verżjonijiet differenti tal-programm parallelament, (c) tipproċessa dejta bħala streams, jew (d) għandek bżonn interfaċċa tal-crypto nadifa għal diversi moduli (Client/Server/Tooling).

Ma jkunx adattat, jekk tipprova b’dan issolvi “kollox”: Għall-Transport huwa responsabbli TLS, mhux wrapper AES mibni internament. Għall-Secrets (passwords, tokens) spiss ikun aktar sensat juża OS-Secret-Store jew Vault. U jekk għandek bżonn interoperabilità ma’ lingwi oħra, trid dokumentazzjoni eżatta tal-header, endianness u l-encoding (jew tuża format stabbilit).

Fazit: AES in Delphi ist weniger Algorithmus, mehr Engineering

Il-benefiċċju ewlieni ta’ dan il-framment mhuwiex biss “AES jaħdem”, imma format operattiv: salt każwali u IV, header versionjat, parametri PBKDF2 fil-payload u proċessar li jappoġġja streams. Għolli l-integrità għal formati ġodda fejn jista’ jkun (AES-GCM jew Encrypt-then-HMAC). B’hekk minn “aħna ninkriptaw xi ħaġa” isir komponent li f-soluzzjonijiet diġitali korporattivi jibqa’ manutenzjonabbli u migrabbli anke wara snin.

Jekk trid tintegra kontenitur bħal dan f’ambjent żviluppat ta‘ Delphi jew timmigra b’mod nadif minn format legacy, jiswa kontroll qasir tal-arkitettura (ġestjoni tal-muftieħ, verżjonijiet tal-format, operazzjoni/logging). Id-dettalji niddiskutuhom bi pjaċir f’laqgħa jekk meħtieġ:

Fil-kuntest tekniku jilgħabu wkoll Delphi Aes u Pbkdf2 Delphi rwol importanti, meta l-integrazzjonijiet, il-flussi tad-data u l-iżvilupp sussegwenti jridu jaħdmu b’mod koerenti u nadif.

Tiddiskuti proġett jew pjan ta‘ modernizzazzjoni ma‘ Net-Base.

Pass li jmiss

Meta suġġett jissarraf f’proġett reali, l-arkitettura, is-sistema eżistenti u l-operazzjoni għandhom jiġu kkunsidrati flimkien kmien.

Wir unterstuetzen nicht nur bei Einzelfragen, sondern auch dann, wenn aus Source-Schnipseln, Legacy-Themen oder Portalideen ein belastbares Unternehmensprojekt werden soll.

  • L-istat attwali, l-istat tal-mira u r-riskji tekniċi jiġu vvalutati flimkien.
  • REST, aċċess għad-dejta, portali u Rollout mhux se jiġu posposti bħala konsegwenzi tardivi.
  • Tara kmieni liema triq hija sostenibbli kemm mill‑punt ta’ vista ekonomiku kif ukoll mill‑punt ta’ vista operattiv.

Aqsam il-post

Aqsam dan il-post direttament

LinkedIn, X, XING, Facebook, WhatsApp u E-Mail huma immedjatament disponibbli. Għal Instagram nippreparaw il-link u t-test qasir direttament.

Imejl

Instagram jiftaħ f'tab ġdid. Il-link u t-test qasir jiġu kkopjati qabel fil-clipboard.