/* jos tuntuu siltä, niin kertokaa onko vika algoritmissa vai itse koodissa, kun ei kryptaa oikein tota tekstiä kertokaa samalla onko okei laittaa putkaan omia koodeja korjattaviksi */ #include <iostream> #include <string> #include <fstream> #include <time.h> using namespace std; char* resize(char* data, int oldsize, int newsize, char filler='\n'); char* EC(char* data, int ndata, const char* key, int nkey, bool deletedata=false, int ikey=0); char* DC(char* data, int ndata, const char* key, int nkey, bool deletedata=false, int ikey=-2); int main() { /*char* avain=new char[16]; avain[0]=67; avain[1]=175; avain[2]=250; avain[3]=91; avain[4]=78; avain[5]=6; avain[6]=203; avain[7]=198; avain[8]=109; avain[9]=47; avain[10]=155; avain[11]=83; avain[12]=98; avain[13]=42; avain[14]=83; avain[15]=19; char* c="jukopliutamasokistit"; char* ccrypted=EC(c,21,avain,16); char* cdecrypted=DC(ccrypted,21,avain,16); ccrypted=resize(ccrypted,21,22,'\0'); avain=resize(avain,16,17,'\0'); /* kerrotaan käyttäjälle mitä ohjelma on saanut aikaan */ /*cout << c << " kryptattuna avaimella " << avain << " on\n" << ccrypted << " ja dekryptauksen tulos on " << cdecrypted <<"\n"; delete [] ccrypted; delete [] cdecrypted;*/ for (int i=0;i<10;i++) // vertaillaan EC:n tuloksia eri avaimella ja { // samalla kryptattavalla tekstillä char* avain=new char[5]; // tehdään avain avain[0]=i*25; // asetetaan arvot avain[1]=50; avain[2]=100; avain[3]=150; avain[4]=200; char* c="cryptattava"; cout << c << "->" << EC(c,11,avain,5) << "\n"; //cout << c << "->" << DC(EC(c,12,avain,5),12,avain,6) << "\n"; } return 0; } /* (resize) turha selittää kun ei ole käytössä deletoi data:n ja palauttaa taulukon, jolla on sama sisältö kuin data:lla, mutta eri kokoisena ja siten, että ylimääräisiin alkioihin on pistetty filler:in sisältö */ char* resize(char* data, int oldsize, int newsize, char filler) { char * vali=new char[newsize]; for (int i=0;i<oldsize&&i<newsize;i++) { vali[i]=data[i]; } if (newsize>oldsize) for (int i=oldsize;i<newsize;i++) vali[i]=filler; delete [] data; return vali; } char* EC(char* data, int ndata, const char* key, int nkey, bool deletedata, int ikey) { if (ikey>=nkey) return data; // palautetaan data käsittelemättömänä kun rekursio päättyy char* encrypted=new char[ndata]; // luodaan ndata:n kokoinen taulukko, johon data kryptataan encrypted[0]=data[0]^key[ikey]; // xorrataan datan eka alkio key[ikey]:llä // ikey on se key:n alkio, jolla tällä kertaa xorrataan data // ikey:n arvoina käydään läpi rekursiossa kaikki key:n alkiot for (int i=1;i<ndata;i++) // xorrataan loput alkiot ekan alkion perusteella { encrypted[i]=data[i-1]^data[i]; } if (deletedata) delete [] data; // data deletoidaan, jos funktiota on kutsuttu EC:n sisältä // muuttujaa tarvitaan, sillä kun käyttäjä kutsuu funktiota, // se ei saa tuhota data:a, mutta kun se kutsuu itseään // täytyy data tuhota, jottei ilmaan jäisi varattua taulukkoa // jokaista kutsuttua funktiota kohti return EC(encrypted,ndata,key,nkey,true,ikey+1); // rekursio-plop } char* DC(char* data, int ndata, const char* key, int nkey, bool deletedata, int ikey) { if (ikey==-2) ikey=nkey-1; // DC on EC:n palautus, joten sitä lie turha sen tarkemmin kommentoida if (ikey==-1) return data; char* decrypted=new char[ndata]; decrypted[0]=data[0]^key[ikey]; for (int i=1;i<ndata;i++) { decrypted[i]=decrypted[i-1]^data[i]; } if (deletedata) delete [] data; return DC(decrypted,ndata,key,nkey,true,ikey-1); } /*char* EC(const char* data, int ndata, const char* key, int nkey) { char* encrypted=new char[ndata]; for (int ik=0;ik<nkey;ik++) { encrypted[0]=data[0]^key[ik]; for (int i=1;i<ndata;i++) { encrypted[i]=data[i-1]^data[i]; } } return encrypted; } char* DC(const char* data, int ndata, const char* key, int nkey) { char* decrypted=new char[ndata]; for (int ik=0;ik<nkey;ik++) { decrypted[0]=data[0]^key[ik]; for (int i=1;i<ndata;i++) { decrypted[i]=decrypted[i-1]^data[i]; } } return decrypted; }*/
Mod Huom. Käytetääs niitä kooditageja
"... ei liene toimivansa." Opettele suomea :)
Mikäs ongelma tuossa on? Yleensä kannattaa kertoa mieluummin se kuin vain tunkea koodi tänne. Useimpia ei kiinnosta korjata sitä, mutta kysymyksiin ja ongelmiin kyllä saa apua.
Minulla ainakin näyttisi toimivan ihan hyvin, kun laitoin pääfunktion for-silmukkaan tulostuksen näin:
cout << c << " -> " << EC(c,12,avain,5) << " -> " << DC(EC(c,12,avain,5),12,avain,5) << "\n";
Lopputulos näytti minun merkistölläni tältä:
cryptattava -> kµ];g�� ���a -> cryptattava cryptattava -> rµ];~�� ���a\Doc� -> cryptattava cryptattava -> Yµ];U�� ���aion � -> cryptattava cryptattava -> µ];,�� ���aDIA � -> cryptattava cryptattava -> �µ];��� ���ailes� -> cryptattava cryptattava -> �µ];��� ���aE=C:� -> cryptattava cryptattava -> ýµ];ñ�� ���aual � -> cryptattava cryptattava -> ĵ];È�� ���aK\v1� -> cryptattava cryptattava -> £µ];¯�� ���a2\os� -> cryptattava cryptattava -> Šµ];†�� ���apl\;� -> cryptattava
Tiedostona, niin löytyvät oudotkin merkit.
Lähinnä tuossa pitää varoa sitä, että ei tule muistivuotoja, ja sitä, että ei kryptatussa käytä merkkejä, joita ei voi tulostaa. Esimerkiksi se nollamerkki katkaisee jonon.
Metabolix sanoi:
"Esimerkiksi se nollamerkki katkaisee jonon"
> Miksi käyttää stringiä - raskasta. Eipä tule tuollaisia ongelmia, jos käyttää ihan char taulukkoa
Nyt en oikein ymmärtänyt Jtm:n asiaa.
Ilmeisesti Jtm sotkee string-luokan ja char-taulukon keskenään.
ville-v tuolla perusteella edellinen kommenttini olisi ristiriidassa itsensä kanssa
Ette taida siis tietää, ettei char-taulukolla ole esimerkiksi mitään nollamerkki ongelmaa, kuten stringillä on. Jos esimerkiksi lataat tiedoston, jossa on yksikin '\0' eli nollamerkki, stringiin - esim. length/size-funktio ei enää osaa palauttaa stringin pituutta oikein, koska string-luokka käyttää lopetusmerkkinä '\0'
Jtm: Et tainnut tietää, että kun char-taulun kirjoittaa tekstimuotoiseen tiedostoon <<-operaattorilla, kirjoittaminen loppuu nollamerkkiin. Siksipä, jos aikoo kryptaustaan käyttää tiedostossa muuten kuin koko tiedoston matkalla tai muulla määrätyn mittaisella matkalla, pitää käyttää jotakin, jossa ei pääse tulemaan nollia. Tietenkin jos tiedetään, että tekstiä on tasan 23679 kirjainta, niin silloin voidaan lukea ja kirjoittaa binäärimuodossa sen verran, mutta jos ei tiedetä, niin voi tulla ongelmia.
Ja eihän täällä ole kukaan stringiä käyttänyt. Tässä tapauksessa tiedän kyllä, mistä itse puhun :)
Tietenkin loppuu nollamerkkiin jos talletetaan teksti-muodossa. Mutta jos nollamerkin haluaa mukaan niin tallennetaan suoraan binaarina. Se paljon tiedosto vie tilaa, siitä näkee aina suoraan monta kirjaisinta kryptattava tieto tulee sisältämään. Myös kryptatun tiedon pituus voidaan laskea, sillä kryptaus noudattaa aina tiettyä logiikkaa.
Käytitte epäsuorasti string-tekniikkaa
Kannattaa käyttää fwrite funktiota (stdio.h) tuollaisiin asioihin niin ei tule ongelmia hassujen merkkien kanssa ja tiedostoon päätyy juuri niin monta merkkiä kuin itse haluat.
Ja sitten muistetaan avata tiedosto muodossa "wb" ja "rb" (tai C++-streameilla ios::binary), etteivät \r ja \n muutu \r\n-pareiksi.
Tuossa kokoasiassa tulee sitten se, että tiedostoon pitää tallentaa myös jokaisen tekstin koko, jos sama tiedosto sisältää useampia tekstinpätkiä. Ja jos kryptausta aikoo käyttää muuallakin kuin omissa binääritiedostoissaan, esimerkiksi PHP-skripteissä tms, niin silloin on syytä tehdä versio, joka käyttää melko rajallista merkkikantaa.
Aihe on jo aika vanha, joten et voi enää vastata siihen.