27 Januar 2014 ~ 5 Kommentare

Caesar-Verschlüsselung in Java – ein einfaches Beispiel

caesar-verschluessung-java

“Mehr Informatikzeug!” kommentierte jüngst ein nicht weiter genannter Leser hier, der seines Zeichens zwar selbst als Informatiker tätig und natürlich “immer zweimal mehr als ich” (mindestens!) kompetent in dieser Hinsicht ist – aber vielleicht ist es ja einfach nur interessant, aus dieser Warte heraus die ersten Gehversuche anderer mitanzusehen 😉 Und auch wenn ich nicht direkt auf dem Weg zum waschechten Informatiker bin, so kommt das Coding doch im E-Commerce Studium nicht wirklich zu kurz. Daher hier ein weiteres Beispiel aus meiner aktuellen Klausurvorbereitung für Java.

Es geht um die “Caesar-Verschlüsselung”, einer sehr simplen Verschlüsselungsmethode. Oder wie Wikipedia sagt: “Als eines der einfachsten und unsichersten Verfahren dient es heute hauptsächlich dazu, Grundprinzipien der Kryptologie anschaulich darzustellen”. Also wollen wir mal: Es geht darum, die einzelnen Zeichen eines Textes um eine bestimmte Anzahl im Alphabet nach rechts zu verschieben und so einen “Geheimtext” zu erhalten. Verschiebt man z.B. den Buchstaben “a” um 3 Zeichen, so erhält man ein “d” (also 3 Zeichen weiter). Das Ganze soll rotieren, sobald man also z.B. über das “z” hinausgeht, fängt man wieder am Anfang des Alphabets an (“z” um 3 Zeichen verschoben gäbe also wieder ein “c”). Eine Aufgabe zur Caesar-Verschlüsselung fand sich auch in einer Klausur des letzten Semesters, allerdings stark vereinfacht, so dass nur die Großbuchstaben von A bis Z als Eingabe angenommen werden sollten. Da dies fast schon ein wenig langweilig ist, habe ich mich nun daran versucht, das Ganze etwas universeller auf die ganze ASCII Tabelle umzusetzen. Hier zunächst mein Code:

public class Caesar {

	public static void main (String[] args) {

		Scanner scanner = new Scanner (System.in);

		System.out.println("Zu verschlüsselnden Text eingeben:");

		String text = scanner.nextLine(); // Text eingeben

		System.out.println("Um wieviele Stellen soll 
		verschoben werden? (1-127)");

		int offset = scanner.nextInt(); 
		// Offset (Verschiebung) wählen

		if (offset >= 1 && offset <= 127) {

		char [] meinArray = text.toCharArray();
		// den Text in ein Char Array laden

		char [] meinNeuesArray = verschluesseln(offset, meinArray);
		// mit der Methode (siehe unten) "verschluesseln" ein neues 
		// Char Array mit dem verschlüsselten Text erstellen

		// verschlüsselten Text wieder ausgeben:

			System.out.println("\nSo sieht der Text verschlüsselt 
			aus:");

		for (int i = 0; i < meinNeuesArray.length; i++) {

			System.out.print(meinNeuesArray[i]);
		}
			System.out.println("\n");

		meinNeuesArray = entschluesseln(offset, meinNeuesArray);

		// entschlüsselten Text wieder ausgeben:

		System.out.println("\nUnd so wieder zurück entschlüsselt:");

			for (int i = 0; i < meinNeuesArray.length; i++) {

				System.out.print(meinNeuesArray[i]);
			}
				System.out.println("\n");

		scanner.close();
	}
		else System.out.println("Die Verschiebung muss zwischen 
		1 und 127 liegen!");
	}

	// hier die Methode zum verschlüsseln

	public static char[] verschluesseln(int offset, char[] charArray) {

		char[] cryptArray = new char[charArray.length];
		// erstmal ein leeres Char Array erstellen

		for (int i = 0; i < charArray.length; i++) {

					int verschiebung = (charArray[i] + offset)%128;
					// ursprüngliches Zeichen plus Offset modulo 128

					cryptArray[i] = (char) (verschiebung);

		}
		return cryptArray;

	}

	// hier die Methode zum entschlüsseln

	public static char[] entschluesseln(int offset, char[] charArray) {

		char[] cryptArray = new char[charArray.length];
		// erstmal ein leeres Char Array erstellen

		int verschiebung; 

		for (int i = 0; i < charArray.length; i++) {

					if (charArray[i] - offset < 0)  verschiebung = 
					charArray[i] - offset + 128;

					// nach Verschiebung kleiner 0? Wenn ja, dann
					// 128 addieren

					 else verschiebung = (charArray[i] - offset)%128;

					 // wenn nein, einfach nur modulo 128

					 cryptArray[i] = (char) (verschiebung);

		}
		return cryptArray;

	}

}

Die Ausgabe des Programmes würde beispielsweise so aussehen:

Zu verschlüsselnden Text eingeben:
Hallo, ich bin ein Text!!
Um wieviele Stellen soll verschoben werden? (1-127)
6

So sieht der Text verschlüsselt aus:
Ngrru2&oin&hot&kot&Zk~z”

Und so wieder zurück entschlüsselt:
Hallo, ich bin ein Text!!

Der Nutzer wird also aufgefordert, einen Text einzugeben und auch, um wieviele Zeichen in der ASCII Tabelle dieser verschoben werden soll. Die Eingabe wird in ein Char-Array übertragen und in einer Schleife jedes Zeichen um das gewählte Offset verschoben. Um die Rotation zu gewährleisten, wird das Ganze modulo 128 gerechnet. Erklärung hierzu: Die ASCII Zeichentabelle besteht aus 128 verschiedenen Zeichen. Möchte man nun z.B. den Buchstaben “p” (“kleines p”) um 50 Stellen nach rechts verschieben, dann hilft es zu wissen, dass “p” in der ASCII Tabelle an der Stelle 112 steht. 112 + 50 ergibt 162, ASCII hat aber, wie gerade erwähnt, nur 128 Zeichen. Wir erinnern uns vielleicht: 162 modulo 128 bedeutet “welchen Rest erhalte ich, wenn ich 162 durch 128 teile?”. Die Antwort hierauf ist natürlich 34. In diesem Fall geht es einfach nur darum, wenn ich über die 128 hinaus verschiebe, soll wieder von vorne – also bei 1 – begonnen werden. Als Informatiker würde man natürlich eher von 127 und 0 sprechen, aber so ist es erst einmal anschaulicher. Ich lande also an der Stelle 34, was in ASCII das Gänsefüßchen wäre. Beim Entschlüsseln muss man natürlich genau umgekehrt vorgehen. Hier hat man also z.B. die Stelle 34 vorliegen, muss aber wieder um 50 Stellen nach links verschieben. Da man dabei wiederum unter 0 kommt (34 – 50 = -16), zählen wir hinterher einfach wieder 128 dazu (-16 + 128 = 112, die ursprüngliche Stelle unseres “p”).

Ich selbst als bekennender Mathe-Versager konnte das Prinzip und den Code dazu hoffentlich wenigstens halbwegs verständlich erklären. Falls nicht, einfach nochmals nachfragen, ich kann aber nicht garantieren, dass ich es verständlicher machen kann 😉 Für den Programmcode kann ich allerdings auch keine Garantie übernehmen, in meinen Tests hat es funktioniert, aber was heißt das schon 😉

greg

Blogger bei kleingebloggt
Servus! Mein Name ist Michael Gregor, ich bin E-Commerce Student an der FHWS, Blogger, Webworker und schon IT-Geek seit ich 1994 meinen ersten 386er hatte :)

5 Kommentare zu “Caesar-Verschlüsselung in Java – ein einfaches Beispiel”

  1. Vince 28 Januar 2014 at 18:52 Permalink

    Schöner ausführlicher Artikel. Frei nach dem Motto, man hat es nur dann wirklich verstanden, wenn man es anderen ganz leicht erklären kann. Caesar ist immer ein schönes Beispiel.

    Kleine Anmerkungen hierzu: ASCII hat natürlich nicht 128 Bit, das wäre ja wahnsinnig. Du meinst 8 Bit, in denen man 128 (oder 256) Zeichen unterbringen kann.
    Ist dir außerdem aufgefallen, dass deine Methoden zum Ver- und Entschlüsseln praktisch bis auf ein Vorzeichen identisch sind? Mit 1-2 Änderungen an der richtigen Stelle könntest du die Methoden zusammenlegen und redundanten Code vermeiden. Sozusagen als kleiner “Optimierungstipp”. Ist ja auch logisch, weil die Verschlüsselung semantisch dasselbe ist wie die Entschlüsselung – es wird einfach in die andere Richtung verschoben.

    Als nächstes bitte die Vigenère-Chiffre, so wie sich das gehört 🙂

  2. greg 28 Januar 2014 at 19:01 Permalink

    Ach klar, wie konnte das denn passieren 😉 Hast natürlich recht, 128 Zeichen und nicht Bit. Habs korrigiert, danke.

    Ja, das mit der Optimierung stimmt auch. Daran habe ich ehrlichgesagt gar nicht gedacht zu dem Zeitpunkt, es sollte einfach nur anschaulich sein. Vielleicht liefere ich irgendwann mal die optimierte Variante nach 😉

  3. DragonHunter 5 Mai 2015 at 20:19 Permalink

    Hei,

    netter Beitrag, aber es gibt ein nicht unbedeutendes Problem:
    Bei größeren Verschiebungen werden manche Zeichen sicher vorne im Bereich der ASCII-Tabelle landen, die nicht druckbar ist. Also bei den Steuerzeichen.

    Das kann schlecht gewollt sein 😉

    • greg 5 Mai 2015 at 20:22 Permalink

      Hi,

      das stimmt, da hast du absolut recht. Für den Druck ist die Variante so nicht geeignet, rein digital funktioniert es aber wunderbar. Man könnte den verschiebbaren Bereich aber auch auf die problemlos darstellbaren Zeichen (A-Z, a-z, 0-9) beschränken.

      Gruß Greg

      • jonas 5 Dezember 2016 at 13:01 Permalink

        Hallo
        kann mir bitte jemand helfen. Würde gerne wissen wie der Code aussehen muss wenn die Verschiebung nur von A-Z möglich sein soll. Was muss im Code alles geändert werden.
        Danke
        Gruß Jonas


Hinterlasse einen Kommentar

Kommentare werden moderiert, es kann also etwas dauern, bis dein Kommenatar angezeigt wird.

RSS abonnieren
Twitter Profil