. Comunicarea Intre Doua Sisteme Haotice In Timp Discret
MEMORIU TEHNIC
I. Criptologia
1. Criptografia
Criptografia este un „ ansamblu de tehnici care permit protectia informatiilor datorita unui cod secret”. Ea studiaza in special metode pentru securizarea informatiilor in fata unor atacuri intentionate. Aceste metode de cifrare sunt bazate in general pe algoritmi matematici foarte dificili de rezolvat daca nu avem cheile de cifrare.
Pentru a face un mesaj „ilizibil”, de neinteles pentru un interceptor avem mai multe posibiliatati, dintre care enumeram :
Repetarea de mai multe ori a aceluiasi caracter, acesta este un cod cu repetitie.
Inlocuirea unui caracter cu un altul, substitutia.
Schimbarea ordinii caracterelor intr-un cuvant, transpozitia.
Un mesaj este numit texte en clair. Procesul de „transformare” a unui mesaj intr-o asemenea maniera de a-l face incomprensibil este denumit cifrare. Rezultatul acestui proces de cifrare este numit text cifrat (criptograma). Procesul de reconstuctie al textului original pornind de la textul cifrat este numit decifrare. Figura urmatoare ilustreaza poate mai bine toate aceste procese :
Textul in clar poate fi o suita de biti, un fisier text , o imagine video digitala,….dar toate aceste date pentru un calculator sunt doar informatii binare.
Servicii de securitate: criptografia permite folosirea mai multor servicii de securitate avand ca obiectiv protejarea datelor sau a tranzactiilor in forma electronica:
Confidentialitatea : Confidentialitatea este un serviciu care impiedica citirea mesajului de catre persoanele neautorizate, bazandu-se pe un transfer sigur. Cifrarea informatiilor constituie tehnica cea mai adecvata pentru a implementa acest serviciu.
Integritatea datelor : Controlul integritatii datelor consista in a putea fi siguri ca acestea in drumul lor de la expeditor la destinatar, nu au fost modificate accidental sau de ce nu, intentionat. Nu reprezinta neaparat o metoda a criptologie pentru ca functia de integritate a datelor nu necesita cifrare.
Non repudiation : Este un serviciu care permite obtinerea dovezii de emitere a unui mesaj (repudiation of submission) sau de receptia lui (repudiation of delivery); cu alte cuvinte nici emitorul nici receptorul nu pot nega trimiterea respectiv receptia unui mesaj.
Autentificarea : In principal acest serviciu permite asigurarea ca corespondentul este cel dorit. Autentificarea partenerilor de dialog.
Sunt mai multe posibilitati de a face un mesaj ilizibil, aceasta depinzand de securitatea si confidentialitatea de care avem nevoie. Este clar ca pentru a avea un plus de securitate avem nevoie de algiritmi puternici.
2. Analiza criptografica
2.1. Securitatea sistemelor criptografice
Diferitii algoritmi au nivele de securitate diverse, mai usor sau mai dificil de spart. Daca costul necesar pentru spargerea unui astfel de algoritm depaseste valoarea informatiei cifrate, atunci este posibil ca acest algoritm sa fie sigur. Daca timpul necesar pentru spargerea unui algoritm este mai mare decat timpul in care informatia cifrata trebuie sa ramana secreta, atunci este posibil ca acest algoritm sa fie sigur. Cuvantul „probabil” este folosit in aceste explicatii pentru ca oricand este posibil ca in criptanaliza sa se găsească noi „soluții”.
Lars Knudsen a clasat diferite modalități de a sparge un algoritm astfel :
Spargerea completa. Un criptanalist gaseste cheia k astfel incat .
Obtinerea globala. Un criptanalist gaseste textul in clar al unui mesaj cifrat, anterior interceptat.
Obtinerea de informatii. Un criptanalist obtine ceva informatii referitoare la textul in clar, sau referitoare la cheie. Aceste informatii pot fi, fie cativa biti din cheie, parti din text sau combinatii ale acestora.
Un algoritm este neconditionat sigur daca nu exista informatii suficiente pentru a determina textul in clar. Toate celelalte criptosisteme sunt vulnerabile unui atac la text cifrat simplu, pur si simplu prin incercarea tuturor cheilor posibile una cate una si privind daca rezultatul are vreun sens. Acest atac se numeste atac exaustiv.
Criptografia se ocupa in special de criptosistemele invulnerabile prin calcul. Un algoritm este considerat invulnerabil prin calcul daca nu poate fi spart folosind resursele disponibile actuale sau viitoare. Prin resurse disponibile se poate vorbi de cantitatea de memorie necesara pentru a efectua atacul, timpul necesar pentru a desfasura atacul (numit si efort) sau cantitatea de informatii necesare la intrarea algoritmului.
Dupa ce am clasificat putin securitatea in ceea ce priveste criptosistemele, sa aruncam o privire de ansamblu si asupra atacurilor care pot avea loc:
2.2. Atacurile criptografice
Sunt patru tipuri generice de atacuri cript-analitice. Insa trebuie tinuta seama ca fiecare dintre ele porneste de la ipoteza ca cript-analistul cunoaste algoritmul de cifrare.
Atacul cu text cifrat. Cript-analistul dispune de textele cifrate ale mai multor mesaje, toate fiind la randul lor cifrate cu acelasi algoritm. Munca pe care trebuie sa o depuna cript-analistul este de determina textul in clar a cat mai multor mesaje trimise sau si mai mult, de a gasi cheile care au fost folosite la cifrarea mesajului, ceea ce va permite descifrarea viitoarelor mesaje ce vor fi cifrate cu aceleasi chei.
Atacul cu text in clar cunoscut. Cript-analistul nu doar ca are acces la textele cifrate ale mai multor mesaje, ba mai mult, chiar si la textele in clar corespunzatoare acestor mesaje.Totul in scopul de a determina cheile utilizate pentru cifrarea acestor mesaje, sau determinarea unui algoritm care sa permita descifrarea oricarui alt nou mesaj cifrat cu aceste chei.
Atacul cu text in clar ales. Cript-analistul nu doar ca are acces la textele cifrate si cele in clar, ba in plus el isi poate alege textele in clar pe care sa le cifreze. Aceste atacuri sunt mai eficace decat anterioarele pentru ca cript-analistul isi poate alege pentru a cifra texte speciale care sa dea cat mai multe informatii despre cheie. Toate acestea in scopul de a determina cheile utilizate pentru cifrarea acestor mesaje, sau determinarea unui algoritm care sa permita descifrarea oricarui alt nou mesaj cifrat cu aceste chei.
Atacul cu text in clar ales adaptiv. Acesta este un caz particular al atacului cu text in clar ales. Diferenta consta in faptul ca cript-analistul isi poate adapta alegerea textelor ce vor fi cifrate in functie de rezultatele celorlalte incercari. In cazul atacului cu text clar ales cript-analistul este „autorizat” in a alege doar un bloc mare de text in clar, pe cand atacul cu text in clar ales adaptiv permite alegerea unui bloc de pornire mai mic, si apoi poate alege altele in functie de rezultatele anterioare.
2.3. Metode de atac
1. Atacul statistic
Acest atac consta in a recunoastere diferitele caracetere ale unui text, bazandu-se pe rezultatele unui analize statistice. Acesta analiza depinde in mare masura de limba in care este scris textul. Daca de exemplu, textul in clar este scris in limbaj natural, inamicul poate exploata faptul ca frecventa de aparitie a literei ‘E ‘ este foarte ridicata, ca litera ‘Q’ este aproape tot timpul urmata de un ‘U’, etc. Daca este vorba codului ASCII inamicul se va putea ‘lega’ de faptul ca anumite combinatii nu apar niciodata (caracterele de control).
2. Atacul in frecventa
Inamicul face o Transformata Fourier (TF) a semnalului cifrat, izoleaza banda de frecventa a semnalului util, inlatura celelalte frecvente ce constituie zgomotul si realizeaza o transformata Fourier Inversa. Aceasta metoda implica cunoastrea aproximativa a benzii de frecventa a semnalului cautat.
Idealul este de a nu exista alt atac mai bun decat cel numit exhaustiv sau sistematic care consta in a incerca diferite chei de descifrare una dupa cealalta pana la obtinerea celui cautate. Un astfel de atac are nevoie in medie de k/2 incercari, in care k este numarul de chei posibile. Vom alege deci k destul de mare, tinand cont de tehnologiile actuale. Tipic, un k=232 este putin fiabil, in timp ce k=264 pare suficient. ( sunt apoximativ 500.000 ani in 264microsecunde).
Pentru proiectul nostru am decis sa folosim criptarea haotica ! Dar inainte de toate ce este haosul?
II. Haosul
1. Ce este haosul ?
O simpla analiza a cunostintelor noastre generale despre lume permite impartirea lucrurilor in doua mari clase: cea a ordinii si cea a dezordinii. Suntem tentati sa le asociem cu dihotomia: bine – rau, caci este de preferat sa fii inconjurat de lucruri sau evenimente ce se desfasoara in spatiu sau timp dupa reguli clare, cunoscute. Este o placere sa ajungi in statia de troleibuz la ora 9 si 39 de minute stiind ca exact la 9 si 40, vehicolul se opreste, deschide ca intotdeauna usa si, la fel de ordonat, lumea urca, fara socuri, fara dezordine. Dar mai este oare o placere sa constati aceeasi ordine, aceeasi stereotipie bine stapanita, intr-un spatiu destinat creatiei artistice? Sa patrundem la ora 9 si 39 in holul apartamentului unui mare pictor sa zicem, stiind ca la ora 9:40 fix el ne va inmana capodopera tocmai terminata, corespunzator contractului de a genera la termene bine determinate numai valori "universale"?!
Nu, sigur nu mai este acelasi lucru. Am putea conchide ca, acolo unde lucrurile sunt clare, iar scopul sistemului este doar de a reproduce un flux tehnologic, de a reproduce o actiune ce implica sincronizari de persoane, ordinea este absolut necesara. Intr-un asemenea sistem, predictibilitatea oricarei actiuni este asigurata de chiar structura si functionarea sistemului. Este imperiul ordinii, al "staticului", in care nimic nu poate sa surprinda, in care o variatie este sinonima accidentului.
La polul opus, starea de dezordine pare sa fie, pana la interventia unor factori coercitivi, structuranti, starea normala a unui sistem. Interactiunea dintre numeroase celule ce alcatuiesc un sistem complicat (suma moleculelor ce formeaza un gaz, suma indivizilor ce formeaza un grup, o societate) conduce la o variabilitate normala a parametrilor masurabili. In consecinta, nu este posibila predictia decat in limite statistice, ce nu ne prea ajuta intr-o situatie data. Starea de frustrare este clara daca autobuzul nu vine atunci cand am nevoie de el, chiar daca in rest si in medie el este "de gasit pe traseu"?! Spunem imediat ca in acel sistem este dezordine, la limita chiar anarhie. Intr-o asemenea situatie, sincronizarile dintre persoane sau dintre dorinte individuale sunt doar accidentale. Intr-o societate in care fiecare subsistem se manifesta liber, in sensul de neingradit, dupa bunul plac, se mai spune ca domneste haosul.
Termenul de « haos » a fost intordus in literatura de specialitate de catre TIEN-Yien Li si James A. Yorke in 1975 in lucrarea intitulata "Period Three Implies Chaos". « Haosul » a fost definit ca si comportamentul imprevizibil al sistemelor deterministe. Astfel, el poate fi definit prin confuzie sau o dezordine grava.
Deci, ideea unei teorii despre haos sau a unei metodologii privind controlul haosului, este pentru un neavizat o aberatie, ea fiind asociata fie conceptului de dezordine, fie unor termeni ce amintesc de procesul genezei din teologie. Din pacate, aceasta confuzie referitoare la termenul de haos a fost generata de o alegere nefericita, poate gazetareasca, a unei etichete pentru un domeniu de studiu fascinant, descoperit in acest final zbuciumat de mileniu. Pentru unii a insemnat chiar motivul abordarii, caci credeau ca vor obtine informatii transcendente, dar au dat de o matematica "arida", de experimente cu ecuatii diferentiale si au abandonat. Nu au mai ajuns sa afle despre extraordinarele aplicatii practice ale acestui minunat capitol al cunoasterii stiintifice: stabilizarea sistemelor neliniare, comunicarea prin haos, haoticitatea inimii si starea de sanatate, structura haotica a unui semnal encefalografic si restabilirea haoticitatii normale a activitatii neuronale in tratamentele de epilepsie, si cate si mai cate.
Pentru altii,ronale in tratamentele de epilepsie, si cate si mai cate.
Pentru altii, si aici este mai grav, caci printre ei sunt si matematicieni sau fizicieni, termenul a actionat ca un filtru ce a determinat anularea oricarei sanse de contact cu studii privind comportarile haotice din natura, caci a fost asociat cu filozofia sau teologia, domenii ce nu "fac bine" in societatea moderna.
Am vazut in general ca cel mai usor este sa se asocieze cuvantului haos cel de dezordine sau confuzie. Incercam sa accentuam intrebarea: a cui este confuzia? Este ea principiala, a sistemului ce nu s-a organizat inca, sau este o proprietate a mintii celui ce nu percepe ordinea existenta in suma de variabile ce il inconjoara? Este o proprietate a lucrului observat sau a observatorului?
Se cunoaste in matematica sau in fizica existenta unor sisteme ce manifesta sensibilitate la conditii initiale. Altfel spus, o eroare (epsilon =0.000…1), conduce, mai repede sau mai tarziu, la stari finale diferite. Din acest motiv, predictia in aceste sisteme este dificila in principiu. Nu putem controla starea initiala si astfel, sistemul evolueaza pe cai diferite. Oricat de mica ar fi diferenta aleasa, mai repede sau mai tarziu, cele doua grafice nu mai au nimic in comun. O mica eroare ne poate duce in alta parte!
Din punct de vedere tehnic, termenul de „haos” defineste o stare particulara a unui sistem caracterizat prin urmatoarele:
nu se repeta niciodata (pare neregulat),
exista o dependenta a sensibilitatii in raport cu conditiile initiale: diferente extrem de mici ale valorilor diferitilor parametrii pot duce la rezultate divergente,
dar este mai putin ordonat si poate fi caracterizat de un determinism imprevizibil. Determinismul imprevizibil inseamna ca pana si un model perfect de sistem haotic (ecuatii de miscare identice si aceleasi conditii initiale ) poate duce la rezulate imprevizibile.
Sistemele in stare haotica sunt deci ordonate, deterministe si imprevizibile. Descoperirea acestor sisteme haotice necesita notiuni aparent paradoxale de haos si determinism. Este foarte adevarat ca sisteme „foarte simple” respecta reguli perfect deterministe si totusi comportamentul lor este total imprevizibil. Acesta imprevizibilitate nu este fructul hazardului ci de sensibiliatea la conditiile initiale. Determinist pentru ca efectele pot fi masurate si localizate cu precizie determinand continuarea evenimentelor. Haos pentru ca nu stim tot din ceea ce se va intampla, in ciuda faptului ca cunoastem toate datele care determina evenimentele.
Acum ca definit cat de cat haosul, o sa vedem doua modalitati de a ulitiza haosul cu scopul de a cifra informatii.
2. Metode de cifrare
2.1. Metoda prin aditie
Aceasta tehnica utilizata de catre profesorul Sira Ramirez in articolul sau de cercetare, este utilizata in criptografia bazata pe semnalele haotice de la inceputul anilor 90. Care este principiul de functionare al metodei? Acesta consta in a crea separat sistemul haotic si informatia si apoi in a aditiona cele doua semnale. La randul sau interlocutorul are cheile sistemului ( in cazul nostru conditiile initiale si ecuatiile sistemului – pe care i le-am trimis in prealabil ) cu care isi poate crea la randul sau un sistem haotic ca cel de la emisie. Cand receptioneaza mesajul aditionat al sistemului haotic, nu are nimic altceva de facut de a recuperea mesajul extragand « masca ».
Schema clasica pentru cifrarea si descifrarea unui mesaj, folosind metoda prin aditie, este urmatoarea:
In mijlocul echipei E.C.S. (Equipe Commandes Systèmes) a Facultatii E.N.S.E.A din Cergy-Pontoise a fost elaborata o alta strategie de utilizare a haosului in sistemele criptografice. Este metoda prin includere.
2.2. Metoda prin incluziune
Modelul de transmisie utilizand tehnica de criptare prin incluziune, este urmatoarea:
In acest caz, mesajul nu este doar înecat in haos, ba chiar el este adanc acuns in structura sistemului haotic, reprezentand inca un obstacol pentru un spion in incercarea lui de a descifra mesajul.
Mesajul nu este deci transportat de catre purtatoarea haotica prin linia de transmisie, ci el este propria lui purtatoare. Pe aceasta linie vom gasi doar datele emitorului care ii vor permite destinatarului sa descopere mesajul transmis.
Diferenta intre metoda prin aditie si cea prin incluziune este ca in acest ultim caz, mesajul nu este « regasit » in receptor, ci este « reconstituit » de catre acesta.
Desi aceasta metoda este probabil mai greu sa criptanalizat, exiasta totusi inconvenientul de a fi dificil de pusa in practica, datorita problemelor de sincronizare intre cele doua sisteme haotice: cel de la emisie si cel de la receptie.
III. Protocoale
1. Introducere in protocoale
Un protocol reprezinta este o serie de etape, care implica doi sau mai muti participanti, conceput pentru a face o operatie. De ce « o colectie de etape »? acesta vrea sa spuna ca un protocol este o suita ordonata de etape, si ca are un inceput si un sfarsit. Fiecare etapa trebuie executata la randul sau si nici o alta etapa nu poate fi executata pana cand precedenta nu s-a terminat. Expresia « doi sau mai multi participanti » indica faptul ca trebuie cel putin doua persoane pentru a realiza un protocol; o persoana izolata nu poate realiza un protocol. Este adevarat ca o persoana singura poate realiza o serie de etape pentru a realiza o operatie, insa acesta nu este un protocol. Nu in ultimul rand, expresia « conceput pentru a realiza o operatie» indica faptul ca un protocol trebuie sa faca ceva. Ceea ce se aseamana cu un protocol dar care nu face nimic, nu este nimic altceva decat o pierdere
de timp. [1]
Protocoalele au si alte caracteristici:
fiecare participant la protocol trebuie sa cunoasca protocolul si toate etapele ce urmeaza ;
fiecare participant implicat intr-un protocol trebuie sa fie de acord pentru a adera la
acesta ;
protocolul trebuie sa fie clar: fiecare etapa trebuie perfect definita si nu trebuoie lasat loc pentru interpretari ;
un protocol trebuie sa fie complet:trebuie sa aiba o actiune specifica la fiecare situatie posibila .
Dar inainte de toate, un protocol trebuie sa fie eficace. Iata in cele ce urmeaza cateva caracteristici esentiale pentru ca un protocol sa fie eficace :
O conceptie tehnica adecvata. Ea trebuie sa raspunda cerinteleror din industie sau tehnica. Asta vrea sa spuna ca protocolul trebuie in principal un produs al inginerilor, nu al comerciantilor.
Un proces de dezvoltare si intretinere deschis. O dezbatere „publica” asupra protocolului trebuie sa existe sub o forma sau alta. Intretinerea protocolului trebuie sa participarea diferitilor actori, care sunt interesati de acesta.
Accesibiliatea. Trebuie sa fie publicat, accesibil in mod liber si permanent pentru toata lumea.
Folosirea fara restrictii. Nu trebuie sa existe restictii in ceea ce priveste utilizarea protocolului. Cineva care doreste sa realizeze o aplicatie bazata pe acest protocol trebuie sa poate face asta fara a intampina nici un fel de obstacol din punct de vedere legal sau financiar.
Un protocol criptografic este un protocol utilizat in crotiptografie. Participantii pot da fie prieteni care au implicit incredere unuk in celalalt , sau de ce nu , dusmani, care sa nu aiba incredere unul in celalalt. Un protocol criptografic utilizeaza anumiti algotritmi criptografici, dar in general scopul unui protocol depaseste simpla problema a confidentialitatii. Participantii la protocol pot dori sa partajeze un secret referitor la calculul unei valori, sa genereze o continuare aleatorie, sa isi convinga interlocutorii de catre identitatea sa, sau sa semnene simultan un cantract. Interesul utilizarii criptografiei intr-un protocol este de a impiedica sau detecta spionajul sau inselatoria. Sunt multe protocoale, in unele unul dintre participanti poate incerca sa ii corupa ce ceilalti. In altele, un spion poate altera protocolul sau obtine informatii secrete. Anumite protocoale esuaeaza in definirea regulilor, altele esueaza pentru ca autorii lor au dat lipsa de meticulozitate in analiza lor. La fel ca si in cazul unui algoritm, este mult mai dificil de a demonstra ca un protocol este sigur decat contrariul.
2. Scopul protocoalelor
In viata de zi cu zi, exista protocoale pentru aproape tot: comanda de marfuri prin telefon, jocul de poker, votul electronic. Nimeni nu se gandeste cu adevarat la ele; ele se evolueaza de-a lungul timpului, toata lumea stie cum sa le utilizeze si functioneaza.
In zilele noastre interactiunea umana se face tot mai mult prin intermediul retelelor informatice si nu fata in fata. Calculatoarele au nevoie de protocoale pentru a face ceea ce oamenii realizeaza fara sa se gandeasca. De exemplu, daca va mutati in alta tara unde gasesti un birou diferit de cel cu care ati fost obisnuit, va veti adapta foarte usor. Calculatoarele nu sunt asa de flexibile. O sumedenie de protocoale „fata-in-fata” necesita prezenta oamenilor pentru a asigura securitatea si impartialitatea. O sa ii dati unui strain bani sa va faca cumparaturile? O sa jucati poker cu cineva daca nu ati vazut cum si cand a amestecat si a impartit cartile? Este o naivitate in a crede ca toti utilizatorii unei retele informationale sunt cinstiti. Cea mai are parte a lor este, insa sunt alti cativa care pot face mult rau. Prin formalizarea protocoalelor, putem sa examinam cum persoanele rau inttionate pot incerca sa triseze, si de asemenea sa dezvoltam protocoale care sa excluda trisorii.
Nu doar ca protocoalele permit formalizarea comportamentelor, ba chiar mai mult ele permit abstractizarea proceselor. Astfel un protocol de comunicare intre doua calculatoare este acelasi, fie ca sunt IBM PC’, VAX de la DIGITAL sau copiatoare. Putem sa examinam aceste protocolale fara a ne inneca in detalii tehnice referitoare la realizarea lor practica. Odata ce suntem convinsi ca avem un protocol bun, putem sa il implementam oriunde, nu conteaza ca sunt calculatoare, telefoane sau telecopiatoare inteligente.
3. Tipuri de protocoale
Avem mai multe tipuri de protocoale:
protocoale cu arbitru
protocoale cu judecator-arbitru
protocoale cu disciplina intrinseca
3.1. Protocoale cu arbitru
Un arbitru este o terta persoana de incredere si dezinteresata, care vegeaza la buna desfasurare a protocolului. Arbitrul este numit « dezinteresat» pentru ca nu are nici o simpatie pentru oricare din ceilalti participanti. Arbitrul este de « incredere» pentru ca toti participantii la protocol accepta ca fiind adevarat ceea ce zice acesta. Arbitrul ajuta la ducerea la indeplinire a protocoalelor intre participantii care nu au cele mai bune intentii.
Conceptul de arbitru este vechi ca si societatea noastra. Au existat tot timpul anumite persoane – conducatori, preoti, etc. – care au avut autoritatea si datoria de a actiona si gandi cinstit (onest). Arbitrii au un rol si o pozitie sociala aparte in societatea noastra. Daca incearca sa insele oamenii isi pierd acest statut: oamenii legii care se folosesc de tot felul de speculatii sunt pasibili de expulzarea din ordinul lor. Aceasta imagine de incredere nu corespunde tot timpul cu realitatea dar ne arata idealul. Acest ideal poate fi adaptat lumii informatice, insa raman totusi unele probleme cand calculatoarele arbitreaza:
Este mult mai usor avea incredere intr-o terta persoana daca stim cine este si cum am putea sa il intalnim. Doi participanti care nu au incredere unul in celalalt este posibil sa nu aiba incredere intr-un arbitru pe care nu l-au vazut si nu il vor vedea vreoadata.
Reteaua informationala trebuie sa isi asume costul arbitrajului. Cunoastem cu totii onorariile notarilor. Care este pretul care trebuie platit intr-o retea informatica?
Exista o intarziere implicita intr-un protocol cu arbitrare.
Arbitrul trebuie sa se ocupe de fiecare tranzitie; este posibil astfel sa se produca congestii in cazul realizarii la scara larga a protocolalelor. Cresterea numarului de arbitrii poate fi o solutie la aceste probleme dar atunci creste foarte mult costul realizarii.
Cum toata lumea din retea are incredere in arbitru , el devine un punctul sensibil al retelei si tinta preferata a celor care vor sa corupa reteaua.
3.2. Protocoale cu judecator-arbitru
Arbitrajul costa mult ! protocoalele cu arbitri pot fi divizate in doua sub-protocolale:un protocol fara arbitru care va fi executat de fiecare data cand protocolul este utilizat, si un alt sun-protocol la care se face apel doar in cazul in care avem un litigiu intre participanti. In acest caz particular nu vom mai vorbi despre un arbitru ci despre un judecator arbitru. Un judecator-arbitru este de asemenea o terta persoana neinteresata si demna de incredere. Diferitenta intre un alrbitru si un judecator-arbitru este ca acesta din urma nu este implicat in fiecare protocol. Acest judecator-arbitru nu este chemat decat pentru a determina daca o tranzactie s-a desfasurat in mod cinstit.
Protocolul de semnare a unui contract poate fi schitat in maniera urmatoare:
A si B negociazatermenii contractului.
A semneaza contractul.
B semneaza contractul.
Sub-protocolul cu judecator-arbitru (executat doar in caz de contestatii)
A sit B apar in fata judecatorului.
A isi prezinta propriul punct de vedere.
B isi prezinta propriul punct de vedere.
Judecatorul ia decizia.
Diferenta intre un arbitru si un un judecator-arbitru este ca judecatorul nu este intotdeauna necasar ; el intervine doar daca exista o contestatie. Daca nu exista asa ceva, un judecator nu este necesar. Exista protocoale informatice cu judecator-arbitru. Aceste protocoale se bazeaza pe ipoteza ca participantii sunt onesti, dar daca cineva triseaza, datele colectate in timpul executarii protocolului permit unei terte persoane, dezinteresate, de a determina daca a avut loc vreo trisare. Intr-un bun protocol cu judecator-arbitru, acesta poate sa indice cu exactitate identitatea celui care a trisat. In loc sa impiedice trisarea, protocoalele cu judecator-arbitru o detecteaza. Acest caracter inevitabil de detectare actioneaza ca o masura preventiva si descurajeaza frauda.
3.3. Protocoale cu disciplina intrinseca
Un protocol cu disciplina intrinseca este cel mai bun tip de protocol. Protocolul insusi garanteaza integritatea tranzactiei, deci nu este nevoie de judecatori-arbitri pentru a regla conflictele. Protocolul este construit de o asemenea maniera incat contestatiile sunt imposibile.
Daca unul dintre participanti incearca sa triseze, celalalt il detecteaza imediat si protocolul este intrerupt. Oricare ar fi sperantele trisorului acestea vor fi naruite. In mod normal toate protocoalele trebuie sa fie cu disciplina intrinseca, insa din pacate nu exista un astfel de protocol pentru fiecare tranzactie posibila.
4. Atacuri la protocoale
Atacurile indreptate contra protocolalelor pot viza fie algoritmii criptografici utilizati de catre protocol, fie tehnicile criptografice utilizate pentru realizarea algoritmilor, sau de ce nu protocului insusi. Pentru moment pornim de la ipoteza ca algoritmii si tehnicile sunt sigure si o sa ne concentram atentia doar asupra atacurilor indreptate protocolului insusi.
Sunt mai multe modalitati de ataca un protocol. Cineva care nu este imlicat in protocol poate spiona totul sau o parte din ceea ce se intampla. Acesta este numit atac pasiv, pentru ca atacatorul nu modifica protocolul. Tot ceea ce poate face este de a a observa etapele desfasurarii protocolului si de a colecta informatii. Acest tip de atac corespunde unui atac cu text cifrat. Atacurile pasive sunt dificil de detectat, datorita faptului ca protocoalele sunt proiectate sa fie rezistente atacurilor si nu pentru a le detecta.
Un atacator poate de asemenea incerca sa moddifice protocolul in scopuri personale, indiferent care ar fi acestea. El poate pretinde ca este altcineva, poate adauga mesaje noi, sa stearga alte mesaje, sa inlocuiasca un mesaj cu un altul, sa retrimita un mesaj mai vechi, sa blocheza canalul de comunicare sau sa modifice informatia stocata pe un calculator. Vom vorbi atunci despre atacuri active pentru ca ele necesita o atitidine activa a atacatorului. Modul cum sunt conduse aceste atacuri depinde in functie de reteaua in care are loc atacul.
Atacantii pasivi nu sunt interesati decat de informatia vehiculata referitoare la participantii la protocol. Ei colecteaza mesajele care circula intre diferiti participanti si incearca sa le criptanalizeze (sa le descifreze). Atacurile active, din contra, pot avea alte obiective. Atacatorul doreste fie sa obtina informatii existente, fie sa aiba acces la resurse secrete.
Atacurile active sunt mult mai serioase decat cele pasive, mai ales in protocoalele unde participantii nu au incredere unul in celalalt. Atacatorul nu trebuie in mod necesar sa fie o persoana din exterior ! Poate fi un utilizator al sistemului. Poate fi chiar administratorul sistemului. De asemenea poate sa fie un grup de atacatori activi, care lucreaza impreuna, fiecare dintre ei fiind un utilizator legitim al sistemului.
Este posibil ca unul dintre participantii la protocol sa fie atacantul. El poate minti in timpul protocolului, sau sa nu respecte regulile in totalitate. Acest tip de atacant este denumit trisor. Trisorii pasivi respecta protocolul, insa incearca sa obtina mai multe informatiii decat le este permis in mod normal. Trisorii activi modifica protocolul in incercarea lor de a trisa.
Este foarte dificil de a garanta securitatea sistemului, daca mare majoritate a utilizatorilor sunt atacanti activi, dar , cateodata, este posibil ca utilizatorii legitimi sa detecteze incercarea de a trisa in mod activ. In orice caz, protocoalele trebuie apãrate intr-o maniera fiabila contra trisarii pasive.
5. Comunicarea cu ajutorul unui criptosistem cu cheie secreta
Cum este posibil ca doua entitati sa comunice intre ele intr-o maniera sigura? Prin cifrarea transmisiunii bineinteles. Protocolul complet al unei comunicari de acest tip este mult mai complicat insa sa vedem o schema simplificata despre cum persoana A ii poate trimite un mesaj cifrat persoanei B.
A si B aleg un criptosistem cu cheie secreta.
A si B aleg o cheie.
A isi cifreazamesajul in clar cu ajutorul algoritmului ales si a cheii selectionate.
A trimite mesajul cifrat lui B.
B descifreaza mesajul receptionat folosind acelasi algoritm ca si la expeditor si aceeasi cheie si in final citeste mesajul.
Un bun criptosistem este un sistem unde securitatea este inerentã in cunoasterea cheii si nu a algoritmului. De aceea gestiunea cheilor este o problema atat de stringenta in criptografie. Cu ajutorul unui algoritm cu cheie secreta, A si B pot sa realizeze etapa 1 in public, dar trebuie ca etapa 2 sa fie realizata in secret. Cheia trebuie sa ramana secreta inainte de efecuarea trasmisiei, pentru ca altfel mesajul nu va mai fi confidential.
Un criptosistem cu cheie secteta are urmatoarele probleme :
Cheile trebuie sa fie distribuite in mod secret. Ele au aceeasi valoare ca si totalitatea mesajelor cifrate cu ajutorul lor, pentru ca cunoastrea cheii de catre o persoana neautorizata ii da acces acesteia la toate mesajele. Pentru un criptosistem utilizat la scara mondiala, distributia cheilor poate fi o operatie descurajanta. De multe ori, aceste chei sunt aduse la destinatie din mana in mana.
Daca cheia este compromisa (furata, determinata, cumparata, etc.) atunci un spion poate descifra toate mesajele cifrate cu ajutorul acestei chei. El poate pretinde ca este unul dintre participanti si sa trimita mesaje cu scopul de a-l duce in eroare pe celalt.
Daca sunt utilizate chei diferite pentru fiecare pereche de utilizatori ai unei retele, numarul necesar de astfel de chei creste foarte repede in raport cu numarul de utilizatori. De exemplu 10 utilizatori au nevoie de 45 de chei diferite pentru a putea realiza orice conversatie in doi; 100 de utilizatori au nevoie de 4950 chei diferite. Acesta problema poate fi minimizata pastrand un numar mic de utilizatori insa aceasta solutie nu este tot timpul posibila.
6. Comunicarea cu ajutorul sistemelor criptografice cu cheie publica
Putem compara algoritmul cu cheie secreta cu un seif. Cheia este combinatia seifului. Cel care cunoaste combinatia poate deschide seiful, poate pune un document in interior si sa reinchida seiful. Altcineva care cunoaste acesta combinatie, poate deschide la randul sau seiful si sa ia documentul. Toti ceilalti care nu cunosc cheia nu au decat sa invete arta spargerii seifurilor.
Functii cu sens unic
Notiunea de functie cu sens unic este fundamentala pentru criptografia cu cheie publica.
Bine ca ea nu este un protocol in sine, dar constituie un element de baza pentru cea mai mare parte a protocoalelor criptografice.
O functie cu sens uniceste o functie usor de calculat insa considerabil mult mai greu de inversat. Cu alte cuvinte, daca avem dat un x este usor de calculat f(x), dar avand f(x) este dificil de determinat x-ul. In acest context « dificil » vrea sa spuna ca ar trebui milioane de ani pentru a determina functia inversa chiar daca toate calculatoarele din lume s-ar alia in aceasta privinta. Spargerea unui farfurii est cel mai bun exemplu de o functie cu sens unic. Este usor de spart o farfurie in mii de bucati, insa este dificil de a lipi toate aceste bucati impreauna pentru a reconstitui farfuria.
Dar la ce poate servi aceste functii unice ? Nu le putem folosi in criptografie. Un mesaj cifrat cu ajutorul unei astfel de chei nu are o prea mare utilitate pentru ca nimeni nu il poate descifra. Pentru criptografia cu cheie publica avem nevoie de ceea ce se numeste functie cu sens unic dar cu bresa secreta.
O functie cu sens unic dar cu bresa secreta este un tip special de functie cu sens unic. Este usor de calculat intr-un sens insa dificil de calculat in celalalt. Diferenta intre aceste doua tipuri este ca in in cazul in care avem bresa secreta, exista o informatie secreta, y, cu ajutorul careia daca avem f(x), este usor de calculat x. Un ceas este un bun exemplu de o astfel de functie. Este usor de a demonta un ceas in nenumarate bucati. Insa este foarte dificil de a pune toate piesele inapoi pentru a reconstitui ceasul care sa si functioneze. Totusi, datorita informatiei secrete reprezentate de schema de asamblare a ceasului, acesta este usor de refacut.
–––––
In 1976 Whitfield Diffie si Martin Hellman au descris principiile criptografiei cu cheie publica. In locul unei singure chei, avem doua chei diferite: una publica si cealalta privata. Toate persoanele pot cu ajutorul cheii publice sa cifreze mesaje, dar ea nu poate descifra mesajele celorlati. Doar persoana care are cheia privata poate descifra mesajele. Este ca si cum cineva art fi schimbat seiful criptografic cu o cutie postala. Punerea unei scrisori in cutie reprezinta cifrarea cu cheia publica, toata lumea o poate face. Scoaterea scrisorii din cutie revine descifrarii cu ajutorul cheii private.
Din punct de vedere matematic, procedura se bazeaza pe functiile cu sens unic si bresa secreta descrise mai sus. Cifrarea este directia usoara. Cheia publica reprezinta instructiunile pentru cifrare: toata lumea poate cifra un mesaj. Descifrarea (decriptarea) este directia dificila. Este suficient de dificila incat persoane care au calculatoare CRAY si milioane de ani la dispozitie nu pot descifra mesajul fara a cunoaste secretul. Secretul sau bresa secreta este cheia privata. Cu acest secret cunoascut, descifrarea este la fel de usoara ca si cifrarea.
Iata in exemplu despre cum persoana A poate expedia un mesaj cifrat unei alte persoane, B, folosind criptografia cu cheie publica.
A si B aleg un criptosistem cu cheie publica.
B ii trimite lui A cheia lui publica.
A isi cifreaza mesajul cu ajutorul cheii publice a lui B si ii trimite rezultatul.
B descifreaza mesajul utilizand chaia lui privata.
Inainte, A si B trebuiau sa se puna de acord asupra cheii, in secret. Criptografia cu cheie publica a rezolvat problema distributiei cheilor. Fara nici un aranjament in prealabil, A ii poate trimite mesajul confidential lui B. un spion care asculta tot acest schimb, poate dispune de cheia publica a lui B si mesajul cifrat cu aceasta cheie, dar nu poate nici gasi cheia privata a lui B nici nu poate citi continutul mesajului.
Chiar daca sunt mai multi utilizatori nu exista nici o problema. Trebuie sa foloseasca un sistem criptografic cu cheie publica, unde fiecare utlizator isi are propriul set de chei publice si private. Toate aceste chei trebuie sa fie disponibile intr-o baza de date pe undeva:
A obtine cheia publica a lui B din baza de date.
A isi cifreaza mesajul utilizand aceasta cheie si ii trimite lui B rezultatul .
B descifreaza mesajul folosindu-se de cheia sa privata.
Algoritmi care folosesc astfel de chei, sunt:
Elgamal (numit dupa inventatorul sau Taher Elgamal);
RSA (numit dupa inventatorii sai: Ron Rivest, Adi Shamir si Leonard Adleman);
Diffie – Hellman (numit tot dupa inventatorii sai);
DSA – Digital Signature Algorithm (inventat de David Kravitz);
7. Sisteme criptografice hibride
Chiar daca am prezentat avantajele sistemelor criptografice cu cheie publica fata de cele cu cheie secreta, in practica algoritmii cu cheie publica nu ii inlocuiesc pe aia cu cheie secreta. De ce, o sa vedem in cele ce urmeaza :
Algoritmii cu cheie publica sunt lenti. Algoritmii cu cheie secreta sunt in general de cel putin 1000 de ori mai rapizi decat cei cu cheie publica. Este adevarat ca calculatoarele sunt din ce in ce mai rapide si ca in cincisprezece ani utilizarea criptografiei publice va fi la fel de rapida ca si criptografie cu cheie secreta de azi. Dar nevoile de largime de banda vor creste si vom avea nevoie tot timpul de cifrare mai rapida decat cea posibila cu ajutorul criptografiei cu cheie publica.
Criptosistemele cu cheie publica sunt vulnerabile atacurilor cu text in clar ales. Daca C=E(M) unde M este un text in clar printre cele n texte in clar posibile, atunci unui analist criptografic sa cifreze cele n mesaje si sa compare textele cifrate rezultate cu C (sa nu uitam ca cheia de cifrare este publica). Nu va putea determina cheia de descifrare in acest mod dar, va putea determina M.
In cea mai mare parte a aplicatiilor practice, criptografia cu cheie publica este utilizata pentru protejarea si distribuirea cheilor de sesiune, si aceste chei de sesiune sunt utilizate in algoritmii cu cheie secreta pentru protejarea mesajului transmis. Acesta este numit uneori in sistem criptografic hibrid.
B ii trimite cheia sa publica lui A.
A genereaza o cheie de sesine aleatorie, k, o cifreaza cu cheiapublica al lui B si ii trimite acestuia rezulatul.
B foloseste cheie sa privata pentru descifrarea mesajului trimis de A si astfel gaseste cheia de sesiune.
A si B utilizeaza astfel aceeasi cheie de sesiune pentru a-si cifra conversatia.
8. Problemele
Problemele cu care protocoalele criptografice au de a face sunt :
Confidentialiatea
Autentificarea
Integritatea
Non-répudiation
Pentru a rezolva o parte din aceste probleme putem sa folosim urmatoarele:
9. Solutii
9.1. Autentificarea
Autentificarea unui mesaj este procedura prin care transmitatorul (sau destinatarul) confirma isi valideaza identitatea prin mijloace tehnice adecvate ( parola sau cod confdential) de care emitorul sau destinatarul nu au de unde sa le cunoasca.
Autentificarea reciproca: garantie pentru fiecare dintre cei doi parteneri ca fiecare este cel care pretinde ca este. Sistemul central este asigurat ce utilizatorul terminalului este cel care s-a anuntat a fi, dar si pentru utilizator ca sistemul la care este conectat este cel dorit.
9.2. Semnaturi digitale
Semnatura electronica (numita uneori si semnatura digitala) este un procedeu care permite garantarea autentificarii expeditorului (functia de autentificare), si verificarea integritatii mesajului receptionat.
Semnatura electronica asigura in egala masura functia de non-repudiation, adica asigura ca expeditorul a trimis mesajul (cu alte cuvinte ea impiedica expeditorul sa nege trimiterea unui mesaj).
Semnaturile de mana de pe documente au fost foloste de-a lungul timpului pentru a face dovedi identitatea autorului lor sau ca au fost semnate cu buna stiinta si sunt de acord cu ceea ce scrie in document. Ce face ca o semnatura sa fie asa de importanta ?
O semnatura este autentica. Ea convinge destinatsarul ca semnatarul a semnat deliberat documentul.
O semnatura nu poate fi falsificata (imitata)! Semnatura este proba ca semnatarul a semnat deliberat documentul.
O semnatura nu este reutilizabila. Semnatura face parte din document si o persoana rau intentionata nu poate muta semnatura pe un alt document.
Un document semnat este inalterabil. Odata semnat el nu poate fi modificat.
O semnatura nu poate fi renegata. Semnatura si documentul sunt obiecte fizice. Signatarul nu poate pretinde mai tarziu ca nu a semnat documentul.
In realiatate insa, niciuna dintre aceste afirmatii nu este cu totul adevarata. Semnaturile pot fi falsificate; semnaturile pot fi transferate dintr-un document in altul. Documentele pot fi modificate dupa ce au fost semnate. Totusi, in ciuda acestor probleme acceptam sa traim cu ele: este dificil de trisat si rascam sa fim demascati cu toate consecintele pe care le implica acest fapt.
Ne-ar face placere sa putem face acelasi lucru si cu calculatoarele dar, imtampinam o serie de probleme. In primul rand fisierele informatice sunt usor de copiat. Chiar daca semnatura unuia este dificil de falsificat, este usor de transferat de pe un document pe un altul folosind tehnica « copy -paster ». Simpla prezenta a unei semnaturi nu mai garanteaza nimica. In al doilea rand este usor de modificat un document dupa ce acesta a fost semnat fara a lasa urme referitoare la acesta “operatie”.
Un posibil protocol, utilizand semnarea documentelor cu ajutorul sistemelor criptografice cu cheie publica, poate fi urmatorul :
A cifreaza documentul cu cheia sa privata , semnand in acelasi si documentul.
A trimite rezultatul lui B.
B descifreaza mesajul cu ajuorul cheii publice a lui A, verificand in acelsi timp si semnatura acestuia ;
Acest protocol are urmatoarele proprietati :
Semnatura este autentica: cand B verifica mesajul cu cheia publica a lui A, el stie ca acesta a semnat ;
Semnatura este nefalsificabila: doar A isi cunoaste cheia privata. seule.
Semnatura nu poate fi reutilizata: ea este o functie a documentului si nu poate fi transferata pe alte documente.
Documentul semnat ramane nescimbat : daca exista cea mai mica tentativa de a falsifica documentul, acesta nu mai poate fi verificat folosind cheia publica a lui A.
Semnatura nu poate fi negata. B nu are nevoie de ajutorul lui A pentru a verifica semnatura.
9.3. Datarea
Dar, raman inca probleme: o persoana poate reutiliza ansamblul semnatura plus document. Pentru a evita aceasta semnaturile digitale contin deseori o DATARE a documentului (data+ora). Aceasta datare a semnaturii este atasata la restul mesajului si semnata impreuna cu restul mesajului.
IV. Alegerea mediului de implementare : Microsoft® Visual C++®
1. Prezentare
Visual C++ 6.0 este penultima versiune a compilatorului Microsoft Visual C/C++.
Produsul a devenit mult mi mult decat un simplu compilator . sunt include clasele fundamentale Microsoft (Microsoft Foundation Classes), care simplifica si accelereaza dezvoltarea aplicatiilor Windows. Sunt incluse editoare sofisticate de resurse in scopul proiectarii casetelor de dialog complexe, a meniurilor, barelor de instrumente, imaginilor si ale multor alte elemente ce compun aplicatiile Windows moderne. Este oferit un excelent mediu de dezvoltare integrat numit Developer Studio, care prezinta forme grafice ale structurii aplicatiei pe masura ce o dezvoltati. Un instrument pentru depanare integrat perfect va permite sa inspectati in detaliu fiecare aspect din cadrul unui program aflat in executie. Iar acestea sunt doar cateva din numarul coplesitor de facilitati oferite de Visual C++ 6.0, care va ajuta sa dezvoltati aplicatii rapide si complete folosind cele mai recente tehnologii din Windows.
Instrumentele mediului Developer Studio :
Un editor integrat pune la dispozitie facilitatea “drag-and-drop” (tragere si plasare), precum si alte facilitati de evidentiere a sintaxei. Editorul meniului Developer Studio poate fi configurat pentru a emula comenzile de tastatura utilizate de doua editoare Brief si Epsilon.
Un editor de resurse este folosit pentu crearea resurselor Windows, de exemplu imagini bitmap, pictograme, casete de dialog.
Un program incarcat de depanare ne permite rularea programelor si depistarea erorilor. Deoarece acest program este componenta a mediului Developer Studio, depistarea si corectarea erorilor de program este simpla.
Un sistem help on-line care paote fi folosit pentru obtinerea informatiilor sensibile la context pentru orice instrument folosit in mediul Developer Studio, precum si informatii detaliate referitoare la limbajul C++, interfata de programare Windows si biblioteca de clase MFC.
2. “Vrajitorii” mediului Developer Studio :
AppWizard este utilizat pentru crearea structurii de baza a unui program Windows. AppWizard suporta trei tipuri de aplicatii :
Mono document
Multiplu document bazate pe arhitectura Document – View
Programe bazate pe casete de dialog in care o caseta de dialog serveste drept fereastra principala a aplicatiei.
ClassWizard este folosit pentru definirea de clse intr-un program creat cu AppWizard. Prin utilizarea facilitatii ClassWizard se pot adauga clase noi in proiect. De asemenea, se pot adauga functii care controleaza modul de manipulare a mesajelor primite de fiecare clasa in parte. Facilitatea ClassWizard mai poate contribui la menevrarea controalelor incluse in casete de dialog, permitand asociarea unui obiect MFC sau a unei variabile membru a clasei fiecarui control.
Majoritatea claselor MFC se incadreaza in una din categoriile urmatoare :
Application Architecture contine clase care contribuie la crearea structurii de baza aplicatiilor
create folosind MFC.
Dialog Boxes (casete de dialog ) deriva din CDialog, o clasa de baza de casete de dialog. In aceasta categorie sunt incluse clasele care controloeaza casetele de dialog obisnuite prezente in Windows98.
Views (imagini) sunt folosite in arhitectura Document View pentru a prezenta datele de iesire ale programului. In aceasta categorie sunt incluse clasele care suporta derularea imaginilor si editarea ferestrelor bazate pe casetele de dialog.
Controls (controale) sunt utilizate pentru a asigra un acces comod la toate controalele puse la dispozitie de Windows98. In aceasta categorie sunt incluse clasele care gestioneaza arborii, listele si casetele combinate.
Graphical Objects (obiecte grafice) sunt folosite pentru vizualizarea datelor de iesire dintr-un program Windows. Aceasta categorie contine clase pentru creioane, pensule, pictograme si imagini bitmap.
Exceptions (exceptii) sunt folosite pentru a semnala aparitia unui eveniment nepravazut in timpul executiei unui program.
Collections (colectii) este o categorie speciala de clase care contin obiecte din alte clase. Unele dintre clasele de tip colectie oferite in biblioteca de clase MFC sunt bazate pe sabloane, ceea ce va permite utilizarea acestora cu aproape orice tip de obiect.
Visual C++ si Developer Studio reprezinta un mediu complet integrat care faciliteaza in mare masura crearea programelor Windows. Prin utilizarea instrumentelor si a “vrajitorilor” care constituie un program poate fi creat in cateva minute.
In general, pentru alcatuirea unui program folosind Visual C++ se parcurg urmatoarele etape:
Crearea scheletului programului folosind AppWizard;
Crearea resurselor folosite de catr eprogram;
Adaugarea claselor si functiilor de manevrare a mesajelor folosind ClassWizard;
Crearea nucleului functional al programului;
Compilarea si testarea programelor.
3. Proiectare orientata pe obiect si functii virtuale
Pentru a profita de suportul oferit de catre limbajul C++ programarea orientata pe obiect este necesara intelegerea modului de proiectare a programelor orientate pe obiect.
Proiectarea orientata pe obiect presupune ordonarea obiectelor si a actiunilor din lumea reala sub forma de clase care pot fi create, manevrate si distruse. Datele care alcatuiesc un obiect si functiile exercitate asupra acelui obiect sunt combinate pentru a forma o clasa. Clasele pot mosteni functionalitatea altor obiecte putand fi cu usurinta adaugate clase noi.
O alta componenta cheie a proiectarii orientate pe obiect este ideea ca o clasa trebuie sa asigure o interfata utilizata pentru manipularea obiectelor existente in aceeasi clasa. Pe cat posibil detaliile de implementare trebuie ascunse utilizatorului .
In proiectarea traditionala, structurata, datele manevrate de un program si functiile care manipuleaza datele sunt separate. Adesea este dificila reutilizarea componentelor unei structuri realizate cu tehnici de proiectare structurata ,daca noua structura difera de cealalta.
Proiectarea orientata pe obiect este utila deoarece poate fi folosita pentru crearea structurilor care pot fi reutilizate si extinse. O structura poate fi reutilizata in programe ulterioare oarecum asemanator cu componenta hard, de tipul cip, o unitate de disc sau o placa de sunet. Deoarece structurile orientate pe obiecte descriun integral clasa din care face parte obiectul respectiv, fiecare clasa pate fi reutilizata cu usurinta intrucat datele si functiile descrise de clasa respectiva sunt integrate.
Partea cea mai delicata a proiectarii orientate pe obiect este gasirea unui set corespunzator de obiecte de lucru. Un obiect nu este decat un “lucru” care se poate folosi in interiorul unui program. Obiectele folosite intr-un program depind efectiv de scopul acelui program. Un obiect poate fi un articol fizic care poate fi manipulat cum ar fi o masina, sau poate avea o natura mai abstracta, cum ar fi o calatorie.
Majoritatea obiectelor au doua caracteristici comune :
Au o anumita stare sau anumite proprietati care le ofera unicitatea
Dispun de functii sau metode care ot fi aplicate obiectului pentru a schimba starea sau pentru a beneficia de proprietatile acestora
Atunci cand se utilizeaza limbajul de programare C++, obiectele sunt descrise printr-o clasa. O clasa este doar o descriere o obiectului care poate fi creat si a operatiilor care se pot executa folosind acel obiect. O clasa in C++ are doua componente principale :
Declaratia clasei – contine interfata clasei si informatii privind datele membre ale respectivei clase. Interfata clasei este de obicei localizata intr-un fisier antet cu extensia .h. Orice fisier care foloseste clasa respectiva trebuie sa foloseasca directiva #include <*.h>, pentru ca declaratia sa fie adaugata fisierului sursa de catre preprocesor.
Implementarea clasei – include toate functiile membre care au fost declarate ca parte a clasei. Ea se afla intr-un fisier avand extensia *.cpp.
La conceperea claselor, cautam asemanari dintre acestea, asa cum exista asemanari intre diferite obiecte. Daca fiecare clasa care descrie un obiect ar fi fost conceputa de la zero, in programe ar fi fost o multime de coduri care s-ar fi repetat.
Exista doua modalitati fundamentale de organizare a claselor :
Ierarhia poate fi folosita pentru organizarea claselor dupa modelul unui arbore genealogic, cu clase care “mostenesc” datele si functiile de la predecesorii lor.
Categorii . Adesea, un set de clase se folosesc impreuna si prezinta un fel de dependenta sau o alta categorie de relatii intre ele. Aceste clase pot fi organizate intr-o categorie, pentru a simplfica utilizarea lor.
4. Clase de baza MFC
Biblioteca de clase MFC include un numar mare de clase corespunzatoare programarii in windows. Majoritatea acestor clase sunt derivate din CObject, clasa care se afla la radacina ierarhiei de clase din MFC. Suplimentar, orice clasa care reprezinta o fereastra sau un control este derivata din clasa CWnd, care manevreaza functiile de baza comune tuturor ferestrelor. Clasele CObject si CWnd utilizeaza functiile virtuale, care permit programatorului sa acceseze functii de uz general, prin intermediul unui pointer de baza. Aceasta permite utilizarea cu usurinta a oricarui obiect derivat din CObject sau CWnd la interactiunea cu cadrul de lucru MFC.
5. Utilizarea limbajului C++ pentru programarea in Windows
Programele scrise pentru Windows trebuie sa colaboreze cu Windows si cu alte programe care pot rula in acelasi timp. Intr-un mediu cooperativ cum este Windows, mesajele se transmit unui proram atunci cand survine un eveniment care influenteaza programul. Fiecare mesaj trimis unui program are un scop specific. De exemplu, se transmit mesaje atunci cand este necesara initializarea unui program, la operarea unei selectii intr-un meniu sau atunci cand o fereastra trebuie redesenata. O alta caracteristica a programelor Windows este aceea ca programele trebuie sa foloseasca resursele in comun. Multe resurse trebuie solicitate sistemului de operare pentru a putea fi folosite si de catre alte programe. Aceasta reprezinta o modalitate de exercitare de catre Windows a controlului asupra unor resurse ca ecranul sau alte periferice. Programul nu trebuie sa ceara permisiunea preluarii controlului asupra unei resurse centrale si trebuie sa fie gata sa reactioneze la orice evenimente care il privesc.
Atunci cand se foloseste limbajul Visual C++, o amre parte a problemelor care apar la scrierea unui program in Windows se rezolva cu usurinta.
Exista trei componente a pachetului Visual C++ care simplifica scrierea unui program in Windows :
Compilatoarele de C si C++. Chiar daca nu se folosesc bibliotecile MFC sau mediul Developer Studio, avem posibilitatea scrierii proframelor folosind compilatorul de C si C++. Developer Studio mai include un editor avansat de texte cu posibilitatea de avidentiere a sintaxei, un sistem integrat de asistenta si un program integrat de depanare.
Biblioteca de clase MFC. Versiunea 6.0 include noi clase, care permit adaugarea de caracteristici avansate programelor doar prin inserarea catorva linii de cod.
Instrumente cum ar fi AppWizard si ClassWizard. Acestea sunt incluse ca si componente a mediului Developer Studio ce permit alcatuirea rapida a unor programe Windows prin generarea de aplicatii de baza si prin controlul procesului de scriere a unui program Windows.
Clasele incluse in biblioteca de clase MFC sunt dispuse in urmatoarele categorii :
Clase de uz general. In aceasta categorie intra clasele utilizate la manipularea fisierelor si a sirurilor.
Clase de obiecte vizuale. Aceste clase manevreaza aproape tot ce este vizibil intr-un program Windows. In aceasta categorie sunt incluse clasele de meniuri, ferestre, controale si obiecte de desenare cum sunt creioanele si pensulele.
Clasele aplicatie. Ina aceasta categorie se include clasele care gestioneaza obiecte de nivel aplicatie, siruri de executie sau arhitectura Document View. Document View reprezinta baza majoritatii programelor scrise folosind MFC.
Biblioteca de clase MFC este construita plecand de la modelul de programare Document View. Utilizarea lui AppWizard pentru crearea codului de baza pentru program reprezinta cea mai rapida modalitate de scriere a programelor in maniera Document View.
AppWizard foloseste clasele MFC pentru a creea aplicatii bazate pe arhitectura MFC Document View. Ideea de baza a acesteia este separarea claselor de manipulare a datelor de clasele care trateaza interfata cu utilizatorul. Separarea datelor de interfata cu utilizatorul permite fiecarei clase sa se concentreze asupra efectuarii unei singure sarcini, cu un set de interfete definite pentru interactiunea cu celelalte clase implicate in program. O clasa de vizualizare este responsabila pentru asigurarea unui “ochean” prin care se poate vedea si controla documentul. O clasa document este responsabila pentru controlul tuturor datelor atunci cand este necesar.
Exista patru clase principale folosite intr-o aplicatie de tip Document View :
Clasa document, care controleaza datele folosite de catre o aplicatie. Datele nu trebuie sa fie neaparat o pagina de text, de exemplu o foaie de calcul sau un plan de proiect pot fi asimilate cu usurinta unui document.
Clasa de vizualizare, utilizata pentru a prezenta utilizatorului informatii despre document si pentru a trata orice interactiune care se impune intre utilizator si document.
Clasa cadru, utilizata pentru a include fizic imaginea, meniul, bara de instrumente si alte elemente fizice ale programului.
Clasa aplicatie, care controleaza interactiunea la nivel de aplicatie cu Windows.
AppWizard pune la dispozitia utilizatorului urmatoarele tipuri de programe generice :
Single Document (SDI) este un program care controleaza un singur document la un moment dat.
Multiple Document (MDI) este un program care poate controla in acelasi timp mai multe documente diferite.
Dialog Based este un program care are drept fereastra principala de afisare o caseta de dialog.
AppWizard creaza un program SDI in urma caruia se obtin mai multe clase si fisiere ce formeaza scheletul programului. De exemplu pentru un program denumit Test, AppWizard va crea urmatoarele clase :
CTestApp derivata din CWinApp, clasa de aplicatie a programului;
CTestDoc derivata din CDocument este clasa document a programului;
CTestView derivata din CView este clasa de vizualizare a programului;
CMainFrame este clasa cadru principala a programului.
In plus AppWizard creaza cateva fisiere care nu sunt folosite de catre clasele C++. Aceste fisiere sunt :
Readme.txt este un fisier ce contine informatii despre toate fisierele create de AppWizard;
Test.rc este un fisier ce contine informatii despre toate casetele de dialog, meniurile si celelalte resurse folosite de program;
Test.mac este un fisier proiect folosit de Developer Studio pentru a construi programul
Stdafx.cpp este un fisier inclus in toate programele create de AppWizard care contine toate fisierele include standard.
Stdafx.h este un fisier antete standard inclus in AppWizard, utilizat pentru a include alte fisiere incluse in fisierle antet precompilate.
5.1. Meniuri
Meniurile sunt o componenta esentiala a majoritatii programelor Windows. Cu exceptia unor aplicatii simple, orientatepe casete de dialog, toate programele Windows ofera un tip de meniu sau altul.
Un meniu este o lista de mesaje de comanda care pot fi selectate si transmise unei ferestre. Pentru utilizator, un articol de meniu este un sir indicand o operatie care poate fi executata de catre aplicatie. Fiecare articol de meniu are un identificator care este utilizat pentru identificarea articolului la directionareaa mesajelor de fereastra. Acest identificator este folosit si la modificarea atributelor articolului de meniu.
De obicei meniurile sunt atasate la o fereastra care pot aparea oriunde pe suprafata de lucru. Meniurile pot fi uneori imbricate, in sensul ca un articol de meniu este de fapt un submeniu care include mai multe articole de meniu suplimentare. Un articol de meniu care duce la meniu imbricat este marcat cu o sageata inclinata spre dreapta pentru a indica faptul ca mai exista si alte optiuni disponibile.
Meniurile se folosesc pentru a indica o lista de operatii care pot fi aplicate uni program Windows. Desi AppWizard creeaza o lista prestabilita de meniuri pentru program, aceste meniuri trebuie modificate la adaugarea functiilor noi. Meniurile se pot creea dinamic sau caresurse statice care se adauga programului. Biblioteca de clase MFC asigura o clasa CMenu care simplifica tratarea meniurilor. AppWizard genereaza o resursa de meniu pentru programele pe care le ceeaza. Aceasta resursa de meniu poate fi modificata in vederea inserarii de articole de meniu suplimentare intr-o aplicatie, sau pentru crearea de noi resurse de meniu pentru aplicatia respectiva.
Un meniu este intotdeauna asociat unei anumite ferestre. In majoritatea programelor MFC, acesta este asociat ferestrei cadru principal, care mai contine bara de instrumente a aplicatiei si bara de stare. La selectarea unui articol din meniu, un mesaj WM_COMMAND este transmis catre fereastra cadru principal, mesaj care include si identificatorul articolului de meniu.
Una dintre cele mai simple operatii cu meniuri o constituie adaugarea unui nou articol in meniu.
Pentru a utiliza un articol nou din meniu avem de facut doua operatii :
Modificam resursa din meniu pentru a include un nou articol;
Adaugam o functie de tratare a mesajului folosind facilitatea ClassWizard.
Pentru modificarea resursei de meniu executam un dublu-click pe caseta libera din meniul File pentru a afisa caseta de dialog cu proprietatile meniului. Ultimul articol din fiecare meniu este liber.
Pentru a adauga un articol de meniu introducem un identificator si o legenda. Prin conventie, identificatorii incep cu ID_ si apoi include numele meniului de nivel ianlt.
Pentru a reveni la editor executam un dublu-click oriunde in afara casetei de dialog. ID este identificatorul resursei de meniu. Acesta este transmis ca parte a mesajului WM_COMMAND adresat aplicatiei si este folosit de ClassWizard pentru a identifica articolul din meniu.
Dupa adaugarea unui articol in meniul aplicatiei, urmatoare etapa este de adaugare a unei functii de tratare a mesajelor pentru noul articol din meniu. Pentru adugarea functiei de tratare procedam astfel :
Deschidem facilitatea ClassWizard;
Selectam eticheta MessageMaps si clasa care va trata mesajul din caseta speciala ClassName.
Selectam obiectul care genereaza mesajul din caseta lista Object. In acest caz, ID_FILE_NAME. In caseta lista Messages se vor afisa doua functii de tratare a mesajelor.
Selectam mesajul COMMAND din caseta lista Messages si executam dublu-click pe butonul AddFunction.
Executam click pe butonul OK pentru a inchide facilitatea ClassWizard.
5.2. Casete de dialog
Casetele de dialog , adesea cunoscute sub numele de dialoguri, se folosesc pentru a prezenta informatii si pentru a primi date de la utilizator. Casetele de dialog pot avea orive marime, variind de la casetele simple de mesaj care afiseaza o singura linie de text pana la casetele de dialog de mari dimensiuni, care contin controale sofisticate. Casetele de dialog se utilizeaza pentru a concentra informatie si pentru a asigura reactia utilizatorului. Tipul de caseta de dialog folosit cel mai des este caseta de dialog modala, care contine de obicei mai multe controale utilizate in interactiune cu un program.
Casetele de dialog se mai folosesc pentru comunicatia uni-sens cu utilizatorul, cum ar fi “ecranele de prezentare” utilizate la lansarea unui program pentru afisarea de informatii legate de copyrigth sau de pornire. Un alt tip de casete de dialog este caseta de mesaj care transmite utilizatorului scurte mesaje sau inregistreaza o reactie a acestuia.
Avem trei tipuri principale de casete de dialog care sunt :
Caseta de mesaje;
Caseta modala de dialog;
Caseta de dialog tip modeless.
De exemplu, pentru aifsarea unei casete de dialog folosind parametri oferiti de MFC, se foloseste urmatoarea linie :
AfxMessageBox(“text”);
Aceasta linie de cod creeaza o caseta de masaj cu un semn de exclamatie intr-un triunghi galben. Intr-o caseta de dialog poate fi continuta o intreaga gama de controale. Unele casete de dialog sunt solicitate atat de frecvent in programe Windows, incat au fost incluse ca parti componente sin sistemul de operare. Aceste casete de dialog ordinare sunt disponibile prin apelarea unei functii si nu necesita crearea unei resurse de tip caseta de dialog.
Majoritatea casutelor de dialog sunt modale ceea ce insemana ca trebuie inchise inainte ca utilizatorul sa poata efectua o alta operatie. O caseta de dialog fara mod (modeless) permite efectuarea altor operatii in acelasi timp ce caseta e deschisa.
Adaugarea unei casete de dialog intr-un program implica patru etape :
Proiectarea si creearea unei resurse caseta de dialog folosind instrumentele din Developer Studio;
Utilizarea facilitatii ClassWizard pentru a creea o clasa C++ derivata din CDialog;
Adaugarea functiilor care sa trateze mesajele transmise casetei de dialog, daca este necesar;
Daca caseta de dialog este selectata din meniul principal, resursa din meniu trebuie sa fie modificata, iar functiile de tratare a mesajelor create folosind ClassWizard.
Developer Studio permite creerea unei casete de dialog si configurarea pe cale vizuala a aceateia. Controalele pot fi adaugate si dimensionate prin intermediul mouse-ului.
Pentru a creea o noua caseta de dialog pentru un proiect existent folosim una dintre urmatoarele metode :
1. Prima metoda :
Selectam Resource din meniul Insert, apoi se selecteaza Dialog ca tip de resursa;
Executam click-dreapta pe Dialog din arborele Resource, iar apoi selectam Insert Dialog din meniul derulant.
Fiecare caseta de dialog dispune de proprietati care pot fi afisate executand dublu-click pe caseta de dialog sau prin executarea uni click-dreapta si apoi selectarea optiunii Properties din meniul derulant.
Proprietatile unei casete de dialog sunt :
Dialog ID, in mod normal stabilita la o valoare gen IDD_DIALOG1. Denumirea casetelor de dialog cu identificatori care incep cu IDD reprezinta o conventie MFC;
Dialog caption (legenda) , in mod normal stabilita la dialog;
Menu, in mod normal libera , intrucat foarte putine casete de dialog folosesc meniuri;
Font, in mod normal libera pentru a putea fi utilizat fontul oferit de sistem;
Position, in mod normal libera.
2. A doua metoda:
La creearea unei clase pentru casete de dialog se poate folosi clasa CDialog care gestioneaza in buna masura interactiunea cu o caseta de dialog. Clasa CDialog ofera functii membre care faciliteaza uzul unei casete de dialog.
Pentru a lansa ClassWizard, utilizam oricare din aceste metode :
Apasam Ctrl+W in mediul Developer Studio;
Selectam ClassWizard din meniul View;
Executam click-dreapta oriunde in editorul casetei de dialog si selectam ClassWizard din meniul derulant.
Daca ClassWizard stie ca a fost adaugata o noua resursa, cum ar fi IDD_TEST , o caseta de dialog va cere sa alegem una dintre cele trei optiuni pentru noua resursa :
Crearea unei clase noi;
Importarea unei clase existente;
Selectara unei clase existente.
6. Arhitectura Document/View
Document/View separa un document in patru clase principale :
O clasa document derivata din Cdocument;
O clasa de vizualizare derivata din Cview;
O clasa cadru derivata din CwrameWnd;
O clasa de aplicatie derivata din CwinApp.
Primul motiv in favoarea utilizarii arhitecturii Document/View este acela ca asigura un mare volum de coduri de aplicatie. Arhitectura Document/View defineste mai multe categorii principale pentru clasele folosite intr-un program Windows. Document/View asigura un cadru flexibil care poate fi folosit pentru crearea de programe de Windows de orice tip. In arhitectura Document/View cele patru clase principale intercomunica prin intermediul unor interfete bine definite, rezulta ca pentru a transforma un program SDI intr-unul MDI modificarea interfetei are efect numai asupra claselor de vizualizare. Diferenta esentiala dintre SDI si MDI este ca ultima trebuie sa gestioneze mai multe documente si mai multe vizualizari, prima gestionand un singur document si o singura vizualizare. Aplicatiile SDI si MDI folosesc un sablon pentru a creea o relatie intre o clasa de vizualizare, o clasa document si o clasa cadru, precum si ca identificator pentru meniu, pictograme si alte resurse de program.
MEMORIU DE PROIECTARE
1. Ce s-a dorit de a se obține de la acest proiect?
S-a încercat realizarea unei aplicații care sa utilizeze sistemul de criptarea haotica pentru trasferuri de mesaje sau de fisiere folosind reteaua Internet, colaborat cu implemenatarea unui protocol de autentificare reciproca a celor doi participanti.
Cum s-a gandit realizarea unei astfel de aplicatii? In primul rand cei doi participanti vor face fiecare taskuri diferite : in timp ce unul dintre ei va trimite mesajele sau fisierele, celalalt va trebui sa fie pregatit sa le primeasca. Asta inseamna ca avem nevoie de o aplicatie client, si de inca una server. Asa s-a gandit programul in prima lui versiune. De ce nu am putea realiza o aplicatie care sa indeplineasca simultan aceste functii : sa fie in stand-by, tot timpul pregatita sa primeasca noi conectari de la diferiti clienti, dar cand utilizatorul doreste sa transmita un mesaj altui utilizator distant, sa o poata face nestingherit de functia de server. Cum se poate realiza acest lucru? Cel mai simplu, comod si eficient mod de a realiza acest lucru este de a folosi diferite fire de executie diferite pentru partea de client si pentru cea de server (tehnica numita multithreading). Dar inainte de a arata cum am realizat practic acest lucru, o sa trecem in revista cateva elemente despre ceea ce inseamna de fapt un fir de executie si ce implica tehnica de multithreading.
2. Programarea folosind multithreading
Orice sistem de calcul modern este capabil sa execute mai multe programe in acelsi imp. Cu toate acestea, in cele mai multe cazuri, unitatea centrala de prelucrare (CPU) nu poate executa la un moment dat decat un singur program. De aceea, sarcina de a rula mai multe programe in acelasi timp revine sistemului de operare, care trebuie sa introduca un model prin intermediul caruia executia programelor, privita din perspectiva utilizatorului, sa se desfasoare in paralel. Se realizeaza, de fapt, un pseudoparalelism, prin care procesorul este alocat pe rand programelor care trebuie rulate, cate o cuanta de timp pentru fiecare, astfel incat din exterior ele par ca ruleaza efectiv in acelasi timp.
2.1. Procese si fire de executie
Un proces este o instanta a unei aplicatii. De exemplu, atunci cand facem double-click pe icoana aplicatiei Notepad din Windows, incepem de faot un proces ce ruleaza aplicatia Notepad. Un proces consista din unul sau mai multe fire de executie, codul, datele si alte resurse ale unui program in memorie [MSDN].
Fiecare proces este o entitate distincta, independenta de celelalte procese aflate in executie la un moment dat. De asemenea, procesorul poate rula la un moment dat un singur proces, procesele sunt executate pe rand, dupa un anumit algoritm de planificare, astfel incat, la nivelul aplicatiilor, acestea pae ca se executa in paralel, se desprind astfel doua idei importante referitoare la procese:
ruleaza independent, avand zone de cod, stiva si date distincte
trebuie planificate la executie, astfel incat ele sa ruleze aparent in paralel
Proces = entitate dinamica ce implica:
procesorul ce-l executa plus alte elemente hardware (memorie, dispozitive,etc.)
secventa de instructiuni (soft)
Practic, la transformarea unui program intr-un proces, calculatorul trebuie sa aloce cate o zona de memorie pentru fiecare din aceste parti si sa puna in PC adresa primei instructiuni.
Starea unui proces este descrisa in totalitate de informatia de mai sus. Mai exact, daca “salvam” cumva aceasta descriere, stingem calculatorul si dupa o saptamana restauram starea asa cum era salvata , procesul isi va continua nestingherit excecutia din locul in care a fost salvat, ca si cum nimic nu s-ar fi intamplat.
Firele de executie fac trecerea de la programarea secventiala la programarea concurenta. Un program secvential reprezinta modelul clasi de program: are un inceput si un sfarsit. Cu alte cuvinte, la un moment dat programul are un singur punct de executie. Un sistem de operare monotasking (MS-DOS) nu estre capabil sa xecute decat un singur proces. Notiunea de fir de executie nu are sens decat in cadrul unui sistem de operare multitasking. Un fir de executie este similar unui proces secvential in sensul ca are un inceput, o secventa de executie si un sfarsit. Diferenta intre un fir de executie si un proces consta in faptul ca un fir de executie nu poate rula independent ci trebuie sa ruleze in cadrul unui proces.
Un fir de executie (thread) este o suscesiune secventiala de intructiuni care se executa in cadrul unui proces. Un program isi poate defini insa nu doar un fir de executie ci oricate, ceea ce inseamna ca in cadrul unui proces, se poate executa simultan mai multe fire de executie, permitand executia concurenta a sarcinilor indeoendente ale acelui program. De asemenea, thread-ul poate fi asemanat cu o verssiune redusa a unui porces, ambele ruland simultan si independent pe o structura secventiala de executie a instructiunilor lor. Executia simultana a firelor de executie in cadrul unui proces este similara cu executia concurenta a proceselor: sistemul de operare va aloca ciclic cuante din timpul procesorului fiecarui fir de executie pana la terminarea lor. Din acest motiv firele de executie se mai numesc si procese usoare.
Pentru a intelege mai bine notiunile de fir si proces vom lua un exemplu: atunci cand pornim Notepad-ul, sistemul de operare creeaza un proces si incepe executia firului de executie principal al acestui proces. Cand acest fir de executie se termina, si procesul se termina. Acest fir de executie primar este oferit sistemului de opaerare de codul de start-up al aplicatiei sub forma unei adrese de functii. De obicei este asresa functiei Main sau WinMain.
Intr-o aplicatie se pot creea fire de executie suplimentare daca se dorste acest lucru. Aceste fire de executie pot efectua task-uri de intretinere sau background, nefiind necesar ca utilizatorul sa astepte ca aceste fire de executie sa fie executate complet.
Firele de executie sunt utile in multe privinte, insa uzual ele sunt folosite pentru executatrea unor operatii consumatoare de timp fara a bloca procesul principal: calcule matematice, ateptarea eliberarii unei resurse, acestea realizandu-se de obicei in fundal.
Un asemenea exemplu unde este foarte utila folosirea multithreading-ului ( a mai multor fire de executie) ar fi situatia in care aplicatia a inceput un proces lung si anevoios de calcul. Daca aplicatia are un singur fir de executie singura cale de a opri calculul ar fi terminarea intregii aplicatii. Programul nu poate raspunde input-urilor utilizator pentru ca este prea ocupat cu alte operatii. Daca am aveam doua fire de executie atunci unul dintre ele ar executa calculul iar celalalt s-ar putea ocupa de input-ul utilizator, astfel putandu-se termina aplicatia in orice moment dorit de catre utilizator.
Un proces poate contine unul sau mai multe fire de eexecutie. Daca aceste fire nu sunt facute vizibile unele pentru altele de catre programator, atunci fiecare fir se executa separat si nu se tie de existenta celorlalte fire de executie. Firele impart resurse comune si isi coordoneaza executia folosind semafoare sau alte metode de comunicare inter-proces.
Trebuie acordata o atentie speciala situatiilor in care mai mult de un fir de executie ar putea cere acces la acelasi obiect.
2.2. Deosebiri intre fire de executie si procese
In primul rand deosebirea consta in faptul ca firele de executie nu pot rula decat in cadrul unui proces. O alta deosebire rezulta din faptul ca fiecare proces are propria sa memorie (propriul sau spatiu de adrese) iar la crearea unui nou proces este realizata o copie exacta a procesului parinte: cod + date; la crearea unui fir de executie nu este copiat decat codul procesului parinte; toate firele de executie au deciacces la aceleasi date, datele procesului original. Practic doua procese care executa acelsi program au memorii complet disjuncte, dar doua thread-uri care executa acelasi program folosesc setul de date in comun. De asemenea comunicarea intre firele de executie este mult mai usoara decat intre procese, prin simpla partajare a variabilelor.
Firele de executie sunt procese care au in comun si segmentul de date, pe langa cel de cod. Din cauza ca thread-urile au in comun atat de mult, cateodata conceptual suint privite ca parte a aceluiasi proces, dar care de data asta poate avea mai multe “fire de executoe” simultam. Pentru utilizator, folosirea mai multor fire de executie duce la senzatia ca programul poate executa simultan mai multe functii.
Sfaturi cu privire la modul de elaborare al programelor cu mai multe fire de executie [“The Complete Guide to Threads”, J. Beveridge si R.Wiener]:
sa se prefere simplitatea si siguranta in locul complexitatii si vitezei
sa n se lucreze cu date care nu sunt intr-o stare sigura ( doau programe sa nu lucreze simultan cu aceleasi date, rezulatele putand fi dezastuoase)
sa se tina cont de faptul ca un fir ce creaza o fereastra va procesa toate mesajele trimise spre acea fereastra.
Sa nu blocheze accesul la o resursa pentru un timp indelungat.
Sa nu creeze pentru fiecare fereastra a unui aplicatii MDI propriul fir de executie
Sa se acorde o atentie speciala sincronizarii firelor de executie.
Ca o concluzie, firele de executie reprezinta nu atat o alternativa, cat o completare pentru lucrul cu mai multe procese. In general, lucrul cu fire multiple de executie este preferabil atunci cand este necesara o interactiune puternica intre secventele de cod ce se xecuta in paralel; atunci cand acestea au putine momente in care trebuie sa comunice, iar interferenta nu este dorita, este indicata utilizarea proceselor. Practic toate sistemele de operare ofera astazi facilitatea de multithreading [MSDN].
2.3. Multithreading MFC
Microdoft Foundation Class Library (MFC), care face parte din Visual C++ ofera suport pentru aplicatii cu mai multe fire de executie.
Toate firele de executie in aplicatii MFC sunt reprezentate de obiecte apartinand clasei CWinThread. In majoritatea situatiilor, nu este necesara crearea explicita a acestor obiecte; se poate folosi functia AfxBeginThread care creaza obiecte CWinThread.
MFC distinge doua tipuri de fire de executie: fire de executie cu interfata utilizator (user interface threads) si fire de executie de tip worker (worker threads). Firele de executie cu interfata utilizator sunt folosite usuak pentru a ase ocupa de input-ul utilizator si pentru a raspunde evenimentelor si mesajelor generate de utilizator. Firele de executie de tip workersunt folosite pentru a complata taskuri, si care nu necesita input utilizator. CWinApp este o clasa in care obiectele instantiate au fire de executie cu interfata utilizator.
Exista fire de executie cu prioritate scazuta, normala si inalta, acest lucru putand fi stabilit de utilizator. Firele de executie cu prioritate mica trebuie sa astepte pna acand firele de executie cu prioritate inalta sis termina munca.
Doua situatii normale pot face ca un fier de executie sa se termine: functia de control iese sau firului de executie nu ii este permis sa ruleze pana la executia completa a taskului asociat.
Firele de executie pot fi in mai multe stari: in executie, blocate, gata de executie sau terminate. Un fir in executie este un fir care are controlul unitatii centrale. Un fir blocat este un fir care asteapta sa fie deblocat de un alt fir (de exemplu cu un semafor). Un fir gata de executie este un fir care asteapta sa primeasca controlul CPU-ului pentru a putea rula. In sfarsit, un fir terminateste un fir care si-a terminat treaba, dar care nu a fost inca observat de parintele sau.
Acum sa aratam cum s-a realizat implementarea:
UINT Asculta(LPVOID pParam)
{
CCriptareView* view = (CCriptareView*)pParam;
sockListen.Create(25500);
BOOL i=FALSE;
do {
i=sockListen.Listen();
} while(!i);
sockListen.Accept(sockRec);
view->ReceptieDate();
return 0;
}
void CCriptareView::OnAsculta()
{
SetDlgItemText(IDC_BUTTON3, "Intrerupe");
ascultaThread = AfxBeginThread(Asculta, this);
}
Se creeaza astfel un thread numit ascultaThread care apeleaza functia Asculta . Codul acestei functii este structurat in jurul directivei Listen care asculta portul in eventualitatea unei conectari. In cazul ca acesta soseste, se apeleaza functia ReceptieDate care reprezinta bucla principala partii de server.
Odata stabiliti acesti pasi ce trebuie urmariti, s-a trecut la realizarea aplicatiei. Mediul folosit pentru dezvolatarea acestei aplicatii este Microsoft® Visual C++®, versiunea a 6-a.
3. Aplicatia Client
Ce doresc sa-i trimit celuilalt utilizator? Mesaje si/sau fisiere.Astfel aplicatia a fost conceputa pe doua planuri: una se ocupa de transmiterea de fisiere, cealalta de trasmiterea de mesaje (asta datorita faptului ca aceste lucrul cu aceste entitati este destul de diferit : pe de o parte in cazul mesajelor nu este necesar decat sa se preia mesajul introdus de calculator si dupa ce a fost criptat folosind una din metodele de criptare haotica, trebuie trimis calculatorului receptor. In cazul fisierelor trebuie ales fisierul de pe calculatorul emitor, la randul lui criptat si apoi trimis in linie. Chiar daca procesul de trimitere a streamului in retea este acelasi, modul de implementare pentru cele doua tipuri de date ce vor fi trimise este putin diferit. In ce mod va fi explicat in cele ce urmeaza.
Partea de client este structurata in doua directii: una se ocupa de trimiterea de fisiere, cealalta se ocupa cu trimiterea de mesaje instant. Selectarea unuia dintre aceste doua moduri se face folosind optiunile Fisier sau Mesaj ale meniului Trimite.
Pentru partea de trimitere de mesaje (optiunea Trimite -> Mesaj) interfata cu utilizatorul are urmatoarele componente:
o casuta pentru editarea mesajului ce va fi transmis celuilalt utilizator
o casuta pentru editarea adresei IP a calculatorului destinatie
un buton pentru trimiterea mesajului.
Modul de functionare:
Programele MFC nu contin o functie principala sau o bucla de evenimente. Gestiunea tuturor evenimentelor se produce „in spatele scenei” pentru programele care folosesc clasa CWinApp. Pentru ca sunt ascunse, avem nevoie de o modaliatate prin care sa ii cerem buclei programului sa ne atentioneze cand au loc tot felul de evenimente in aplicatia nostra ( ex: apasarea unui buton, selectarea unei optiuni din meniu, miscarea mouseului intr-o anumita directie). Aceasta notificare se realizeaza folosind un mecanism numit „message map”. Mecanismul message map identifica evenimentele interesante pentru utilizator si apoi indica functiile corespunzatoare acestor evenimente.
Acest mecanism este implementat si in aplicatia noastra.
BEGIN_MESSAGE_MAP(CCriptareView, CFormView)
//{{AFX_MSG_MAP(CCriptareView)
ON_COMMAND(ID_TRIMITE_FISIER, OnTrimiteFisier)
ON_COMMAND(ID_TRIMITE_MESAJ, OnTrimiteMesaj)
ON_BN_CLICKED(IDC_BUTTON3, OnAsculta)
ON_BN_CLICKED(IDC_BUTTON1, OnTrimite)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()END_MESSAGE_MAP()
Odata cu apasarea butonului TRIMITE, message map-ul va cere MFC-ului sa apeleze procedura de trimitere de mesaje. Acesta procedura a fost implementata astfel :
void CCriptareView::OnTrimiteMesaj()
{
//s-a selectat trimiterea unui mesaj din meniu
m_optiune = optiuneMesaj;
UpdateData(FALSE);
bTrimiteMesaj = TRUE;
}
Se apleaza apoi functia comuna de trasmitere a fisierelor. Pentru a separa la receptie datele care apartin fiserelor de cele ale mesajelor se utilizeaza un identificator , controlat in cazul nostru de variabila BOOLeana bTrimiteMesaj. Pentru a nu avea probleme cu salvarea fisierelor temporare s-a ales solutia de a utiliza directorul temporar asignat sistemului de operare prin utlizarea variabilor de sistem.
void CCriptareView::OnTrimite()
{
TCHAR filePath[2000];
TCHAR fileName[] = "date.tmp";
FILE* fisDate = NULL;
char* buffer;
GetEnvironmentVariable(_T("TEMP"), tempDir, 1000);
strcpy(filePath, tempDir);
strcat(filePath, "\\");
strcat(filePath, fileName);
if(bTrimiteMesaj)
{
fisDate = fopen(filePath,"w");
UpdateData(TRUE);
int lungimeSir = m_texttransmis.GetLength();
buffer = m_texttransmis.GetBuffer(lungimeSir);
fwrite( buffer, 1, lungimeSir, fisDate);
fclose(fisDate);
TrimiteFisier(filePath);
}
else
{
int lungimeCale = m_texttransmis.GetLength();
TrimiteFisier(m_texttransmis.GetBuffer(lungimeCale));
}
}
void CCriptareView::TrimiteFisier(char* buffer)
{
unsigned char octet1, octet2, octet3, octet4;
char ip[16];
char octet_ip[3];
//extragem adresa serverului si o transformam in string
m_serverip.GetAddress(octet1, octet2, octet3, octet4);
GetStrOctet(octet1, octet_ip);
strcpy(ip, octet_ip);
strcat(ip, ".");
GetStrOctet(octet2, octet_ip);
strcat(ip, octet_ip);
strcat(ip, ".");
GetStrOctet(octet3, octet_ip);
strcat(ip, octet_ip);
strcat(ip, ".");
GetStrOctet(octet4, octet_ip);
strcat(ip, octet_ip);
strcat(ip, "\0");
IPServer = CString(ip);
// se apeleaza functia de initializare a criptarii…
long nrcaract=CryptInit(buffer);
TCHAR fileTemp[2000];
TCHAR fileName[] = "dateCriptate.tmp";
FILE* fisDate = NULL;
char* buffer;
GetEnvironmentVariable(_T("TEMP"), tempDir, 1000);
strcpy(fileTemp, tempDir);
strcat(fileTemp, "\\");
strcat(fileTemp, fileName);
CFile f; //trebuie sa fie fisierul criptat
if(!f.Open(fileTemp,CFile::modeRead))
{
MessageBox("Eroare la deschiderea fisierului","Eroare !!!",MB_ICONEXCLAMATION);
}
CString strStr,strRecF;
sockClient.Create();
BOOL ini = FALSE;
do {
ini=sockClient.Connect(IPServer,PORT);
} while(!ini);
CSocketFile fisier(&sockClient);
CArchive arTrimiteFis(&fisier,CArchive::store);
CArchive arPrimesteFis(&fisier,CArchive::load);
if(bTrimiteMesaj)
arTrimiteFis<<(BYTE*)"mes";
else
arTrimiteFis<<(BYTE*)"file";
arTrimiteFis.Flush();
do {
arPrimesteFis>>strRecF;
} while(!arPrimesteFis.IsBufferEmpty());
// se trimit numarul de caractere al fisierului original…
arTrimiteFis<<nrcaract;
arTrimiteFis.Flush();
do {
arPrimesteFis>>strRecF;
} while(!arPrimesteFis.IsBufferEmpty());
// se trimite lungimea fisierului criptat
long lung_fis;
lung_fis=f.GetLength();
char y[100];
ostrstream ies(y,100);
ies<<lung_fis<<ends;
arTrimiteFis<<(BYTE*)y;
arTrimiteFis.Flush(); // atentie trebuie Acknowledge
do {
arPrimesteFis>>strRecF;
} while(!arPrimesteFis.IsBufferEmpty());
BYTE octet;
CString mesaj;
f.SeekToBegin();
for(int k=0;k<lung_fis;k++)
{
try
{
f.Read(&octet,1);
}
catch(…)
{
MessageBox("Eroare la citire.","Eroare !!!",MB_ICONEXCLAMATION);
}
arTrimiteFis<<octet;
arTrimiteFis.Flush();
do { //verifica transmiterea corecta a octetului
arPrimesteFis>>mesaj;
} while (!arPrimesteFis.IsBufferEmpty());
} // end for -> trimitere fisier octet cu octet
f.Close();
}
Ce face exact acesta procedura (metoda)? Prin
UpdateData(TRUE);
int lungimeSir = m_texttransmis.GetLength();
buffer = m_texttransmis.GetBuffer(lungimeSir);
se preia textul scris de catre utilizator dintr-o casuta de editare si este formatat intr-un sir de caractere.
Mai apoi se creaza un socket prin intermediul caruia aplicatia va trimite si va receptiona pachete de date din retea.
Prin urmatoarele linii de cod se incearca conectarea la serverul a carui adresa este data IP-ul introdus in casuta de editare corespunzatoare:
BOOL ini = FALSE;
do {
ini=sockClient.Connect(IPServer,PORT);
} while(!ini);
Pentru a nu folosi doua proceduri diferite pentru cifrarea mesajelor sau a fisierelor, s-a recurs la urmatoarea solutie: se va face doar criptare de fisiere. Deci solutia de compromis este ca vom scrie continutul mesajului intr-un fisier temporar si apoi acesta ca fi criptat si trimis in retea.
Totusi la receptie trebuie sa se stie natura datelor trimise: daca este un mesaj instant sau daca este un fisier. Aceasta se realizeaza prin trimiterea unui identificator special („mes” sau „fisier” ), care in partea de server va determina ca aplicatia sa ia una din umatoarele stari :
asteptare stream mesaj;
asteptare stream fisier.
Pentru partea de trimitere fisiere (optiunea Trimite->Fisier) se porneste o fereasta de dialog in care utilizatorul este rugat sa aleaga fisierul care va fi criptat si apoi trimis in linie.
void CCriptareView::OnTrimiteFisier()
{
//s-a selectat trimiterea unui fisier din meniu
const char fileDialogFilter[]="All Files (*.*)|*.*||";
const char fileDialogExt[]="";
m_optiune = optiuneFisier;
UpdateData(FALSE);
CFileDialog fileDialog(TRUE,fileDialogExt,NULL,OFN_FILEMUSTEXIST,fileDialogFilter);
if (fileDialog.DoModal()==IDOK)
{
m_texttransmis = fileDialog.GetPathName();
UpdateData(FALSE);
}
bTrimiteMesaj = FALSE;
}
Prin apelarea metodei Cryptinit(numeFisier) se realizeaza criptarea fisierului selectat de catre utilizator si se returneaza numarul de caractere al fisierului original. Acest numar este necesar pentru partea de decodare.
4. Criptarea
Pe partea de client a fost necasara implementarea unei metode de cifrare haotica. Am ales din multitudinea de tipuri si sisteme de cifrare, sistemul de cifrare prin incluziune, Mandelbrot.
Ecuatiile acestui sistem pentru cifrarea unui mesaj sunt urmatoarele :
Unde constantele si sunt cheile partajate de emitor si receptor, u este variabila de control ce o aplicam la intrarea sistemului, ea reprezentand nici mai mult nici mai putin decat mesajul ce trebuie transmis.
Un ansamblu de posibile valori care au fost des utilizate in procedurile experimenatele sunt urmatoarele :
– conditiile initiale: , ,
cheile : ,;
Semnalul este iesirea codata care va trebuie transmisa receptorului distant.
Implementarea acestui sistem in aplicatia noastra este urmatoarea :
double CCriptareView::Encrypt(double simbol)
{
double x2k_anterior;
// implementarea ecuatiilor emitorului
x1k1 = x1k*bk + x3c + x4k + x1k * x1k + x1k * x3c – x2k * x2k;
x2k1 = x3c+x5c+2*x1k*x2k;
x4k1 = 0.09+simbol;
//actualizarea variabilelor sistemului
x2k_anterior = x2k;
x1k = x1k1;
x2k = x2k1;
x4k = x4k1;
return x2k_anterior;
}
Aceasta procedura accepta ca si parametru o variabila de tip double (numar real reprezentat pe 32 de biti), care reprezinta „mesajul” ce va fi criptat. Am scris mesajul intre ghilimele pentru a evidentia faptul ca nu este vorba despre intreg mesajul (fisierul) pe care il dorim cifrat, ci doar o mica parte din el care anterior a fost „putin” prelucrat pentru a ajuta sistemul de cifrare. Prelucrare: mesajul este preluat caracter cu caracter, si fiecarui caracter reprezentat initial pe 8 biti (cod ASCII) este reprezentat ca un intreg pe 16 biti, apoi acest numar este inmultit cu o valoare foarte mica, pentru a-l duce in multimea numerelor reale si totodata diferentele intre doua caractere succesive sa fie minime. Din rezulatate exprerimentale s-a determinat ca cele mai indicate valori prin care sa translatam un intreg in multimea numerelor reale au ordinul de marime de 10-8. O valoare mai mare va face ca diferenta intre „caractere” sa fie prea mare, iar o valoare mai mica va duce la ingreunarea calculului fara a se observa imbunatatiri substantiale la nivelul textului cifrat.
Functia de cifrare retureaza o valoare double care reprezinta cifrarea informatiei primite la intrarea sistemului. Acesta este valoarea care va fi trimisa in linie calculatorului receptor.
Metoda de trasmitere a fisierului este urmatoarea:
se determina lungimea fisierului ;
se trimite receptorului aceasta lungime pentru a stii cand se termina transmisiunea. Mai puteam folosi pentru a determina cand s-a terminat de trimis fisierul un identificator, dar s-a ales cealalta solutie ;
apoi octet cu octet se trimite prin retea fisiserul la receptor .
S-au intalnit dificultati la utilizarea obiectelor CSocketFile in sensul ca la receptie de multe ori nu se amestecau datele pentru ca era o problema cu bufferele de transmisie/receptie. Acesta problema a fost rezolvata prin transmiterea din sens invers, de la server la client a unui mesaj de Acknowledge dupa fiecare fragment primit care sa goleasca aceste buffere. Acum se pune problema utilizarii nejudicioase a benzii canalului dar asta este o alta problema. S-a preferat asigurarea calitatii transmisiei in dauna ocuparii benzii.
5. Aplicatia server
Serverul este implementat in urmatorul mod:
Apasarea butonului Asculta determina crearea unui socket de receptie pe un anumit port si intrarea in modul de ascultare (LISTEN). Astfel serverul este pregatit pentru conectarea oricarui client. Iesirea din aceasta stare se produce cand apare o cerere de conectare pe acest port. Odata aceasta cerere a aparut se creeaza un alt socket, socketul initial ramanand activ pentru conectarea eventuala a altui client.
Adresa IP a clientului conectat este preluata de catre program si vizibila intr-un framebox din interfata cu utilizatorul.
In acest moment aplicatia este in stare de stand-by pana cand se primesc date din retea. Datele asteptate de aplicatie sunt indentificatorii de mesaj instant („mes”) sau de fisier („file”) care corespund optiunii facute de utilizatorul calculatorului emitor. Acest identificator va determina intrarea serverului in starea de asteptare mesaj sau fisier.
In cazul in care avem de a face cu un mesaj, se va salva textul cifrat intr-un fisier temporar, acest fisier va fi supus procesului de descifrare ce va fi aratat in cele ce urmeaza, si in cele din urma i se va prezenta utilizatorului intr-o casuta de vizualizare acest mesaj instant. Daca din contra suntem in situatia de a astepta un fisier, utilizatorului i se va prezenta o casuta dialog in care este rugat sa aleaga numele si locatia in care va fi salvat.
Procedura de receptie a fisierului este complementara celei de emisie:
se astepta lungimea fisierului (in octeti) ce va fi transmis ;
se trimite „Ack” pentru receptie corecta ;
cat timp numarul de octeti receptionati este mai mic decat lungimea asteptata, se primeste alt octet.
Odata acest fisier temporar fiind receptionat se poate incepe procesul de descifrare.
6. Descifrarea
Pentru a face descifrarea avem nevoie de un alt sistem criptografic haotic care sa evolueze sincronizat cu cel de la emisie. Trebuie mentionat ca observatorul (receptorul) diferit fata de versiunile anterioare de sisteme criptografice ce se bazau pe haos, dobandeste conditiile de sincronizare doar folosind informatia continuta in textul cifrat sosit din linie.
Deci nici o alta informatie, referitoare la starea sistemului haotic de la emisie nu trebuie trimisa, facand astfel intreg sistemul mai robust impotriva oricarui efort indreptat in a-l sparge.
Singurul neajuns al acestui sistem inovativ este necesitatea ca pentru a descifra al N-lea fragment de mesaj (ultimul al mesajului in clar) este necesar a de a avea in plus doua fragmente de mesaj N+1 si N+2.
Sistemul haotic de la receptie are aproximativ aceeasi structura ca si cel de la emisie:
Unde: – = date necunoscute
– = date estimate
Nu este absolut necasar a avea acelesi conditii initiale si la receptor, sosirea primilor biti de informatie porneste sistemul care va adopta un comportament haotic incepand cu prima iteratie. Pentru a accelera convergenta observatorului am ales ca valorile conditiilor initiale sa fie din campul de variatie al semnalului haotic.
Reconstructia lui x1
Receptorul primeste ca si unica informatie despre emitor, o stare a sistemului care consta aici in variabila .
Datorita acestei variabile vom putea calcula care reprezinta eroarea intre starea estimata de catre emitor, – incluzand mesajul confidential- si starea reprodusa de catre receptor(i .e -). De aici putem gasi eroarea (i.e ) :
,
.
De unde :
; .
Ne gasim in fata unei singularitati cand . O sa propunem aici o solutie care sa ne permita sa trecem de acesta singularitate: ea consista in a forta ca eroarea sa ia ultima valoare calculata (i.e ) cand avem astfel de sigularitati:
,
unde este o constanta pe care o vom alege sa fie in apropiere de zero (10-15).
Intradevar, cand:
de unde .
Si cand :
de unde: .
Putem in acest moment sa reconstituim prima stare a receptorului in functie de eroarea estimata e2 , stare pe care o vom nota cu :
Corectia lui x1
Prin corectie intelegem folosirea starii in calculul starii receptorului pe care o vom nota cu . Asta se face astfel:
,
unde .
Reconstructia mesajului
Acum putem sa reconstituim mesajul emis cu doua iteratii anterioare printr-o simpla operatie de scadere :
Acest sistem are o proprietate interesanta: daca se folosesc alte chei de desifrare decat cele folosite la cifrare, chiar daca diferenta este nesemnificativa, textul descifrat va fi altul decat cel original.
Pentru implementarea practica a receptorului s-a creat o procedura care are urmatoarele linii de cod:
double CCriptareView::DeCrypt(double x2k)
{
//implementarea receptorului
//calculul erorii
e2k=x2k-x2ck;
// corecția pentru evitarea singularității
if ( fabs (x2km) > epsilonk )
x1tkm = x1ckm+e2k*(1/(2*x2km));
else
x1tkm = x1ckm;
// introducerea corectei în valoarea estimate a lui x1
x1ck = x1tkm*bk + x3c + x4ck + x1tkm * x1tkm + x1tkm *x3c – x2km * x2km;
// calcului valorii estimate x2k necesare pentru iterația următoare
x2ck1 = x3c+x5c+2*x1ck*x2k;
// calculul erorii între valoarea estimata și valoarea calculată
e1km = x1tkm-x1ckm;
e1km = e1km/sigmak;
// aproximarea erorii e1 la întregul cel mai apropiat
decim = e1km-floor(e1km);
if (decim > 0.5)
e1km = ceil(e1km);
else
e1km = floor(e1km);
//reactualizarea variabilelor pentru iteratia urmatoare
x2km = x2k;
x1ckm = x1ck;
x2ck = x2ck1;
x4ck = x4ck1;
return e1km;
}
Asemanator cu procedura de cifrare si cea de desifrare primeste ca date de intrare o variabila de tip double de data asta este variabila cifrata „primita” din linie si dupa ce se fac toate operatiile se returneaza mesajul descifrat (in clar).
Observatie ! Datorita faptului ca avem nevoie de cateva iteratii pentru ca cele doua sisteme sa se sincronizeze pentru a nu pierde din informatia utila s-a recurs la un artificiu de implementare software. In fisierul ce va trebui criptat, se introduc inainte de a realiza acesta operatie ( criptarea) o serie de n caratere. De asemenea se adauga un set de 2 caractere si la sfarsitul fisierului pentru a avea astfel informatie suficienta pentru descifrarea corecta a ultimul fragment din textul in clar original. In acest moment suntem pregatiti pentru cifrarea fisierului.
Pe durata descifrarii caracterelor introduse suplimentar cele doua sisteme vor converge si vor urmari aceeasi traiectorie haotica. Odata sistemul sincronizat poate incepe si descifrarea celorlalte fragmente care reprezinta textul in clar cifrat.
Trebuie avut grija ca la salvarea in fisier a textului descifrat, sa inlaturam acelasi numar de caractere ca si cel introdus la emisie (cele n caractere introduse pentru sincronizare si cele 2 caractere introduse pentru asigurarea descifrarii ultimului fragment al textului in clar ).
7. Protocolul de autentificare
Pentru autentificarea celor doi participanti la transmisiune s-a ales un protocol simplu cu cheie secreta . Acesta consta in trimiterea unei secvente de caractere, ce va trebui recunoscuta de catre celalalt participant la protocol. Aceasta secventa este implementata direct in structura serverului si in aceasta versiune a programului nu se poate modifica. Odata secventa receptionata de catre aplicatia server aceasta o compara cu cea aflata in baza lui de date, si in functie de rezultatul acestei comparatii va termina conectarea cu clientul in cazul in care acestea nu se potrivesc, sau ii va trimite la randul sau, aplicatiei client de pe cealalta masina cheia lui de identificare.
Acesta este un protocol simplu de schimbare de chei.
Dezavantajul metodei este ca ar trebui rezervat pentru fiecare client care se conecteaza la server o alta cheie de identificare, care va fi asociata adresei IP a acestuia. Tinand cont de faptul ca se stie in prealabil cu cine se va comunica, adica aceasta aplicatie va fi distribuita intr-un erc restans de utilizatori numarul de astfel de chei nu este prea mare.
Oricum ca o perspectiva de dezovolatare este recomandata implemenatrea unui protocol cu cheie publica, ale carui avantaje au fost aratate intr-o sectiune anterioara. Tinand cont ca este vorba doar de un schimb de chei, principalul dezavantaj al acestui algoritm propus, timpul de cifrare, este minimizat.
Un posibil protocol de autentificare reciproca:
Expeditorul genereaza doua numere aleatoare si le trimite receptorului.
Receptorul primeste aceste doua numere X si Y, realizeaza cu ele o operatie matematica cu acestea doua si obtine rezultatul R1.
Receptorul alege la randul sau alte doua numere aleatoare Z si W, si le trimite expeditorului impreuna cu rezultatul R1.
Expeditorul verifica daca rezultatul R1 primit este acelasi cu cel calculat de el realizand aceeasi operatie matematica cu numerele X si Y. Daca rezultatele conincid inseamna ca receptorul este cel care pretinde ca este, in caz contrar legatura este intrerupta.
Expeditorul realizeaza o operatie matematica cu numerele primite Z si W, obtinand un al doilea rezultat R2 pe care il trimite receptorului.
Se repeta pasul 4, cu deosebirea ca valoarea pusa in dicutie nu mai este R1 ci R2.
REZULTATE EXPERIMENTALE
In urma compilarii, si rularii programului se obtine aplicatia care are urmatoarea interfata grafica cu utilizatorul :
in care se observa impartirea in doua a aplicatiei : una dedicata eventualelor conexiuni care vor aparea (serverul), si cealalta dedicata conexiunilor pe care le vom utiliza noi.
Selectarea optiunii Mesaj… din meniul Trimite permite trasferul de mesaje instant criptate intre cele doua masini :
Toata incecarea de a trasmite date ar fi in zadar, daca nu am activa serverul, adica nu am deschide “poarta” pentru conectari :
Transmiterea de fisiere: procedura este asemanatoare cu cea de la trasmiterea de mesaje
instant., diferenta constand in faptul ca utilizatorului i se ofera o casuta de dialog prin care sa isi aleaga fisierul dorit a fi transmis.
In cazul in care se trimit de fisiere va aparea o fereastra de dlialog in care utilizatorul este rugat sa aleaga locatia si un nume unde sa salveze acest fisier.
Exemplu de criptare : s-a criptat un fisier text care avea urmatoarul continut :
********* Install/uninstall sessmgr service *********
Installing sessmgr service
HelpAssistant account name – HelpAssistant
Entering UpgradeSessmgr
Setting policy registry key
B1 policy key does not exist
Setting fAllowGetHelp policy key result – 0
Leaving UpgradeSessmgr
Successfully setup account
Entering CServiceModule::RegisterServer 1, 1
Installing service…
Entering CServiceModule::IsInstalled()
OpenService() failed with 1060
Leaving IsInstalled() – 0
Entering CServiceModule::Install()…
Entering CServiceModule::IsInstalled()
OpenService() failed with 1060
Leaving IsInstalled() – 0
Leaving CServiceModule::Install() – 0
successfully installing service…
Entering CServiceModule::IsInstalled()
OpenService() Succeeded
Leaving IsInstalled() – 1
Entering SetupEventViewerSource()…
Exiting SetupEventViewerSource() with status code 0…
Leaving CServiceModule::RegisterServer 0x00000000
Entering CreatePendingHelpTable
CreatePendingHelpTable() return 0
*** Finish Setup with Status 0x00000000 ***
O parte a continutului fisierului criptat este urmatorul:
Fisierul receptionat decriptat, este urmatorul :
********* Install/uninstall sessmgr service *********
Installing sessmgr service
HelpAssistant account name – HelpAssistant
Entering UpgradeSessmgr
Setting policy registry key
B1 policy key does not exist
Setting fAllowGetHelp policy key result – 0
Leaving UpgradeSessmgr
Successfully setup account
Entering CServiceModule::RegisterServer 1, 1
Installing service…
Entering CServiceModule::IsInstalled()
OpenService() failed with 1060
Leaving IsInstalled() – 0
Entering CServiceModule::Install()…
Entering CServiceModule::IsInstalled()
OpenService() failed with 1060
Leaving IsInstalled() – 0
Leaving CServiceModule::Install() – 0
successfully installing service…
Entering CServiceModule::IsInstalled()
OpenService() Succeeded
Leaving IsInstalled() – 1
Entering SetupEventViewerSource()…
Exiting SetupEventViewerSource() with status code 0…
Leaving CServiceModule::RegisterServer 0x00000000
Entering CreatePendingHelpTable
CreatePendingHelpTable() return 0
*** Finish Setup with Status 0x00000000 ***
CONCLUZII
Scopul acestei lucrări este de a realiza o aplicație software bazată pe tehnologia client-server, sub Visual C++ pentru platforma Windows, pentru transmisia criptată a unei secvențe de date în timp real.
Noutatea temei constă în utilizarea unui algoritm de cifrare inovativ bazat pe sistemele haotice. Astfel metoda utilizată este metoda incluziunii, aflată încă în continuă dezvoltare în laboratoarele Echipei de Comanda a Sistemelor a E.N.S.E.A Cergy, Franța. Acesta metoda presupune faptul ca mesajul nu este doar adunat semnalului haotic, ci acesta modifică succesiv iteratiile sistemului ducând la ascunderea lui în structura sistemului haotic. Aceasta reprezentă un important obstacol pentru un spion în încercarea de a descifra mesajul. Mesajul nu este deci transportat de catre purtatoarea haotica prin linia de transmisie, ci el este propria lui purtatoare.
Acest algoritm face parte din categoria celor de criptare cu cheie secretă, cheia de la cifrare fiind aceeași cu cea de la descifrare. Cheile trebuie sa fie distribuite in mod secret. Ele au aceeasi valoare ca si totalitatea mesajelor cifrate cu ajutorul lor, pentru ca cunoastrea cheii de catre o persoana neautorizata ii da acces acesteia la toate mesajele.
Pentru moment, când cantitatea de date ce se dorește a fi criptată nu este prea mare, viteza de calcul a procesorului stației nu este esențială. Pe viitor, când aceste cerințe vor crește, se recomandă utilizarea unui sistem cu putere mare de calcul, de exemplu un ADSP Sharc. Aplicația a fost gândită în acest sens, astfel că fără prea mari schimbări la nivelul codului, să se poată realiza această implementare și cu procesoare de semnal. Adică procedura de criptare este împărțită în două parți: prima se ocupă de inițializările sistemului și cealaltă se ocupa de criptarea propriu-zisă. Pentru implementarea pe un procesor de semnal trebuie realizata doar interfațarea cu calculatorul si „translatarea” algoritmului de criptare pe procesor.
Problema cea mai mare nu este timpul de calcul, ci modul în care se va realiza transmisia efectivă a datelor criptate. Este vorba despre modul de implementare a algoritmului de cifrare, care duce la un raport date cifrate-date originale de 8:1. Acesta se datorează în principal reprezentării pe 32 de biți a unui bloc de 8 biți de date.
Referitor la transmisia in timp real a acestor date criptate, valoarea blocului de 32 de octeți, nu se pretează unei comunicări folosind protocolul TCP/IP. Datorita faptului că integritatea datelor trimise în rețea se lasă în grija protocolului de transmisiune folosirea protocolului UDP, nu este la rândul său recomandată. Trebuie deci găsita o cale de compromis în acest sens. O posibila soluție consta în folosirea de blocuri mai mari de date în sistemul de cifrare, astfel crescând și mărimea blocului de date ce trebuie transmis în linie, și deci posibilitatea folosirii TCP/IP-ului cu toate avantajele pe care acesta le oferă din punct de vedere al integrității datelor.
ANEXE
Listingul fisierului antet CriptareView.h
// CriptareView.h : interface of the CCriptareView class
//
/////////////////////////////////////////////////////////////////////////////
#if !defined(AFX_CRIPTAREVIEW_H__02086A19_99F5_496F_9A51_28AC0C18AF4C__INCLUDED_)
#define AFX_CRIPTAREVIEW_H__02086A19_99F5_496F_9A51_28AC0C18AF4C__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
class CCriptareView : public CFormView
{
protected: // create from serialization only
CCriptareView();
DECLARE_DYNCREATE(CCriptareView)
public:
//{{AFX_DATA(CCriptareView)
enum { IDD = IDD_CRIPTARE_FORM };
CIPAddressCtrl m_serverip;
CString m_optiune;
CString m_clientip;
CString m_texttransmis;
CString m_textreceptionat;
//}}AFX_DATA
// Attributes
public:
CCriptareDoc* GetDocument();
// Operations
public:
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CCriptareView)
public:
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
virtual void OnInitialUpdate(); // called first time after construct
//}}AFX_VIRTUAL
// Implementation
public:
void CitesteDinFisier(char* buffer, char* textCitit);
void GetStrOctet(unsigned char octet, char* sir);
void TrimiteFisier(char* buffer);
void ReceptieDate();
double EnCrypt(double);
long OnCryptInit (char*);
virtual ~CCriptareView();
void OnDeCrypt(char*,CString,long);
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
protected:
// Generated message map functions
protected:
//{{AFX_MSG(CCriptareView)
afx_msg void OnTrimiteFisier();
afx_msg void OnTrimiteMesaj();
afx_msg void OnAsculta();
afx_msg void OnTrimite();
afx_msg void OnClose();
afx_msg void OnDestroy();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
#ifndef _DEBUG // debug version in CriptareView.cpp
inline CCriptareDoc* CCriptareView::GetDocument()
{ return (CCriptareDoc*)m_pDocument; }
#endif
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_CRIPTAREVIEW_H__02086A19_99F5_496F_9A51_28AC0C18AF4C__INCLUDED_)
Listingul fisierului sursa Criptare.cpp
// Criptare.cpp : Defines the class behaviors for the application.
//
#include "stdafx.h"
#include "Criptare.h"
#include "MainFrm.h"
#include "CriptareDoc.h"
#include "CriptareView.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CCriptareApp
BEGIN_MESSAGE_MAP(CCriptareApp, CWinApp)
//{{AFX_MSG_MAP(CCriptareApp)
ON_COMMAND(ID_APP_ABOUT, OnAppAbout)
// NOTE – the ClassWizard will add and remove mapping macros here.
// DO NOT EDIT what you see in these blocks of generated code!
//}}AFX_MSG_MAP
// Standard file based document commands
ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew)
ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CCriptareApp construction
CCriptareApp::CCriptareApp()
{
// TODO: add construction code here,
// Place all significant initialization in InitInstance
}
/////////////////////////////////////////////////////////////////////////////
// The one and only CCriptareApp object
CCriptareApp theApp;
/////////////////////////////////////////////////////////////////////////////
// CCriptareApp initialization
BOOL CCriptareApp::InitInstance()
{
if (!AfxSocketInit())
{
AfxMessageBox(IDP_SOCKETS_INIT_FAILED);
return FALSE;
}
AfxEnableControlContainer();
// Standard initialization
// If you are not using these features and wish to reduce the size
// of your final executable, you should remove from the following
// the specific initialization routines you do not need.
// Change the registry key under which our settings are stored.
// TODO: You should modify this string to be something appropriate
// such as the name of your company or organization.
SetRegistryKey(_T("Local AppWizard-Generated Applications"));
LoadStdProfileSettings(); // Load standard INI file options (including MRU)
// Register the application's document templates. Document templates
// serve as the connection between documents, frame windows and views.
CSingleDocTemplate* pDocTemplate;
pDocTemplate = new CSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CCriptareDoc),
RUNTIME_CLASS(CMainFrame), // main SDI frame window
RUNTIME_CLASS(CCriptareView));
AddDocTemplate(pDocTemplate);
// Parse command line for standard shell commands, DDE, file open
CCommandLineInfo cmdInfo;
ParseCommandLine(cmdInfo);
// Dispatch commands specified on the command line
if (!ProcessShellCommand(cmdInfo))
return FALSE;
// The one and only window has been initialized, so show and update it.
m_pMainWnd->ShowWindow(SW_SHOW);
m_pMainWnd->UpdateWindow();
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
//{{AFX_DATA(CAboutDlg)
enum { IDD = IDD_ABOUTBOX };
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
//{{AFX_MSG(CAboutDlg)
// No message handlers
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
// No message handlers
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
// App command to run the dialog
void CCriptareApp::OnAppAbout()
{
CAboutDlg aboutDlg;
aboutDlg.DoModal();
}
/////////////////////////////////////////////////////////////////////////////
// CCriptareApp message handlers
Listingul fisierului sursa CriptareView.cpp
// CriptareView.cpp : implementation of the CCriptareView class
//
#include "stdafx.h"
#include "Criptare.h"
#include <strstrea.h>
#include <sys/stat.h>
#include <string.h>
#include <math.h>
#include "CriptareDoc.h"
#include "CriptareView.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define PORT 25500
int i;
double sigma=0.0000001;
double epsilon=0.00000001;
double x1k,x1k1,sk;
double x2k,x2k1,x3c;
double x4k,x4k1,x5c;
long lNrCar;
//date globale
CString optiuneFisier("Fisierul selectat pt transmisie…");
CString optiuneMesaj("Mesajul introdus pt transmisie…");
CWinThread* ascultaThread;
CSocket sockRec;
CSocket sockListen;
CSocket sockClient;
BOOL bListen = FALSE;
BOOL bTrimiteMesaj = TRUE;
CString IPServer;
//calea catre directorul temporar specific utilizatorului
TCHAR tempDir[1000];
/////////////////////////////////////////////////////////////////////////////
// CCriptareView
IMPLEMENT_DYNCREATE(CCriptareView, CFormView)
BEGIN_MESSAGE_MAP(CCriptareView, CFormView)
//{{AFX_MSG_MAP(CCriptareView)
ON_COMMAND(ID_TRIMITE_FISIER, OnTrimiteFisier)
ON_COMMAND(ID_TRIMITE_MESAJ, OnTrimiteMesaj)
ON_BN_CLICKED(IDC_BUTTON3, OnAsculta)
ON_BN_CLICKED(IDC_BUTTON1, OnTrimite)
ON_WM_CLOSE()
ON_WM_DESTROY()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CCriptareView construction/destruction
CCriptareView::CCriptareView()
: CFormView(CCriptareView::IDD)
{
//{{AFX_DATA_INIT(CCriptareView)
m_optiune = _T("");
m_clientip = _T("");
m_texttransmis = _T("");
m_textreceptionat = _T("");
//}}AFX_DATA_INIT
// TODO: add construction code here
}
CCriptareView::~CCriptareView()
{
}
void CCriptareView::DoDataExchange(CDataExchange* pDX)
{
CFormView::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CCriptareView)
DDX_Control(pDX, IDC_IPADDRESS1, m_serverip);
DDX_Text(pDX, IDC_STATIC1, m_optiune);
DDX_Text(pDX, IDC_STATIC2, m_clientip);
DDX_Text(pDX, IDC_EDIT1, m_texttransmis);
DDX_Text(pDX, IDC_EDIT4, m_textreceptionat);
//}}AFX_DATA_MAP
}
BOOL CCriptareView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return CFormView::PreCreateWindow(cs);
}
void CCriptareView::OnInitialUpdate()
{
CFormView::OnInitialUpdate();
GetParentFrame()->RecalcLayout();
ResizeParentToFit();
}
/////////////////////////////////////////////////////////////////////////////
// CCriptareView diagnostics
#ifdef _DEBUG
void CCriptareView::AssertValid() const
{
CFormView::AssertValid();
}
void CCriptareView::Dump(CDumpContext& dc) const
{
CFormView::Dump(dc);
}
CCriptareDoc* CCriptareView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CCriptareDoc)));
return (CCriptareDoc*)m_pDocument;
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CCriptareView message handlers
void CCriptareView::OnTrimiteFisier()
{
//s-a selectat trimiterea unui fisier din meniu
const char fileDialogFilter[]="All Files (*.*)|*.*||";
const char fileDialogExt[]="";
m_optiune = optiuneFisier;
UpdateData(FALSE);
CFileDialog fileDialog(TRUE,fileDialogExt,NULL,OFN_FILEMUSTEXIST,fileDialogFilter);
if (fileDialog.DoModal()==IDOK)
{
m_texttransmis = fileDialog.GetPathName();
UpdateData(FALSE);
}
bTrimiteMesaj = FALSE;
}
void CCriptareView::OnTrimiteMesaj()
{
//s-a selectat trimiterea unui mesaj din meniu
m_optiune = optiuneMesaj;
UpdateData(FALSE);
bTrimiteMesaj = TRUE;
}
void CCriptareView::OnTrimite()
{
TCHAR filePath[2000];
TCHAR fileName[] = "date.tmp";
FILE* fisDate = NULL;
char* buffer;
GetEnvironmentVariable(_T("TEMP"), tempDir, 1000);
strcpy(filePath, tempDir);
strcat(filePath, "\\");
strcat(filePath, fileName);
if(bTrimiteMesaj)
{
fisDate = fopen(filePath,"w");
UpdateData(TRUE);
int lungimeSir = m_texttransmis.GetLength();
buffer = m_texttransmis.GetBuffer(lungimeSir);
fwrite( buffer, 1, lungimeSir, fisDate);
fclose(fisDate);
TrimiteFisier(filePath);
}
else
{
int lungimeCale = m_texttransmis.GetLength();
TrimiteFisier(m_texttransmis.GetBuffer(lungimeCale));
}
}
void CCriptareView::TrimiteFisier(char* fis_in)
{
//in buffer am calea spre fisierul ce trebuie criptat
unsigned char octet1, octet2, octet3, octet4;
char ip[16];
char octet_ip[3];
GetEnvironmentVariable(_T("TEMP"), tempDir, 1000);
//extragem adresa serverului si o transformam in string
m_serverip.GetAddress(octet1, octet2, octet3, octet4);
GetStrOctet(octet1, octet_ip);
strcpy(ip, octet_ip);
strcat(ip, ".");
GetStrOctet(octet2, octet_ip);
strcat(ip, octet_ip);
strcat(ip, ".");
GetStrOctet(octet3, octet_ip);
strcat(ip, octet_ip);
strcat(ip, ".");
GetStrOctet(octet4, octet_ip);
strcat(ip, octet_ip);
strcat(ip, "\0");
IPServer = CString(ip);
CFile f; //trebuie sa fie fisierul criptat
CString strStr,strRecF;
sockClient.Create();
BOOL ini = FALSE;
do {
ini=sockClient.Connect(IPServer,PORT);
} while(!ini);
CSocketFile fisier(&sockClient);
CArchive arTrimiteFis(&fisier,CArchive::store);
CArchive arPrimesteFis(&fisier,CArchive::load);
long NrCaract=0;
double b,a,dEncData;
FILE *fisier_original,*fisTmp;
FILE *fisSyncro2,*fisCifrat,*fisCryptat;
FILE *fisSyncro1;
//FILE *fisier_criptat,*fisier_lucru,*fisier_dim;
//initializarea variabilelor de stare de la emisie
x1k=-0.66;
x2k=1.05;
x4k=0.1;
x3c=2.28;
x5c=0.548;
a=0;b=0;
fisier_original=fopen(fis_in,"rb");
TCHAR fisier_temp_1[2000];
GetEnvironmentVariable(_T("TEMP"), tempDir, 1000);
strcpy(fisier_temp_1, tempDir);
strcat(fisier_temp_1, "\\");
strcat(fisier_temp_1, "fisSyncro1.tmp");
fisSyncro1=fopen(fisier_temp_1,"wb");
while(!feof(fisier_original))
{
sk=getc(fisier_original);
fputc(sk,fisSyncro1);
}
for(i=1;i<=2;i++)
{
fputc('12',fisSyncro1);
}
fclose(fisSyncro1);
fisSyncro1=fopen(fisier_temp_1,"rb");
TCHAR fisier_temp_2[2000];
strcpy(fisier_temp_2, tempDir);
strcat(fisier_temp_2, "\\");
strcat(fisier_temp_2, "fisSyncro2.tmp");
fisSyncro2=fopen(fisier_temp_2,"wb");
TCHAR fisier_cifrat[2000];
strcpy(fisier_cifrat, tempDir);
strcat(fisier_cifrat, "\\");
strcat(fisier_cifrat, "fisCryptat.tmp");
fisCifrat=fopen(fisier_cifrat,"wb");
TCHAR fisier_dimens[2000];
strcpy(fisier_dimens, tempDir);
strcat(fisier_dimens, "\\");
strcat(fisier_dimens, "fisDimens.tmp");
// aout=fopen(fisier_dimens,"wb");
//pentru asigurarea convergentei se adauga un set de 4 caractere la inceputul fisierului.
for(i=1;i<=4;i++)
{
fputc('12',fisSyncro2);
}
while(!feof(fisSyncro1))
{
sk=getc(fisSyncro1);
fputc(sk,fisSyncro2);
NrCaract++;
}
fclose(fisSyncro2);
//trimit identificatorul de stare: mesaj sau fisier
if(bTrimiteMesaj)
arTrimiteFis<<(BYTE*)"mes";
else
arTrimiteFis<<(BYTE*)"file";
arTrimiteFis.Flush();
do {
arPrimesteFis>>strRecF;
} while(!arPrimesteFis.IsBufferEmpty());
//trimit numarul de caractere
long lNrCaract=NrCaract+4;
arTrimiteFis<<(LONG) lNrCaract;
arTrimiteFis.Flush();
do {
arPrimesteFis>>strRecF;
} while(!arPrimesteFis.IsBufferEmpty());
GetEnvironmentVariable(_T("TEMP"), tempDir, 1000);
TCHAR filePath[2000];
strcpy(filePath, tempDir);
strcat(filePath, "\\");
strcat(filePath, "fisCryptat.dta");
fisCryptat=fopen(filePath,"wb");
//criptarea fisierului
fisTmp=fopen(fisier_temp_2,"rb");
for(i=1;i<=NrCaract+4;i++)
{
sk=getc(fisTmp);
sk=sk*sigma;
b=b++;
///TRansmite in linie !!!
dEncData=EnCrypt(sk); //cripteaza
fwrite(&dEncData,sizeof(dEncData), 1, fisCryptat);
arTrimiteFis<<(double)dEncData;
arTrimiteFis.Flush(); // atentie trebuie Acknowledge
do {
arPrimesteFis>>strRecF;
} while(!arPrimesteFis.IsBufferEmpty());
// end transmitere secventa criptata
}
fclose(fisSyncro1);
fclose(fisTmp);
fclose(fisSyncro2);
fclose(fisCifrat);
}
long CCriptareView::OnCryptInit(char* fis_in)
{
return 0;
}
double CCriptareView::EnCrypt(double sk)
{
double x2k_ant;
x1k1=x1k*(1-x3c) + x4k- x2k * x2k;
x2k1=(1+x5c)*x2k+x1k*x2k;
x4k1=0.09+sk;
x2k_ant=x2k;
x1k=x1k1;
x2k=x2k1;
x4k=x4k1;
return x2k_ant;
}
UINT Asculta(LPVOID pParam)
{
CCriptareView* view = (CCriptareView*)pParam;
sockListen.Create(25500);
BOOL i=FALSE;
do {
i=sockListen.Listen();
} while(!i);
sockListen.Accept(sockRec);
view->ReceptieDate();
return 0;
}
void CCriptareView::OnAsculta()
{
bListen = TRUE;
SetDlgItemText(IDC_BUTTON3, "Intrerupe");
ascultaThread = AfxBeginThread(Asculta, this);
ascultaThread->m_bAutoDelete = FALSE;
}
void CCriptareView::ReceptieDate()
{
TCHAR fileName[] = "receptie.tmp";
TCHAR filePath[2000];
strcpy(filePath, tempDir);
strcat(filePath, "\\");
strcat(filePath, fileName);
CString mesaj;
FILE* fisReceptie = NULL;
long nrcaract;
//ascultaThread->SuspendThread();
CSocketFile fisier(&sockRec);
CArchive arPrimeste(&fisier,CArchive::load);
CArchive arTrimite(&fisier,CArchive::store);
UINT port;
CString client;
sockRec.GetPeerName(client,port);
SetDlgItemText(IDC_STATIC2, client);
do {
arPrimeste>>mesaj;
} while(!arPrimeste.IsBufferEmpty());
arTrimite<<(BYTE*)"Ack";
arTrimite.Flush();
if (mesaj=="mes") // clientul va trimite un mesaj
{
fisReceptie = fopen(filePath,"wb");
long lung;
do {
arPrimeste>>(LONG&) lung; //primeste lungimea "fisierului"
} while (!arPrimeste.IsBufferEmpty());
arTrimite<<(BYTE*)"Ack";
arTrimite.Flush();
double dDataRec;
for (long ix=0;ix<lung;ix++)
{
do {
arPrimeste>>(double) dDataRec;
} while (!arPrimeste.IsBufferEmpty());
fwrite(&dDataRec,sizeof(dDataRec), 1, fisReceptie);
arTrimite<<(BYTE*)"Ack";
arTrimite.Flush();
} //end for //cu error sending/receiving file !
fclose(fisReceptie);
// se apeleaza procedura de decriptare care are ca parametri: numele fisierului
// receptionat "receptie.tmp" dat de filePath si numarul de caractere ce trebuiesc descifrate
// numele fisierului cu date descifrate este:……
GetEnvironmentVariable(_T("TEMP"), tempDir, 1000);
TCHAR fileName[] = "mesaj.tmp";
TCHAR fisierMesaj[2000];
strcpy(fisierMesaj, tempDir);
strcat(fisierMesaj, "\\");
strcat(fisierMesaj, fileName);
OnDeCrypt(filePath,(CString)fisierMesaj,lung-4);
char textReceptionat[1000];
CitesteDinFisier(fisierMesaj, textReceptionat);
SetDlgItemText(IDC_EDIT4, textReceptionat);
}//sf if mesaj
else if (mesaj=="file") // clientul va trimite un fisier
{
//se va afisa o caseta de dialog cu ajutorul careia se va putea seta calea si numele
//sub care se va salva fisierul receptionat
const char fileDialogFilter[]="All Files (*.*)|*.*||";
const char fileDialogExt[]="";
CString caleFisierSalvat;
CFileDialog fileDialog(FALSE,fileDialogExt,NULL,OFN_CREATEPROMPT,fileDialogFilter);
if (fileDialog.DoModal()==IDOK)
caleFisierSalvat = fileDialog.GetPathName();
TCHAR fisierSosit[2000];
strcpy(fisierSosit, tempDir);
strcat(fisierSosit, "\\");
strcat(fisierSosit, "fisSosit.tmp");
fisReceptie = fopen(fisierSosit,"wb");
long lungs;
do {
arPrimeste>>(LONG&) lungs; //primeste lungimea "fisierului"
} while (!arPrimeste.IsBufferEmpty());
arTrimite<<(BYTE*)"Ack";
arTrimite.Flush();
double dDataRec;
for (long ix=0;ix<lungs;ix++)
{
do {
arPrimeste>>(double) dDataRec;
} while (!arPrimeste.IsBufferEmpty());
fwrite(&dDataRec,sizeof(dDataRec), 1, fisReceptie);
arTrimite<<(BYTE*)"Ack";
arTrimite.Flush();
} //end for //cu error sending/receiving file !
fclose(fisReceptie);
OnDeCrypt(fisierSosit,caleFisierSalvat,lungs-4);
SetDlgItemText(IDC_EDIT4, "Fisierul a fost scris pe disk!");
}//sfarsit else – cazul in care este primit un fisier
}
void CCriptareView::OnDeCrypt(char* fisier_sosit,CString fis_out, long lNrCaract)
{
//fisier_sosit reprezinta numele fisierului criptat sosit din linie
//fis_out reprezinta numele fisierului decriptat
double decim;
double x2k,x2km,x3c;
double x5c;
double e2k,e1km;
double x1ck,x1ckm;
double x2ck,x2ck1;
double x4ck,x4ck1;
double x1tkm;
double b;
FILE *fisCryptat;
FILE *fisDecryptat;
fisDecryptat=fopen(fis_out,"wb");
fisCryptat=fopen(fisier_sosit,"rb");
//initializari
//x3c si x5c sunt aceleasi ca si la criptare
x3c=2.28;
x5c=0.548;
x1ckm=-0.66;
x2ck=1.05;
x2km=1.05;
x4ck=0.09;
x4ck1=0.09;
b=0;
for(i=1;i<=lNrCaract+3;i++)
{
//preia din fisCryptat care contine textul criptat si pune la adresa lui x2k
fread(&x2k,sizeof(x2k),1,fisCryptat);
b=b++;
e2k=x2k-x2ck;
if(fabs(x2km)>epsilon)
x1tkm=x1ckm+e2k*(1/(x2km));
else
x1tkm=x1ckm;
//implementarea ecuatilor pentru decriptare
x1ck=x1tkm*(1-x3c)+ x4ck – x2km * x2km;
x2ck1=(1+x5c)*x2k+ x1ck*x2k;
//recuperarea mesajului
// calcul eroare
e1km=x1tkm-x1ckm;
e1km=e1km/sigma;
decim=e1km-floor(e1km);
if (decim>0.5)
e1km=ceil(e1km);
else
e1km=floor(e1km);
if (b>=8)
fputc(e1km,fisDecryptat);
//actualizarea variabilelor
x2km=x2k;
x1ckm=x1ck;
x2ck=x2ck1;
x4ck=x4ck1;
}//for
fclose(fisCryptat);
fclose(fisDecryptat);
}
// conversie unsigned char -> sir de caractere
void CCriptareView::GetStrOctet(unsigned char octet, char* sir)
{
char buffer[4];
int lungime;
if(octet<100 && octet > 10)
lungime = 1;
else if(octet<10)
lungime = 0;
else
lungime = 2; //pentru numerele de la 100 la 255
for(int i = lungime; i >= 0; i–)
{
if(octet<10)
buffer[i] = octet + 48;
else
buffer[i] = octet%10 + 48;
octet = octet/10;
}
buffer[lungime + 1] = '\0';
strcpy(sir, buffer);
}
void CCriptareView::CitesteDinFisier(char *caleFisier, char* textCitit)
{
char* buffer;
FILE *fis = NULL;
struct _stat buf;
long sizeOfFile = 0;
//deschidem si adaugam in fisier
fis = fopen(caleFisier, "r");
//citeste informatii despre fisier printre care si lungimea lui, pentru a sti cat sa
//alocam pt buffer-ul in care citim continutul fisierului
_stat(caleFisier, &buf);
sizeOfFile = buf.st_size;
buffer = new char[sizeOfFile];
fread(buffer, sizeof(char),sizeOfFile, fis);
fclose(fis);
buffer[sizeOfFile] = 0x00; //sfarsitul de sir
strcpy(textCitit, buffer);
//facem null buffer-ul alocat mai devreme
buffer = NULL;
}
void CCriptareView::OnClose()
{
CFormView::OnClose();
}
void CCriptareView::OnDestroy()
{
if(bListen)
{
WaitForSingleObject(ascultaThread->m_hThread, INFINITE);
delete ascultaThread;
// if(sockRec.AssertValid)
sockRec.Close();
sockListen.Close();
sockClient.Close();
}
CFormView::OnDestroy();
}
BIBLIOGRAFIE
[1] Bruce Schneier, ” Applied cryptography: Protocols, Algorithms and Source Code in C ”,
John Wiley & Sons Inc., New York, 1996.
[2]. Florin Munteanu, “Între ordine si dezordine: o muchie a haosului”, 1997
[3] Marshall Brain, Lance Lovette, “Developing Professional Applications in
Windows 98 and NT”
[4] Francesco Fuzio, “Un protocollo di Comunicazione per la Sincronizzazione di Sistemi
Caotici nella Crittografia : Progetto e Implementazione “, Projet de fin d’études à l’ENSEA,2002.
[5] David J. Kruglinski "Programming MicroSoft® Visual C++®, Fifth edition",
Microsoft Press 1998
[6] Kate Gregory "Special Edition Using Visual C++ 6"
[7] I.Belmouhoub, "Cryptographie chaotique" Projet à l’Université de Paris-Sud UFR
D’Orsay, 2002
[8]. Microsoft Corporation, “MicroSoft Developer Network Library”, October 2001
[9]. ***, “Introduction to Public-Key Cryptography”
http://developer.netscape.com/docs/manuals/security/pkin/index.thml
Copyright Notice
© Licențiada.org respectă drepturile de proprietate intelectuală și așteaptă ca toți utilizatorii să facă același lucru. Dacă consideri că un conținut de pe site încalcă drepturile tale de autor, te rugăm să trimiți o notificare DMCA.
Acest articol: . Comunicarea Intre Doua Sisteme Haotice In Timp Discret (ID: 148963)
Dacă considerați că acest conținut vă încalcă drepturile de autor, vă rugăm să depuneți o cerere pe pagina noastră Copyright Takedown.
