Ó théama an iris go cleachtas tionscadail
Leathanaigh seirbhíse agus teicniúla oiriúnacha don alt
Sa phraiticiúil, ní bhíonn an fhadhb go hiondúil leis an „AES fein“ féin ach le coinníollacha imeallacha: caithfidh sonraí a bheith próiseáilte mar shruth (comhaid, BLOBanna, cúltacaí), caithfidh seanfhormáidí a bheith inléite fós, agus sa táirgeadh teastaíonn inúsáidteacht le haghaidh dífhabhtaithe (Header, leaganú) agus socruithe réamhshocraithe slána (Salt/IV randamach, gan athúsáid). Mar sin, ní sheasann an slisín foinse seo ach le „Encrypt/Decrypt“ — léiríonn sé fomáid bheag, iontaofa le Header, Leagan, Salt agus IV — móide PBKDF2 don aisghineadh eochair agus áit ar féidir iontaofacht a chur leis go héifeachtach.
Cén fáth nach leor „sreang AES a chriptiú“ beagnach riamh
I bhogearraí ghnó indibhidiúla tagann criptiú de ghnáth ar fud trí chineál áiteanna: (1) Cumraíocht/Rúnaí (m.sh. sonraí rochtana), (2) comhaid malartaithe/easpórtála agus (3) sonraí i stádas neamhghníomhach (m.sh. cartlanna, coimeádáin doiciméad). Bíonn an cur chuige naíf „Pasfhocal → Eochair AES → Sreang isteach/amach“ ag teip go tapa:
- Athúsáid IV: I módanna cosúil le CBC nó GCM caithfidh veicteoir tosaíochta (IV) a bheith uathúil do gach criptiú. Is sceitheadh é IV seasta, fiú má tá an pasfhocal láidir.
- Eochair as pasfhocal gan KDF: Má úsáideann tú pasfhocal go díreach mar eochair (nó má dhéanann tú hash air uair amháin amháin) tugann tú cuireadh d’ionsaithe as líne. Cothaíonn KDF (Key Derivation Function) cosúil le PBKDF2 moill ar ionsaitheoirí go spriocdhírithe.
- Gan leagan fhormáid: Gan Header/Leagan beidh sé beagnach dodhéanta an líon n-itearuithe, an algartam nó paraiméadair a athrú níos déanaí gan sonraí sean a fhágáil gan úsáid.
- Gan iontaofacht: Criptíonn AES-CBC sonraí ach ní chuireann sé cosc ar mhodhnú. Gan fíordheimhniú (m.sh. HMAC nó AEAD cosúil le GCM) beidh tú ag fáil fadhbanna athrú giotán/padála agus patrúin earráide deacra a dhiagnósú.
Is é croílár an ailt seo: formáid coimeádáin bheag a thacaíonn le sruthú, atá in-athleagtha agus a sheachnaíonn na botúin chaighdeánacha.
AES Verschlüsselung Delphi le Header, Salt, IV agus PBKDF2
Sainmhíneofar formáid coimeádáin shimplí, ar féidir í a úsáid freisin i BLOBanna bunachar sonraí nó i paylóidí teachtaireachta:
- Comhartha ‚Magic‘: 4 Bait, m.sh.
NBAE(seiceáil tapa „An bhfuil sé seo ár bhformáid?“) - Leagan: 1 Bait (cuireann sé migriú ar chumas)
- Paraiméadair KDF: líon na n-itearuithe (4 Bait)
- Salt: 16 Bait (randamach do gach comhad)
- IV: 16 Bait (randamach do gach comhad don AES-CBC)
- Ciphertext: sonraí úsáide criptithe (tacaíonn le sruthú)
Tábhachtach: Níl Salt agus IV rúnda. Ní mór dóibh a bheith nua do gach criptiú. Fanann an pasfhocal rúnda; ní stóráiltear an eochair a ghintear uaidh.
AES Verschlüsselung Delphi sa sruth: Coimeádán a scríobh/a léamh
Tá an cód scríofa ar mhaithe le bheith mar “phlean tógála”: feidhmeanna go soiléir scartha, Header in-inniúchta, gan athróga domhanda ceilte. Do AES agus PBKDF2 úsáideann go leor foirne leabharlann cripteagrafaíochta cruthaithe (m.sh. DEC). Taispeánann an slisín an fhormáid agus an patrún sruthaithe; tá na glaonna AES-/PBKDF2 pacáilte ar bhealach gur féidir iad a mhalartú de réir an leabharlainne a roghnaíonn tú.
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;
// --- Spleáchais a bheidh le cur i bhfeidhm de réir an Crypto-Stack ---
procedure FillRandomBytes(var B: TBytes);
begin
// Maidir le randamacht cryptíochta: bain úsáid as CSPRNG an chórais (Windows BCryptGenRandom,
// Linux getrandom/urandom). Seo mar áiteoir.
raise ENbCryptoError.Create('FillRandomBytes: Níl CSPRNG nasctha');
end;
function PBKDF2_HMAC_SHA256(const APassword: string; const ASalt: TBytes;
const AIterations, AKeyLen: Cardinal): TBytes;
begin
// Cur i bhfeidhm, m.sh. le DEC (PBKDF2) nó le leabharlann eile.
// Toradh: AKeyLen Bytes.
raise ENbCryptoError.Create('PBKDF2_HMAC_SHA256: Níl cur i bhfeidhm nasctha');
end;
procedure AES256_CBC_EncryptStream(const AKey, AIV: TBytes; const AIn, AOut: TStream);
begin
// Cur i bhfeidhm trí leabharlann:
// - KeyLen = 32 Bytes
// - IVLen = 16 Bytes
// - PKCS#7 Padding
// Tábhachtach: Déan próiseáil ar an sruth, ná gach rud a luchtú isteach sa chuimhne.
raise ENbCryptoError.Create('AES256_CBC_EncryptStream: Níl cur i bhfeidhm nasctha');
end;
procedure AES256_CBC_DecryptStream(const AKey, AIV: TBytes; const AIn, AOut: TStream);
begin
raise ENbCryptoError.Create('AES256_CBC_DecryptStream: Níl cur i bhfeidhm nasctha');
end;
// --- Cúntóir ---
procedure WriteHeaderV1(const AOut: TStream; const H: TNbHeaderV1);
begin
if AOut.Write(H, SizeOf(H)) <> SizeOf(H) then
raise ENbCryptoError.Create('Níorbh fhéidir an ceanntásc a scríobh');
end;
function ReadHeaderV1(const AIn: TStream): TNbHeaderV1;
var
H: TNbHeaderV1;
begin
if AIn.Read(H, SizeOf(H)) <> SizeOf(H) then
raise ENbCryptoError.Create('Ceanntásc neamhiomlán');
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('Ní coimeádán bailí (Magic stimmt nicht)');
if H.Version <> CVersion then
raise ENbCryptoError.CreateFmt('Leagan coimeádáin anaithnid: %d', [H.Version]);
if (H.Iterations < 10000) or (H.Iterations > 5000000) then
raise ENbCryptoError.Create('Uimhir na n-iterations lasmuigh de theorainneacha réasúnta');
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('Ní cheadaítear pasfhocal folamh');
// Salt/IV a ghiniúint
SetLength(Salt, CSaltLen);
SetLength(IV, CIvLen);
FillRandomBytes(Salt);
FillRandomBytes(IV);
// Ceanntásc a líonadh
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);
// Eochair a ghiniúint (32 Bytes do AES-256)
Key := PBKDF2_HMAC_SHA256(APassword, Salt, AIterations, 32);
// Sonraí úsáide a chriptiú (Ciphertext folgt direkt nach 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('Ní cheadaítear pasfhocal folamh');
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);
// Díchriptiú ag tosú ón suíomh reatha sa sruth (tar éis an cheanntásc)
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.Cuspóir: Coimeádán íosta oiriúnach do chomhaid agus BLOBanna, lena n-áirítear leaganú agus paraiméadair KDF. Coinníollacha: Caithfidh tú nasc CSPRNG fíor (randam criptografaíoch slán ón gcóras oibriúcháin) agus cur i bhfeidhm AES/PBKDF2 láidir a chur faoi. Rioscaí: Ná húsáid ach ‘Random’ ar bith (ní Random()), ná IVanna seasta; pleanáil láimhseáil earráide shoiléir don díchriptiú (pasfhocal mícheart vs. sonraí truaillithe). Eagsúlachtaí: in ionad CBC úsáid AEAD (féach thíos), nó an Header a leathnú le ID algartaim agus HMAC.
Ionracas: cén fáth go bhfuil AES-CBC ró-rioscaireach má úsáidtear é leis féin
Tá AES-CBC fós i láthair i go leor comhthéacsanna oidhreachta agus d’fhéadfadh sé oibriú má úsáideann tú tacaíocht ionracais bhreise. Gan ionracas, is féidir le hionsaitheoir an ciphertext a mhodhnú; fiú gan ionsaí gníomhach, d’fhéadfadh earráidí tarchuir nó sraitheanna stórála lochtacha earráidí “padding” a ghiniúint a bhíonn deacair a dhiagnóisiú.
Roghanna praiticiúla:
- Encrypt-then-HMAC: Scríobh HMAC (m.sh. HMAC-SHA-256) tar éis an ciphertext ar an Header + ciphertext. Ag léamh, seiceáil an HMAC ar dtús, ansin díchriptiú. Chuige sin, tá sé idéalach dhá eochair a fhoilsiú ó PBKDF2 (m.sh. 64 byte: 32 don AES, 32 don HMAC), in ionad an eochair chéanna a úsáid dhá uair.
- AES-GCM: Mód AEAD (Authenticated Encryption with Associated Data). Soláthraíonn sé ciphertext + Auth-Tag. Go minic is é seo an rogha is soiléire faoi láthair, má thacaíonn do leabharlann Delphi le GCM go seasmhach. Is féidir réimsí Header a chur mar “AAD” a fhíordheimhniú gan iad a chriptú.
Má tá ort fanacht le CBC (m.sh. de bharr idir-oibriúlachta), is é Encrypt-then-HMAC an forlíonadh iontaofa. Maidir le formáidí nua, is fiú GCM toisc go bhfaigheann tú fíordheimhniú mar chuid den phróiseas agus go mbíonn patrúin earráide níos soiléire.
Go háirithe tábhachtach: „Randaim criptografaíoch“ agus cén fáth nach leor System.Hash
Réaltacht choitianta i dtionscadail oidhreachta Delphi: “Glacfaimid SHA256 ar thimpeall an ama + rud éigin agus beidh Random againn.” Ní bunús iontaofa é sin. Maidir le salt agus IV, teastaíonn CSPRNG (Cryptographically Secure Pseudo Random Number Generator) ón gcóras oibriúcháin. Faoi Windows is gnách go mbaintear úsáid as an BCrypt-API (CNG), faoi Linux gineadóir an chroí-chóras cosúil le getrandom() nó /dev/urandom. Tá an difríocht praiticiúil: tá CSPRNG deartha ionas nach féidir luachanna amach anseo a thuar bunaithe ar luachanna atá feicthe.
Cleas ailtireachta: pacáigh é i aonad beag “RandomProvider” is féidir leat a mhochamáil i dtástálacha. Mar sin réitíonn tú dhá chás ag an am céanna: tástálacha inathnuaite (le seed seasta sa mock) agus slándáil fhíor i mbun táirge (le OS-CSPRNG). Mar seo seachnófar go n-ionsóidh Random() arís i hotfix toisc go bhfuil sé níos tapúla sin a dhéanamh.
Dífhabhtú agus inimirce oidhreachta: Níl leaganú ina só
Níl an Header ann ar son “álainn cryptó” amháin — tá sé riachtanach don chothabháil:
- Chóiriú Idirghníomhartha: Athraíonn líon na n-idirghníomhartha PBKDF2 thar na blianta. Le réimse sa Header is féidir duit an líon idirghabhálacha a ardú níos déanaí gan sonraí sean a dhéanamh neamh-inléite.
- Aistriú formáid: D’fhéadfadh Leagan 2, mar shampla, athrú go AES-GCM nó HMAC a chur leis.
- Diagnóis sa réimse: Ceadaíonn Magic/Version seiceálacha tapa i logaí agus uirlisí gan sonraí a díchriptú.
Leid phraiticiúil: Cur i bhfeidhm iniúchóra beag a léann ach an cheannlíne (Magic/Version/Iterations) agus a scríobhann í isteach i log. Mar sin réiteoidh tú go leor cásanna tacaíochta („Cén leagan atá anseo?“) gan bainistiú pasfhocail.
Aistriú glan: „Read old, write new“ seachas Big Bang
Nuair a chuirtear deireadh le seanfhormáid (m.sh. IV socraithe, gan KDF, Blowfish/3DES, nó XOR féin-dhéanta), tá patrún aitheanta i bhforbairtí Delphi: Beim ag léamh déanann tú aithint ar roinnt formáidí (Magic/Version nó heurstic fhillte), beim ag scríobh cruthaíonn tú ach an fhormáid nua. Ina theannta sin is féidir, tar éis díochriptithe rathúil, ath-criptiú a dhéanamh sa chúlra (“lazy migration”) má oireann sé don phróiseas. Laghdaíonn sé sin an riosca rollaithe agus seachnaíonn sé an riachtanas “arís ar fad a ath-criptiú” mar fhuinneog cothabhála.
Snáithithe agus sruthú: imeallacha tipiciúla i Delphi
Is minic a ritheann criptú i snáitheanna oibre (m.sh. le linn onnmhairiúcháin, le linn uaslódála isteach i Kundenportal, nó agus ag scríobh argóintí móra). Dhá phointe a thaispeántar go minic i bhforbairtí Delphi:
- Suíomh srutha: Sainmhínigh conarthaí soiléire sula gcriptítear nó sula ndí-criptítear: léitear an Input-Stream ón suíomh reatha agus scríobhtar an Output-Stream ón suíomh reatha. Nuair a úsáidtear sruthanna arís agus arís eile, socraigh go héadrom
Position := 0. - Buaicphointí cuimhne: Seachain “gach rud i TBytes”. Tá an cur chuige srutha riachtanach do chomhaid mhóra. Má ghlacann do leabharlann chripteo ach le hearnálacha byte, is fiú an obair bhreise a dhéanamh chun cur i bhfeidhm atá in ann sruthú a thacaíonn leis nó adapter maolaithe a thógáil.
Má chripteálann tú i seirbhísí ({{NBML_TERM_2_aea23489}}- nó Linux-Services), tabhair aird ar logging eisceachtúil glan freisin: tá “pasfhocal mícheart”, “ceannlíne briste”, “Tag/HMAC neamhbhailí” mar chásanna oibríochta difriúla agus ba chóir iad a idirdhealú. Tábhachtach: níor chóir go mbeadh teachtaireachtaí earráide ró-mhionsonraithe taobh amuigh (níor chóir “Padding mícheart sa Bloc 7” a thabhairt mar earráid API), ach is féidir iad a bheith mionsonraithe sa log inmheánach.
Cathain is fiú an cur chuige — agus cá bhféadfadh sé teip
Is fiú é, más gá duit: (a) sonraí onnmhairiúcháin/ionnmhairiúcháin criptithe a stóráil go buan, (b) leaganacha éagsúla den chlárlann a oibriú go comhthreomhar, (c) sonraí a phróiseáil mar shruthanna, nó (d) comhéadan criptithe glan a bheith agat do roinnt modúl (Client/Server/Tooling).
Teipeann sé, má dhéanann tú iarracht leis an gcur chuige seo “gach rud” a réiteach: is é TLS atá freagrach as an transport, ní wrapper AES féin-dhéanta. Maidir le secrets (pasfhocail, tokenanna) b’fhearr stórais rúnda an chórais oibriúcháin nó Vault a úsáid de ghnáth. Agus má dteastaíonn comhoiriúnacht le teangacha eile, ní mór duit an Header, endianness agus encoding a dhoiciméadú go cruinn (nó formáid bhunaithe a úsáid).
Conclúid: Tá AES i Delphi níos lú faoi algartam, níos mó faoi innealtóireacht
Ní “go n-oibríonn AES” an phríomhchiall den phacáiste seo, ach formáid oibríochta inúsáidte: Salt agus IV randamach, ceannlíne le leagan, paraiméadair PBKDF2 sa payload agus próiseáil atá in ann sruthú. Cuir iontaofacht leis do fhorbairtí nua más féidir (AES-GCM nó Encrypt-then-HMAC). Mar sin athraítear “níos mó ná rud éigin a chriptiú” go codán a fhéadfaidh fanacht cothabhálach agus inaistrithe i réitigh fhiontraíochta dhigiteacha fiú tar éis blianta.
Má tá ort coimeádaí den sórt sin a chomhtháthú i dtimpeallacht Delphi atá fhorbartha cheana nó é a aistriú go glan ó fhormáid Legacy, is fiú seiceáil ghearr ar an ailtireacht (bainistíocht eochracha, leaganacha formáide, oibriú/logáil). Sonraí a shoiléiriúfaimid de réir mar is gá i gcomhrá:
Sa chomhthéacs ghairmiúil, tá ról tábhachtach ag Delphi Aes agus Pbkdf2 Delphi freisin, nuair is gá go n-oibreoidh comhtháthuithe, sreafaí sonraí agus forbairt leanúnach go glan le chéile.
Céim eile
Nuair a éiríonn an t-ábhar seo ina thionscadal fíor, ba chóir ailtireacht, an córas reatha agus an t-oibriú a mheas le chéile go luath.
Ní hamháin go dtacaímid le ceisteanna aonair, ach freisin nuair is gá ó shlisíní cód foinse, ó ábhair legacy nó ó smaointe portail tionscadal corparáideach iontaofa a fhorbairt.
- Measúnítear an staid reatha, an stát sprioc agus na rioscaí teicniúla le chéile.
- Ní chuirfear REST, rochtain ar shonraí, portalí agus Rollout siar mar iarmhairtí.
- Feiceann sibh go luath cé acu an cosán atá inbhuanaithe ó thaobh eacnamaíochta agus oibríochta.