/* Ver-/Entschluesseln von Dateien mit der 'Buch Methode' 19-05-2019 -- heinz Als Schluessel dient eine beliebige Datei. Sie sollte gross genug sein und muss aus allen 256 Zeichen bestehen. Im Moment sollten keine Schluesseldateien verwendet werden die groesser als 900MB sind! ToDo: ------- Es werden sicher Probleme auftauchen, wenn die Schluesseldatei so gross ist, dass dabei Positionen herauskommen die mehr als 9 Stellen haben. (Also groesser als 999999999) Siehe >int Zahllaenge(long long int Z)< Man koennte vlt. einfach die Schluesselgroesse auf <1GB beschraenken... */ // Serviceschalter --------------------------------------------------------------------------------- // Debug-Textausgaben an-/ausschalten. #define DEBUG false /* Tarnung an-/ausschalten. Wenn Tarnung aus ist, werden die Adressen nur als eine lange Zeile von Nummern (Fundstellen) ausgegeben. Die erste Stelle enthaelt die Anzahl der Stellen der Adresse. Dann kommt die Adresse und dann wieder die Anzahl der Stellen u.s.w. Die Tarnung macht aus der langen Liste von Zahlen eine halb so grosse Datei mit Bytewerten (Immer 2 Zahlen werden zu zu einem Wert zusammengefasst und gespeichert) */ #define TARNUNG true // Analyse-Modus an-/ausschalten. // (Wenn Analyse an ist, werden Adressen Zeile fuer Zeile ausgegeben um die ermittelten Adressen besser zu erkennen) // (!Zur Analyse muss auch die Tarnung ausgeschaltet sein!) #define ANALYSE false // Include ----------------------------------------------------------------------------------------- #include #include #include #include #include #include #include #include #include "anleitung.h" // Typen ------------------------------------------------------------------------------------------- // Programm-Optionen struct option opts[]={ {"verschluesseln", required_argument,0, 'v'}, {"verschluesseln_extrem", required_argument,0, 'V'}, {"entschluesseln", required_argument,0, 'e'}, {"zieldatei", required_argument,0, 'z'}, {"schluesseldatei", required_argument,0, 's'}, {"schluesselfrage", required_argument,0, 'S'}, {"schluesseltest", required_argument,0, 't'}, {"schluesseltest_frage", no_argument, 0, 'T'}, {"keine_ausgaben", no_argument, 0, 'k'}, {"anleitung", no_argument, 0, 'a'}, {"help", no_argument, 0, 'h'}, {0, 0, 0, 0} }; // Globales ---------------------------------------------------------------------------------------- char VERSION[]={"V 0.11"}; // Pools der Schluesseldatei long long int* pospool[256]; long long int pospool_groesse[256]; char* pool=NULL; char* tarnpool=NULL; // Schluesselnoten char schluesselnoten[7][20]={ "Optimal", "Gut", "Mittelmaessig", "Ausreichend", "Schlecht", "Sehr Schlecht", "Miserabel"}; // Dateinamen const int MAX_ZEILENLAENGE=1024; char quelldateiname[MAX_ZEILENLAENGE]={""}; char zieldateiname[MAX_ZEILENLAENGE]={""}; char schluesseldateiname[MAX_ZEILENLAENGE]={""}; // Tempdatei char tempdateiname[]={"/tmp/V2_enttarn.bin"}; // Groesse der Schluesseldatei long long int schluesseldatei_groesse=0; // Aktivitaetsanzeige bool aktiv_anzeige=true; char aktiv_zeichen[][2]={ "|", "/", "-", "\\", ""}; bool textausgabe=true; // Extrem verschluesseln. (Jedes Zeichen im pool wird nur einmal verwendet) bool extrem=false; const int extrem_versuche=4000;// (So oft wird versucht eine passende Position im Pool zu finden) // Funktionen -------------------------------------------------------------------------------------- bool Schluesseldatei_einlesen(char*);// (dateiname) void Verschluesseln(); void Entschluesseln(); void Tarnen(); void Enttarnen(); bool Schluesseldatei_testen();// Gibt Schluesseldatei=OK zurueck. void Schluesseldateiname_abfragen(); int Zahllaenge(long long int);// (zahl) Gibt Ziffern-Anzahl zurueck. void Pospool_erweitern(int,long long int);// (zeichen, position) void Pools_leeren(); void Programm_beenden(); bool Datei_existenz_test(char*);// (dateiname) Gibt existiert zurueck. long long int Dateigroesse(char*);// (dateiname) Gibt groesse in Bytes zurueck. void Datei_loeschen(char*);// (dateiname) void Aktivitaets_anzeige(); void Anleitung_ausgeben(); void Bedienung(); // Debug Funktionen -------------------------------------------------------------------------------- #if DEBUG void Test_pool_ausgabe(); #endif // Hauptteil --------------------------------------------------------------------------------------- int main(int argc, char *argv[]) { if(argc==1){Bedienung();} bool entschluesseln=false; bool verschluesseln=false; bool schluesseltest=false; int optc=0; while((optc=getopt_long(argc,argv,"v:V:e:z:s:St:Tkah",opts,NULL))!=EOF) { switch(optc) { case'V': extrem=true; case'v': strncat(quelldateiname,optarg,MAX_ZEILENLAENGE-1); verschluesseln=true; break; case'e': strncat(quelldateiname,optarg,MAX_ZEILENLAENGE-1); entschluesseln=true; break; case'z': strncat(zieldateiname,optarg,MAX_ZEILENLAENGE-1); break; case's': if(strlen(schluesseldateiname)!=0) { fprintf(stderr,"\aSie koennen nur eine Schluesseldatei angeben!\n"); exit(1); } strncat(schluesseldateiname,optarg,MAX_ZEILENLAENGE-1); break; case'S': if(strlen(schluesseldateiname)!=0) { fprintf(stderr,"\aSie koennen nur eine Schluesseldatei angeben!\n"); exit(1); } Schluesseldateiname_abfragen(); break; case't': if(strlen(schluesseldateiname)!=0) { fprintf(stderr,"\aSie koennen nur eine Schluesseldatei angeben!\n"); exit(1); } strncat(schluesseldateiname,optarg,MAX_ZEILENLAENGE-1); schluesseltest=true; fprintf(stderr,"Test der Schluesseldatei >%s<...\n",schluesseldateiname); break; case'T': if(strlen(schluesseldateiname)!=0) { fprintf(stderr,"\aSie koennen nur eine Schluesseldatei angeben!\n"); exit(1); } Schluesseldateiname_abfragen(); schluesseltest=true; break; case'k': textausgabe=false; aktiv_anzeige=false; break; case'h': Bedienung(); break; case'a': Anleitung_ausgeben(); break; } } // Man kann nicht Ver- und Entschluesseln gleichzeitig if(verschluesseln && entschluesseln) { fprintf(stderr,"\aSie muessen sich entscheiden! Wollen Sie Ver- oder Entschluesseln?\n"); exit(1); } // Quell-, Ziel- und Schluesseldatei muessen angegeben sein! if(strlen(quelldateiname)==0 && !schluesseltest) { fprintf(stderr,"\aSie muessen einen Dateinamen angeben!\n"); exit(1); } if(strlen(zieldateiname)==0 && !schluesseltest) { fprintf(stderr,"\aSie muessen einen Ziel-Dateinamen angeben!\n"); exit(1); } if(strlen(schluesseldateiname)==0) { fprintf(stderr,"\aSie muessen eine Schluesseldatei angeben!\n"); exit(1); } // Dateien auf existenz pruefen if(!Datei_existenz_test(quelldateiname) && !schluesseltest) { fprintf(stderr,"\aDie Quelldatei >%s< extstiert nicht!\n",quelldateiname); exit(1); } if(!Datei_existenz_test(schluesseldateiname)) { fprintf(stderr,"\aDie Schluesseldatei >%s< extstiert nicht!\n",schluesseldateiname); exit(1); } // Vorbereitung ------------------------------------------------------------------------------------ // Zufall srand48(time(0)); // Pool Leeren for(int z=0;z<256;z++) { pospool[z]=NULL; pospool_groesse[z]=0; } // Groesse der Schluesseldatei feststellen schluesseldatei_groesse=Dateigroesse(schluesseldateiname);// (dateiname) Gibt groesse in Bytes zurueck. // Speicher fuer Schluesseldatei erstellen pool=(char*)calloc(schluesseldatei_groesse,sizeof(char)); // Schluesseldatei einlesen if(Schluesseldatei_einlesen(schluesseldateiname))// (dateiname) { if(!Schluesseldatei_testen()) { fprintf(stderr,"\aDie Schluesseldatei ist nicht verwendbar!\n"); Programm_beenden(); } } // Schluessel nur testen if(schluesseltest){Programm_beenden();} #if ! TARNUNG fprintf(stderr,"\a\nAchtung Tarnung ist ausgeschaltet...\n\n"); #endif #if ANALYSE fprintf(stderr,"\a\nAchtung Analyse-Modus ist angeschaltet...\n\n"); #endif // Ver-, Entschluesseln ---------------------------------------------------------------------------- if(verschluesseln) { Verschluesseln(); } if(entschluesseln) { Entschluesseln(); } // Ende -------------------------------------------------------------------------------------------- Programm_beenden(); } // Funktionen -------------------------------------------------------------------------------------- bool Schluesseldatei_einlesen(char* SDN)// (dateiname) { // Schluesseldatei einlesen... #if DEBUG fprintf(stderr,"Schluesseldatei >%s< einlesen...\n",SDN); #endif if(textausgabe)fprintf(stderr,"Lese Schluesseldatei >%s\n",schluesseldateiname); // File-Handler erzeugen std::ifstream load(SDN,std::ios::in); if(load==NULL) { fprintf(stderr,"\aSchluesseldatei >%s< konnte nicht geoeffnet werden!\n",SDN); return(false); } // Schluesseldatei lesen long long int pos=0; char Z; while(true) { Aktivitaets_anzeige(); load.get(Z); if(load.eof()){break;} // Positionen im Positions-Pool ablegen Pospool_erweitern((unsigned char)Z,pos); // (zeichen, position) // Schluessel-Werte im Zeichen-Pool ablegen pool[pos]=Z; pos++; } load.close(); #if DEBUG Test_pool_ausgabe(); #endif return(true); } void Verschluesseln() { #if DEBUG fprintf(stderr,"Verschluesseln gestartet...\n"); #endif // Quelldatei einlesen... #if DEBUG fprintf(stderr,"Quelldatei >%s< lesen,\nZieldatei >%s< schreiben...\n",quelldateiname,zieldateiname); #endif if(textausgabe)fprintf(stderr,"Verschluesseln von >%s<\nMethode >%s...\n",quelldateiname,extrem?"Extrem":"Normal"); // File-Handler erzeugen std::fstream load(quelldateiname,std::ios::in); if(load==NULL) { fprintf(stderr,"\a>%s< konnte nicht geoeffnet werden!\n",quelldateiname); return; } std::fstream save; save.open(zieldateiname,std::ios::out); if(save==NULL) { fprintf(stderr,"\akonnte >%s< nicht anlegen!\n",zieldateiname); return; } // Verschluesseln char Z; long long int zufall=0; while(true) { Aktivitaets_anzeige(); load.get(Z); if(load.eof()){break;} if(!extrem) { // Normal Verschluesseln zufall=lrand48()%pospool_groesse[(unsigned char)Z]; #if ANALYSE save<=0) { gefunden=true; break; } versuche++; } if(gefunden) { #if ANALYSE save<%s< ist nicht gross genug!\n",schluesseldateiname); load.close(); save.close(); Datei_loeschen(zieldateiname);// (dateiname) Programm_beenden(); } } //printf("Zeichen=%i # poolgr.=%lli # Z=%lli\n",(unsigned char)Z,pospool_groesse[(unsigned char)Z],zufall); } load.close(); save.close(); #if TARNUNG Tarnen(); #endif #if DEBUG fprintf(stderr,"Verschluesseln beendet.\n"); #endif } void Entschluesseln() { #if DEBUG fprintf(stderr,"Entschluesseln gestartet...\n"); #endif // Quelldatei einlesen... #if DEBUG fprintf(stderr,"Quelldatei >%s< lesen,\nZieldatei >%s< schreiben...\n",quelldateiname,zieldateiname); #endif #if TARNUNG Enttarnen(); // File-Handler erzeugen std::fstream load(tempdateiname,std::ios::in); if(load==NULL) { fprintf(stderr,"\a>%s< konnte nicht geoeffnet werden!\n",tempdateiname); return; } #else std::fstream load(quelldateiname,std::ios::in); if(load==NULL) { fprintf(stderr,"\a>%s< konnte nicht geoeffnet werden!\n",quelldateiname); return; } #endif std::fstream save; save.open(zieldateiname,std::ios::out); if(save==NULL) { fprintf(stderr,"\akonnte >%s< nicht anlegen!\n",zieldateiname); return; } // Entschluesseln char Z; while(true) { Aktivitaets_anzeige(); #if ANALYSE long int W=0; char zeichen[MAX_ZEILENLAENGE]; load.getline(zeichen,MAX_ZEILENLAENGE); if(load.eof()){break;} W=atol(zeichen); #else load.get(Z); if(load.eof()){break;} int Zm=Z-48; long int W=0; for(int z=0;z%s<\n",schluesseldateiname); Programm_beenden(); } //printf("%c",pool[W]); } load.close(); save.close(); // Tempdatei loeschen #if ! ANALYSE Datei_loeschen(tempdateiname);// (dateiname) #endif #if DEBUG fprintf(stderr,"Entschluesseln beendet.\n"); #endif } void Tarnen() { #if DEBUG fprintf(stderr,"Tarnen...\n"); #endif // Groesse der letzten Ausgabe feststellen long long int dg=Dateigroesse(zieldateiname); // Speicher fuer komplette Zieldatei anlegen tarnpool=(char*)calloc(dg,sizeof(char)); #if DEBUG fprintf(stderr,"Datei- Poolgroesse=%lli\n",dg); #endif // File-Handler erzeugen std::fstream load(zieldateiname,std::ios::in); if(load==NULL) { fprintf(stderr,"\a>%s< konnte nicht geoeffnet werden!\n",zieldateiname); return; } // Datei einlesen long long int pos=0; char Z; while(true) { Aktivitaets_anzeige(); load.get(Z); if(load.eof()){break;} tarnpool[pos]=Z; pos++; } load.close(); // Kennung erzeugen plus Marker, ob die Ursprungsdatei eine gerade oder ungerade anzahl von Bytes enthaelt char kennung[4]={""}; sprintf(kennung,"V2%s",(dg%2==0)?"+":"-"); // File-Handler erzeugen std::fstream save; save.open(zieldateiname,std::ios::out); if(save==NULL) { fprintf(stderr,"\akonnte >%s< nicht anlegen!\n",zieldateiname); return; } // Datei schreiben save<=pos) { save<=pos){break;} } save.close(); #if DEBUG fprintf(stderr,"Tarnen beendet.\n"); #endif } void Enttarnen() { #if DEBUG fprintf(stderr,"Enttarnen...\n"); #endif // Groesse der Quelldatei feststellen long long int dg=Dateigroesse(quelldateiname); // File-Handler erzeugen std::fstream load(quelldateiname,std::ios::in); if(load==NULL) { fprintf(stderr,"\a>%s< konnte nicht geoeffnet werden!\n",quelldateiname); return; } std::fstream save; save.open(tempdateiname,std::ios::out); if(save==NULL) { fprintf(stderr,"\akonnte >%s< nicht anlegen!\n",tempdateiname); return; } // Kennung einlesen bool gerade=true; char Z; for(int kp=0;kp<3;kp++) { load.get(Z); switch(kp) { case 0: if(Z!=86)// V { fprintf(stderr,"\aKeine gueltige Datei! >%s<\n",quelldateiname); Programm_beenden(); } break; case 1: if(Z!=50)// 2 { fprintf(stderr,"\aKeine gueltige Datei! >%s<\n",quelldateiname); Programm_beenden(); } break; case 2: if(Z!=43 && Z!=45)// + - { fprintf(stderr,"\aKeine gueltige Datei! >%s<\n",quelldateiname); Programm_beenden(); } else { if(Z==45){gerade=false;} } break; } } // Datei einlesen und enttarnen long long int p=0; while(true) { Aktivitaets_anzeige(); load.get(Z); if(load.eof()){break;} if(p>=dg-4) { if(gerade) { save<%i< Zeichen!\n",fehlende_zeichen);} #if DEBUG else{fprintf(stderr,"In der Schluesseldatei sind alle 256 Zeichen vorhanden.\n");} #endif } // Mindestanzahl der Auswahlzeichen im Pool ermitteln int min_auswahlzeichen=10000; for(int z=0;z<256;z++) { if(pospool_groesse[z]8000){einschaetzung=1;} else if(min_auswahlzeichen<8000 && min_auswahlzeichen>6000){einschaetzung=2;} else if(min_auswahlzeichen<6000 && min_auswahlzeichen>4000){einschaetzung=3;} else if(min_auswahlzeichen<4000 && min_auswahlzeichen>2000){einschaetzung=4;} else if(min_auswahlzeichen<2000 && min_auswahlzeichen>1000){einschaetzung=5;} else if(min_auswahlzeichen<1000 && min_auswahlzeichen>800){einschaetzung=6;} else if(min_auswahlzeichen<800){einschaetzung=7;ok=false;} if(textausgabe && einschaetzung<7) { fprintf(stderr,"Der \"Wert\" der Schluesseldatei ist > %s %i < (0-6)\n",schluesselnoten[einschaetzung],einschaetzung); } return(ok); } void Schluesseldateiname_abfragen() { fprintf(stderr,"Bitte geben Sie den Dateinamen der Schluesseldatei ein:\n"); std::cin>>schluesseldateiname; } void Pools_leeren() { // Speicher des Positionspools freigeben #if DEBUG fprintf(stderr,"Freigeben des Positionspools...\n"); #endif for(int z=0;z<256;z++) { if(pospool[z]!=NULL) { free(pospool[z]); pospool[z]=NULL; } pospool_groesse[z]=0; } // Speicher des Zeichenpools freigeben #if DEBUG fprintf(stderr,"Freigeben des Zeichenpools...\n"); #endif if(pool!=NULL) { free(pool); pool=NULL; } // Speicher des Tarnpools freigeben #if DEBUG fprintf(stderr,"Freigeben des Tarnpools...\n"); #endif if(tarnpool!=NULL) { free(tarnpool); tarnpool=NULL; } } void Programm_beenden() { Pools_leeren(); if(aktiv_anzeige) { fprintf(stderr,"\r"); } #if DEBUG fprintf(stderr,"Programmende.\n"); #endif exit(0); } bool Datei_existenz_test(char* D)// (dateiname) Gibt existiert zurueck. { #if DEBUG fprintf(stderr,"TEST Datei: >%s< ",D); #endif // (man 2 stat) struct stat sb; if(stat(D,&sb)!=0) { #if DEBUG fprintf(stderr,"?? existiert nicht.\n"); #endif return(false); } if((sb.st_mode&S_IFMT)==S_IFREG) { #if DEBUG fprintf(stderr,"existiert.\n"); #endif return(true); } else { #if DEBUG fprintf(stderr,"existiert nicht.\n"); #endif return(false); } } long long int Dateigroesse(char* D)// (dateiname) Gibt groesse in Bytes zurueck. { #if DEBUG fprintf(stderr,"GROESSE Datei: >%s< ",D); #endif // (man 2 stat) struct stat sb; stat(D,&sb); #if DEBUG fprintf(stderr,"%li\n",sb.st_size); #endif return(sb.st_size); } void Datei_loeschen(char* DN)// (dateiname) { if(remove(DN)<0) { fprintf(stderr,"Konnte >%s< nicht loeschen!\n",DN); switch(errno) { case EACCES: fprintf(stderr,">Fehlende Schreibberechtigung.<\n"); break; case ENOENT: fprintf(stderr,">Diese Datei gibt es nicht.<\n"); break; case EROFS: fprintf(stderr,">Datei befindet sich auf einem schreibgeschützten Medium.<\n"); break; } } } void Aktivitaets_anzeige() { if(!aktiv_anzeige){return;} static int zeichen=0; static int zaehler=0; if(zaehler%100000==0) { fprintf(stderr," %s\r",aktiv_zeichen[zeichen]); zeichen++; if(strlen(aktiv_zeichen[zeichen])==0){zeichen=0;} } zaehler++; } void Anleitung_ausgeben() { printf("\n"); for(int z=0;z