Vigenere Ver- Entschlüsselung in C



  • Bau doch on case ein. Hier zum schmökern ein alter code von mir, ist zwar mit goto aber zumgucken reicht es.

    /* enig_a.c ist ein einfaches Programm zum kodieren und dekodieren von Dateien
       Dieses Beispiel dient zur Demonstration von Schreib- und Lesezugriffen
    */
    
    #include <stdio.h>  //getch
    #include <stdlib.h> /* für malloc */
    #include <fcntl.h>  // wegen open
    #include "direct.h"  /* Symbolische Konstanten für open */
    #include <errno.h>  // wegen errno
    #include <unistd.h> // wegen close, lseek, getch
    #include <termios.h> // getch
    
    /* Ersatz für das im DOS übliche getch, funzt auch auf der Linux-Konsole */
    int getch(){
        struct termios oldt, newt;
        int ch;
        tcgetattr( STDIN_FILENO, &oldt );
        newt = oldt;
        newt.c_lflag &= ~( ICANON | ECHO );
        tcsetattr( STDIN_FILENO, TCSANOW, &newt );
        ch = getchar();
        tcsetattr( STDIN_FILENO, TCSANOW, &oldt );
        return ch;
    }
    // Zeigt das Schlüsselwort an
    void SLUAN(unsigned char schluessel[], int *codelaenge)
    {
    int sleia;
     printf("\nSchüsselwort:\n");
     for (sleia = 0; sleia <= 99; sleia++)
      {// Das Zeichen für Stringende ist Null
      printf("%c", schluessel[sleia]);
      if (schluessel[sleia] == 0)
       {
        *codelaenge = sleia;
        goto finito;
       }
      }
    finito: printf("\n");
    }
    /* Bestimmt die Länge einer Datei, diese wird als long zurückgegeben */
    long getdatlen(char datname[])
    {
      int fh;
      long rewer = 0L;
      if( (fh = open( datname, _O_RDONLY | _O_BINARY ) ) == -1 )
       {
        rewer = errno;
        goto finito;
       }
      rewer = lseek(fh, 0, SEEK_END);
      close( fh );
    
    finito: return(rewer);
    }
    
    // Löscht den Tastaturspeicher, um fehlerhafte Eingaben zu vermeiden
    void clpuf(void)
     {
     while (getchar() != '\n')
        ;
     }
    
    void getfilename(char *text, char dateiname[])
    {
     printf("%s", text);
     scanf("%s", dateiname);
    }
    
    int main(void)
    {
    int codze, codelaenge, wohin = 0, zeichen, kodierart = 0;
    char queldat[70], zieldat[70];
    unsigned char schluessel[100], dummy;
    long slei, groesse;
    
    FILE *fziel, *fquelle;
    
    printf("\nCodierungsprogramm Wiscod V0.1");
    
    hauptmenue:
       printf("\n\nSchlüssellänge maximal 90 Zeichen!");
       printf("\nSchlüssel eingeben............1");
       printf("\nSchlüssel anzeigen............2");
       printf("\ncodieren......................3");
       printf("\ndecodieren....................4");
       printf("\nEnde..........................0");
       printf("\n\nIhre Wahl: ");
    
    wouhi: scanf("%d", &wohin);
           clpuf();
        if (wohin == 1) goto schluessel;
        if (wohin == 2) goto schlissl;
        if (wohin == 3) { kodierart = 0; goto danafa; } // 0 = kodieren
        if (wohin == 4) { kodierart = 1; goto danafa; } // 1 = dekodieren
        if (wohin == 0) goto finito;
       goto wouhi;
    
    dateilesen:
         printf("\n\nDatei öffnen..1     Zurück..0");
         printf("\n\nIhre Wahl: ");
    
         scanf("%d", &wohin);
         if (wohin == 0) goto hauptmenue;
         if (wohin == 1) goto danafa;
       goto dateilesen;
    
    danafa: getfilename("\nName der Quelldatei: ", queldat);
            getfilename("\nName der Zieldatei.: ", zieldat);
        //Zuerst Länge der Quelldatei bestimmen
         groesse = 0;
         printf("\nDateigröße wird ermittelt.");
         groesse = getdatlen(queldat);
         if (groesse == -1)
          {
           printf("Fehler beim Öffnen der Quelldatei.");
           goto dateilesen;
          }
         printf("Die Dateigröße der Quelldatei beträgt: %ld Zeichen", groesse);
         // Lese Quelldatei im Binärnmodus (b) ein,
         fquelle = fopen(queldat, "rb");
         if (fquelle == NULL)
          {
           printf("\nEine Öffnung der Quelldatei ist nicht möglich.");
           goto dateilesen;
          }
         printf("\nDie Quelldatei wurde geöffnet.\n");
    
         fziel = fopen(zieldat, "wb");
         if (fziel == NULL)
          {
           printf("\nEine Erstellung der Zieldatei ist nicht möglich.");
           goto dateilesen;
          }
         printf("\nDie Ziel wurde Erstellt.\n");
    
    /*Kodieren oder dekodieren der Datei n bei 0 ist kodieren angesagt */
         codze = 0;
         if (kodierart == 0) printf("\nKodieren von %ld Zeichen",   groesse);
          else               printf("\nDekodieren von %ld Zeichen", groesse);
         for (slei = 0; slei < groesse; slei++)
          {
           zeichen = fgetc(fquelle); /* slei=Zeichenenmenge beim einlesen */
           if (zeichen == EOF) break;
           // naunco = "Nachricht uncodiert"
           if (kodierart == 0)
            {
             dummy = (unsigned char)zeichen + schluessel[codze];
             if (dummy > 255) dummy -= 255;
            }
           if (kodierart == 1)
            {
             dummy = (unsigned char)zeichen - schluessel[codze];
             if (dummy < 0)   dummy += 255;
            }
           fputc(dummy, fziel);
           codze++;
           if (codze >= codelaenge - 1)
            codze = 0;
          }
      if (kodierart == 0) printf("\nDatei wurde kodiert");
       else               printf("\nDatei wurde dekodiert");
    
         fclose(fquelle);
         fclose(fziel);
         printf("\nDie Dateien wurden geschlossen.");
         printf("\nEs wurden %ld Zeichen bearbeitet.", slei);
      goto hauptmenue;
    
    /*Schlüsselwort eingeben */
    schluessel:
        for (slei = 0; slei <= 99; slei++)
         schluessel[slei] = 0;
        printf("\nBitte Schlüsselwort eingeben: ");
        scanf("%[^\n]", schluessel); /* alle Zeichen, auch Leerzeichen bis auf Enter einlesen */
        printf("\nIhre Eingabe:\n");
        SLUAN(schluessel, &codelaenge); // Schlüsselwort anzeigen
        printf("\nDas Schlüsselwort ist %d Zeichen lang", codelaenge);
      goto hauptmenue;
    
    schlissl:
         printf("\nSchlüsselwort anzeigen\n");
         SLUAN(schluessel, &codelaenge);
      goto hauptmenue;
    
    finito: printf("\nProgrammende");
    return(0);
    }
    

    Geschrieben habe ich damals das ganze auf codeblocks 13.12. Es ist ein
    einfaches Beispiel der Substitution, quasi Ersatzalphabet. Da ich es
    mit der englischen Sprache nicht so habe sind die Bezeichner etwas
    schräg geraten. Rein theoretisch könnte man zuerst die Dateilänge der
    zu kodierenden Datei bestimmen, dann eine Datei mit Zufallszahlen
    im Zahlenbereich 0 bis 255 anlegen, deren Anzahl der Byts, also der
    Zufallszahlen genau so lange ist, wie die zu verschlüsselnde Datei
    selbst. Danach müßte man beide Dateien gleichzeitig öffnen und die
    Kodierung durchführen. Das Ergebnis würde dann logischerweise in einer
    anderen Datei abgspeichert. Der Urcode wurde von mir 1994 schon auf
    Quick-c 2.5 geschrieben. Angefangen habe ich mit einem
    Symantec C 6.11 Shareware-compiler, die Schnupperversion von
    Symantec C 7.0. Nach meinem Umstieg auf Linux wollte ich die Codes
    aller meiner Dateien auf Codedeblocks portieren. Aber was da an 20 Jahren
    Hobby-programmieren zusammengekommen ist, da müßte ich 200 Jahre alt werden
    um das zu schaffen. Man wird eben älter!



  • Wen interessiert dieser Müll?
    Alles Schrott.
    Liebe Kinder, nicht nachmachen.



  • Wenn schon Kritik, dann konstruktive und sachliche Kritik.

    Wenn du in einer Firma arbeitest du hast ein brainstorming,
    Kaizen (PDCA), Fishbon-Ishikawa, FMEA oder andere QM-Meetings
    kannst du auch keine Killerphrasen verwenden, es sei denn, du
    willst deinen Job gleich wieder an den Nagel hängen.



  • Du hast keine Ahnung von C, das hast du mehrfach bewiesen.
    Dein Code ist vollkommener Schrott.
    Wenn du eine Frage zu Standard C hast, stelle sie hier in qualifizierter Form.
    Und unterlasse alle deine "...gut gemeint..." Ratschläge, die interessieren niemanden, sind falsch und behindern die Problemlösung durch die qualifizierten Antworter hier im Forum.



  • @rustyoldguy

    Sorry, das ist Schrott.
    In dem Stil hat man auf dem C64 in BASIC programmiert.

    Wenn du den Code, nach 20 Jahren, immer noch gut findest, hast du nichts dazu gelernt.

    Etwas detailierte Kritik:
    - unnötige goto

    • scanf mit %s oder %[ ohne length-Modifier. Da kannst du auch gets nehmen.
      - unnötige goto
      - viel zu kompliziert
      - unnötige goto
      - nichtssagende oder irreführende Funktionsnamen
      - unnötige goto
      - unnötige POSIX-Funktionen
      - der Code geht an der gefragten Aufgabe weit vorbei

    Konstruiktive Kritik:
    Schmeiß den Code weg und lösch den hier.



  • Ach Wutz lass doch deine lieben, netten, konstruktiven, nutzlosen, völlig unbrauchbare Kommentare bei dir zu Hause im Bett. Dich braucht keiner wenn du nur solchen (Zitat) Müll oder Schrott schreibst, vielen Dank. 🙂

    Du hast keine Ahnung von C, das hast du mehrfach bewiesen.
    Dein Code ist vollkommener Schrott.
    Wenn du eine Frage zu Standard C hast, stelle sie hier in qualifizierter Form.
    Und unterlasse alle deine "...gut gemeint..." Ratschläge, die interessieren niemanden, sind falsch und behindern die Problemlösung durch die qualifizierten Antworter hier im Forum.

    Ach ja freundlic wie eh und je. <333
    Ich glaube ich habe 1 unter 10 deiner Antworten (oh entschuldige, wir sagen lieber hochqualifizierte Kommentare) gesehen, die tatsächlich mal etwas zum Inhalt beigetragen haben :OO



  • TocToc schrieb:

    Ach Wutz lass doch deine lieben, netten, konstruktiven, nutzlosen, völlig unbrauchbare Kommentare bei dir zu Hause im Bett. Dich braucht keiner wenn du nur solchen (Zitat) Müll oder Schrott schreibst, vielen Dank. 🙂

    Wutz ist sehr oft hilfreich.
    Auch daß er rustyoldguys Ergüsse aus Sicht eines Fachmanns rezensiert, ist prima. 👍

    TocToc schrieb:

    Ich glaube ich habe 1 unter 10 deiner Antworten (oh entschuldige, wir sagen lieber hochqualifizierte Kommentare) gesehen, die tatsächlich mal etwas zum Inhalt beigetragen haben :OO

    Diese Quote sehe ich bei Dir. Also kann mich jetzt an keinen Code von Dir erinnern, nur an das fachfremde Gemecker wie schrechlich gemein die Großen sind.



  • Sweet.
    Weiß nicht ob du das bis jetzt bemerkt hast, bin Anfänger. Nur mal so nebenbei..

    Wutz ist sehr oft hilfreich.

    Ich geh mal kurz lachen. Später vllt..

    Auch daß er rustyoldguys Ergüsse aus Sicht eines Fachmanns rezensiert, ist prima. 👍

    Das ist aber schon sehr schöngeredet..



  • Nur interessiert das niemanden, ob oder was du zu meinen Antworten beizutragen hast; ich kann verstehen wenn du meine Beiträge nicht verstehst, ein Mindestmaß an Auffassungsgabe und Intellekt sind dafür nämlich notwendig.
    Deine eigenen "Beiträge", in denen du nur dein irgendwo aufgeschnapptes Halbwissen ohne Sinn und Verstand nachplapperst sind ebenso falsch und dilettantisch wie die von dem oben zitierten Herrn, und behindern ebenso nur eine qualifizierte Problemlösung.
    Trolle dich dahin wo du hergekommen bist und halt die Klappe, wenn sich Erwachsene unterhalten.



  • TocToc schrieb:

    Weiß nicht ob du das bis jetzt bemerkt hast, bin Anfänger. Nur mal so nebenbei..

    Mensch, dann sei doch froh, daß es hier Leute wie Wutz gibt! 😃
    Oder willste aus Wolf-Büchern und rustyoldguys Programmen lernen?



  • #include <stdio.h>
    #include <string.h>
    #include <ctype.h>
    #include <conio.h>
    
    void eingabepuffer_leeren();
    void vigenere(char *text, char *schluessel);
    void einlesen(char *text, int lenText, char *schluessel, int lenSchluessel);
    
    int main()
    {
    	char auswahl;
    
    	char text[100];
    	char schluessel[100];
    
    	do
    	{
    		einlesen(text, sizeof(text), schluessel, sizeof(schluessel));
    
    		printf("\n### Auswahl ###\n\n");
    
    		printf("V) Verschluesseln\n");
    		printf("E) Entschluessen\n");
    		printf("B) Beenden\n");
    
    		printf("\nAuswahl: ");
    		scanf("%c", &auswahl);
    		eingabepuffer_leeren();
    
    		switch (auswahl)
    		{
    				// Auswahl 1 bzw. 2:
    				// Macht in diesem Fall keinen Unterschied, da Verschlüsselung und Entschlüsselung analog sind bzw. sein sollten...
    			case 'v':
    			case 'V':
    				vigenere(text, schluessel);
    				break;
    
    			case 'b':
    			case 'B':
    				printf("Programm wird beendet.\n");
    				break;
    
    			default:
    				printf("Fehlerhafte Eingabe!\n");
    		}
    	} while (auswahl != 'b' && auswahl != 'B');
    
    	return 0;
    }
    
    void eingabepuffer_leeren()
    {
    	char c;
    
    	while ((c= getchar()) != '\n' && c != EOF)
    		 /* verwerfen */ ;
    }
    
    void einlesen(char *text, int lenText, char *schluessel, int lenSchluessel)
    {
    	printf("### Text/Schluessel ###\n");
    
    	printf("Text: ");
    	fgets(text, lenText, stdin);
    
    	printf("Schluessel: ");
    	fgets(schluessel, lenSchluessel, stdin);
    }
    
    void vigenere(char *text, char *schluessel)
    {
    	printf("Geheimtext: ");
    
    	printf("<noch zu implementieren>\n");
    
    	printf("\n");
    }
    


  • Es fehlt natürlich das case für die Entschlüsselung, denn da es ohnehin unnötig ist, hab ich es ausversehen wegoptimiert. 😃



  • Ver- und entschlüsseln sind nicht gleich.
    (könnte es, wenn der Schlüssel aus 'N' besteht)

    Der Prototyp sollte (IMHO) so aussehen:

    void vigenere(char *geheimtext, size_t groesse_von_geheimtext, char *text, char *schluessel);
    

    fgets lässt das '\n' im Text. Das könnte Probleme geben.

    eingabepuffer_leeren() dunktioniert nur richtig, wenn c ein int ist.
    Im übrigen ist der NAme der Funktion irreführend.

    Ein

    auswahl = toupper(auswahl)
    

    nach der Eingabe macht den Code auch lesbarer.

    Deine Menüführung macht den User wütend.

    Tipp:
    Ein Leerzeichen vor dem %c bei scanf wirkt manchmal Wunder (nicht unbedingt hier, aber es schadet nicht):

    scanf(" %c", &auswahl);
    

Anmelden zum Antworten