/*
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.