In diesem Artikel möchte ich dir gerne zeigen, wie du das Vigenère-Verschlüsselungsverfahren in Java anwenden kannst.
Inhalt
Was ist der Vigenère-Chiffre?
Bei Vigenère handelt es sich um ein einfaches Verschlüsselungsverfahren, bei dem eine Nachricht mit einem Schlüsselwort verschlüsselt wird, sodass diese nur mit dem Schlüsselwort auf Anhieb entschlüsselt werden kann.
Vorgehen
Bei dem Algorithmus wird dann in einer Tabelle, in der jeweils die Buchstaben von A bis Z in jeder Zeile stehen, jeweils um einen Buchstaben mehr versetzt, nach der entsprechenden Spalte für den zu verschlüsselnden Buchstaben gesucht. In dieser Spalte wird dann der zum in der linken Spalte stehenden Schlüsselbuchstaben zugehörige Buchstabe abgelesen und in die verschlüsselte Nachricht eingefügt. Zum Entschlüsseln wird dieses Verfahren genau rückwärts wieder ausgeführt.
Wie sicher ist Vigenère?
Natürlich solltest du mit dem Vigenère-Chiffre nicht deine Passwörter oder sonstige Daten verschlüsseln. Es handelt sich dabei um ein altes/traditionelles Verfahren, welches mit sehr wenig Aufwand durch pures Ausprobieren (sogenanntes Brute-Force) geknackt werden kann.
Wie nutze ich Vigenère in Java? (Quellcode)
Mit dem folgenden Quellcode kannst du eine einfache Klasse mit den Methoden encodiere und decodiere nutzen. Im Konstruktor befindet sich direkt auch schon ein Testaufruf dieser Methoden, um den Algorithmus gleich testen zu können. Mit der Methode bruteForce lassen sich alle möglichen Schlüssel und entschlüsselten Nachrichten ermitteln, um eine Nachricht ohne den dazugehörigen Schlüssel zu entschlüsseln.
Der Quellcode ist ausführlich kommentiert. Solltest du noch Fragen dazu haben, kannst du natürlich gerne einen Kommentar hinterlassen.
/**
* Klasse zur Anwendung des Vigenère-Chiffres
* Achtung: die Schlüssel und Nachrichten dürfen jeweils nur aus Buchstaben bestehen, keine Umlaute oder Sonderzeichen. Die Groß- und Kleinschreibung ist dabei egal.
* @author Bloggingwelt.de
* © Copyright 2021 Bloggingwelt.de
*/
public class Vigenere {
//Erstellung der Buchstaben-Arrays
public char[] buchstaben = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'};
public char[][] buchstabentabelle = new char[buchstaben.length][buchstaben.length];
public static void main(String[] args) {
new Vigenere();
}
public Vigenere() {
//Befüllen der Buchstabentabelle (zweidimensionales Array)
buchstabentabelle = erstelleBuchstabentabelle();
//Testaufrufe
System.out.println(encodiere("HAL", "ich habe hunger"));
System.out.println(decodiere("HAL", encodiere("HAL", "ich habe hunger")));
System.out.println(bruteForce(encodiere("HAL", "ich habe hunger"), 3, true));
}
/**
* Klasse für eine Nachricht
*/
private class Nachricht {
private String nachricht;
private String schluessel;
public Nachricht(String pNachricht, String pSchluessel) {
this.nachricht = pNachricht;
this.schluessel = pSchluessel;
}
public Nachricht(String pSchluessel) {
this.nachricht = "";
this.schluessel = pSchluessel;
}
public String getNachricht() {
return this.nachricht;
}
public void setNachricht(String pNachricht) {
this.nachricht = pNachricht;
}
public String getSchluessel() {
return this.schluessel;
}
}
/**
* @param nachricht die Nachricht, die entschlüsselt werden soll
* @param laengeSchluessel die Länge des Schlüssels, bis zu der ausprobiert werden soll
* @param legt fest, ob die Liste aller Nachrichten und Schlüssel in der Konsole ausgegeben werden soll oder nicht
* @return entschlüsselte Nachrichten in einer Liste
*/
public List<Nachricht> bruteForce(String nachricht, int laengeSchluessel, boolean listeAusgeben) {
List<Nachricht> loesungen = moeglicheSchluessel(laengeSchluessel);
if(listeAusgeben == true) {
loesungen.toFirst();
while(loesungen.hasAccess()) {
loesungen.getContent().setNachricht(decodiere(loesungen.getContent().getSchluessel(), nachricht));
System.out.println("Nachricht: " + loesungen.getContent().getNachricht() + ", Schlüssel: " + loesungen.getContent().getSchluessel());
loesungen.next();
}
}
return loesungen;
}
/**
* Nachricht mit der Übergabe eines Schlüssels und der Nachricht, die verschlüsselt zurückgegeben werden soll
* @param String schluessel Schlüssel zum Codieren
* @param String nachricht Nachricht, die codiert werden soll
* @return verschlüsselte Nachricht
*/
public String encodiere(String schluessel, String nachricht) {
//Schlüssel und Nachricht in Char-Array verwandeln, nachdem alle Leerzeichen entfernt wurden und es in Großbuchstaben umgewandelt wurde
char[] schluesselArray = schluessel.replaceAll("\\s+","").toUpperCase().toCharArray();
char[] nachrichtenArray = nachricht.replaceAll("\\s+","").toUpperCase().toCharArray();
String verschluesselteNachricht = "";
//Durchlaufen der kompletten Nachricht
for(int i = 0; i < nachrichtenArray.length; i++) {
//Teilung der Nachricht in 5er-Blöcke
if(i != 0 && i % 5 == 0) {
verschluesselteNachricht += " ";
}
int j = 0;
//"Verlängerung" des Schlüssels auf die Nachrichtenlänge
if(i >= schluesselArray.length){
j = i - (i / schluesselArray.length) * schluesselArray.length;
} else {
j = i;
}
//Heraussuchen des entsprechenden Buchstabens aus der Tabelle und Anfügen an die Nachricht
verschluesselteNachricht += buchstabentabelle[buchstabenPosition(nachrichtenArray[i])][buchstabenPosition(schluesselArray[j])];
}
//Rückgabe der verschlüsselten Nachricht
return verschluesselteNachricht;
}
/**
* Nachricht mit der Übergabe eines Schlüssels und der entschlüsselten Nachricht als Rückgabe
* @param schluessel Schlüssel zum Decodieren
* @param nachricht Nachricht, die decodiert werden soll
* @return entschlüsselte Nachricht
*/
public String decodiere(String schluessel, String nachricht) {
//Schlüssel und Nachricht in Char-Array verwandeln, nachdem alle Leerzeichen entfernt wurden und es in Großbuchstaben umgewandelt wurde
char[] schluesselArray = schluessel.replaceAll("\\s+","").toUpperCase().toCharArray();
char[] nachrichtenArray = nachricht.replaceAll("\\s+","").toUpperCase().toCharArray();
String entschluesselteNachricht = "";
//Durchlaufen der kompletten Nachricht
for(int i = 0; i < nachrichtenArray.length; i++) {
//Teilung der Nachricht in 5er-Blöcke
if(i != 0 && i % 5 == 0) {
entschluesselteNachricht += " ";
}
int j = 0;
//"Verlängerung" des Schlüssels auf die Nachrichtenlänge
if(i >= schluesselArray.length){
j = i - (i / schluesselArray.length) * schluesselArray.length;
} else {
j = i;
}
//Suchen nach der Buchstabenposition in der entsprechenden Spalte des Lösungswortes
int buchstabenPositionSpalte = -1;
for(int p = 0; p < buchstaben.length; p++) {
if(buchstabentabelle[buchstabenPosition(schluesselArray[j])][p] == nachrichtenArray[i]){
buchstabenPositionSpalte = p;
}
}
//Heraussuchen des entsprechenden Buchstabens aus der ganz linken Spalte der Tabelle und Anfügen an die Nachricht
entschluesselteNachricht += buchstabentabelle[0][buchstabenPositionSpalte];
}
//Rückgabe der entschlüsselten Nachricht
return entschluesselteNachricht;
}
/**
* Hilfsmethode zur Bestimmung einer Buchstabenposition im Alphabet
* @param buchstabe der zu suchende Buchstabe
* @return gesuchte Position oder -1, wenn er nicht gefunden wurde
*/
public int buchstabenPosition(char buchstabe) {
for(int i = 0; i < buchstaben.length; i++) {
if(buchstaben[i] == buchstabe) {
return i;
}
}
return -1;
}
/**
* Hilfsmethode zur Erstellung aller möglichen Schlüsseln einer Länge
* @param laenge des zu suchenden Schlüssels
* @return Liste aller möglicher Schlüssel und Nachrichten der definierten Länge
*/
public List<Nachricht> moeglicheSchluessel(int laenge) {
List<Nachricht> schluessel = new List<Nachricht>();
List<Nachricht> schluesselTemp = new List<Nachricht>();
schluessel.append(new Nachricht(""));
for(int j = 0; j < laenge; j++) {
schluessel.toFirst();
while(schluessel.hasAccess()) {
for(int i = 0; i < buchstaben.length; i++) {
schluesselTemp.append(new Nachricht(schluessel.getContent().getSchluessel() + Character.toString(buchstaben[i])));
}
schluessel.next();
}
schluessel.concat(schluesselTemp);
schluesselTemp.toFirst();
while(schluesselTemp.hasAccess()) {
schluesselTemp.remove();
schluesselTemp.next();
}
}
schluessel.toFirst();
schluessel.remove();
return schluessel;
}
/**
* Hilfsmethode zur verschobenen Befüllung der Buchstabentabelle
* @return gefüllte Buchstabentabelle
*/
public char[][] erstelleBuchstabentabelle() {
char[][] tabelle = new char[buchstaben.length][buchstaben.length];;
int verschiebung = 0;
for(int i = 0; i < buchstaben.length; i++) {
for(int j = 0; j < 26; j++) {
verschiebung = j+i;
if(verschiebung >= buchstaben.length) {
verschiebung = verschiebung - buchstaben.length;
}
tabelle[i][j] = buchstaben[verschiebung];
}
}
return tabelle;
}
}
Code-Sprache: Java (java)
Viel Spaß beim Ver- und Entschlüsseln ;-)!