More info in Wikipedia at
http://en.wikipedia....%C3%A8re_cipher
Two programs:
Vigenere.java which is a console version
VigenereGui.java which calls the first one an offer a GUI interface that allows to change the key dynamically.
Vigenere.java
import java.util.Scanner;
/**
* The Ceasar code is really easy to decript. There are only 26 different keys
* and frequency studies can decipher a coded message quite rapidly.
* In English, as example, the letter "e" is the most commonly used letter followed
* by 'a'. As soon as the encrypted 'e' or 'a' is identified it is quite easy to
* apply the same shift to the other letters of the message. But if the message is very short
* and screw up the normal frequency of letters like in: "Zebras run in zig zags from
* Zambia to Zanzibar" :-)
*
* If you use the GUI I wrote for the Ceasar code, it is quite easy to enter the coded
* message and then try the 26 possible shifts by cliking on the different JRadioButtons
*
* Derived from the Ceasar code is the Vigenere's square. His code was developped in the
* XVII century. Actualy the algorithm has been described in a book published
* by Giovan Battista Bellaso in 1563 but is now well known as the Vigener's cypher.
* This cypher was reputated 100% safe until the XIX century.
*
* The whole idea is to use like the Ceasar code a shift of letter in the Alphabet but to change
* the number of shifted letter for each letter of the message. This would completly, at least they thought
* at that time, the frequency analysis.
*
* So to cypher we use the so called Vigenere's square
*
* A - ABCDEFGHIJKLMNOPQRSTUVWXYZ
* B - BCDEFGHIJKLMNOPQRSTUVWXYZA
* C - CDEFGHIJKLMNOPQRSTUVWXYZAB
* D - DEFGHIJKLMNOPQRSTUVWXYZABC
* E - EFGHIJKLMNOPQRSTUVWXYZABCD
* ...
* H - GHIJKLMNOPQRSTUVWXYZABCDED
* ...
* Y - YZABCDEFGHIJKLMNOPQRSTUVWX
* Z - ZABCDEFGHIJKLMNOPQRSTUVWXY
*
* In the Ceasar code, the key is the number of letters we shift the original letter to produce the
* coded message.
* In the Vigenere's cypher the key is a word that is repeat over the message to encrypt.
* Lets assume the key is "CHARLIE" and the message is "tutorials at dic"
*
* We write the the key over the message
*
* CHARLIECHARLIECH
* tutorials at dic
*
* Now to encode the message we use:
* - the shiftet alphabet at row C for the first letter so T becomes V
* - the shifted alphabet ar row H for the second letter so U becomes A
* - the shifted alphabet at row A for the third letter so T stays T
* and so on
*
* P.S.
* If the key is A or AA or AAA or any multiple of A there is no encryption performed
* Evidently the longuest the Key the less repetitions (cycles) you will have
*/
public class Vigenere {
// the key used by this Vigenere object
private String key;
/**
* contructor that receives the key as parameter
*/
public Vigenere(String key) {
// call the standard method to set up the key
setKey(key);
}
/**
* The method to set up/change the key
*/
public void setKey(String key) {
// empty key ignore it
if(key == null) {
this.key = "";
return;
}
// keep only the letters in the key and keep them uppercase
char[] digit = key.toUpperCase().toCharArray();
// use a stringBuilder to create the the keyString
StringBuilder sb = new StringBuilder(digit.length);
for(char c : digit) {
if(c >= 'A' && c <= 'Z')
sb.append(c);
}
// save our key
this.key = sb.toString();
}
/**
* Encode a message according to the key already registered
*/
public String encode(String clear) {
// ignore if null
if(clear == null)
return "";
// ignore if key length == 0
if(key.length() == 0)
return clear.toUpperCase();
// by convention in the cryptology world all original messages are in lower case
// and coded messages in uppercase
// so let us put the original message in lower cases
// convert the original message into an array of char
// into which converted character will be put later
char[] digit = clear.toLowerCase().toCharArray();
// build a string with the repeated key at least the size of our message
String longKey = key;
while(longKey.length() < clear.length())
longKey += key;
// pass through all input digits to convert them
for(int i = 0; i < digit.length; i++) {
// if they are not between 'a' and 'z' just ignore them (message has been translated to lowercase)
if(digit[i] < 'a' || digit[i] > 'z')
continue;
// find out by how much we shift (like in a Ceasar code)
char offset = longKey.charAt(i);
// subtract 'A' for it for the number of shift
int nbShift = offset - 'A';
// convert the digit to uppercase (as we mentionned this is a standard cryptographic convention)
digit[i] = Character.toUpperCase(digit[i]);
// applied the shift to it
digit[i] += nbShift;
// wrap around if over 'Z'
if(digit[i] > 'Z') {
digit[i] -= 'Z';
digit[i] += ('A' - 1);
}
}
return new String(digit);
}
/**
* this method returns the decrypted String from the String received as parameter
* according to the current key
*/
public String decode(String coded) {
// ignore if null
if(coded == null)
return "";
// ignore if key length is 0
if(key.length() == 0)
return coded.toLowerCase();
// by convention in the cryptology world all original messages are in lowercode
// and coded messages in uppercase
// so let us put the original message in upper cases
// convert the original message into an array of char
char[] digit = coded.toUpperCase().toCharArray();
// build a string with the repeated key at least the size of our message
String longKey = key;
while(longKey.length() < coded.length())
longKey += key;
// pass through all input digits to convert them
for(int i = 0; i < digit.length; i++) {
// if they are not between 'A' and 'Z' just ignore them (message has been translated to uppercase)
if(digit[i] < 'A' || digit[i] > 'Z')
continue;
// find out by how much we shift (like in a Ceasar code)
char offset = longKey.charAt(i);
// subtract 'A' for it for the number of shift
int nbShift = offset - 'A';
// convert the digit to lowerrcase (as we mentionned this is a standard cryptographic convention)
digit[i] = Character.toLowerCase(digit[i]);
// applied the shift to it
digit[i] -= nbShift;
// wrap around if before 'A'
if(digit[i] < 'a') {
digit[i] += 'z';
digit[i] -= ('a' - 1);
}
}
return new String(digit);
}
/**
* To test our class
*/
public static void main(String[] args) {
//------------------------------------------------------------------
// Automatic tests
//------------------------------------------------------------------
// test with the whole alphabet
Vigenere vigenere = new Vigenere("DreamInCode");
// code the whole alpahabet
String alphabet = "abcdefghijklmnopqrstuvwxyz";
// code it
String coded = vigenere.encode(alphabet);
System.out.println("Coded alphabet is: " + coded);
// decode it back
String clear = vigenere.decode(coded);
System.out.print(" Alphabet back ?: " + clear);
// print if we succeed
if(alphabet.equals(clear))
System.out.println(" Seems to work :-)");
else
System.out.println(" Oups !!! Bug ...");
System.out.println();
// now test that frequency will be defeated
// (we should find the key "Another Key" under the aaaaaaaaaa
// with the Ceasar encoding all e would have the same encoding)
String freq = "eeeeeeeeeeeeeeeeaaaaaaaaaaaaaaaazzzzzzzzzzzzzzz";
// use another key
vigenere.setKey("AnotherKey");
// print out initial String
System.out.println("Frequency test");
System.out.println("Frequency String: " + freq);
// encode it
coded = vigenere.encode(freq);
// print the coded string and its translation back
System.out.println(" as coded String: " + coded);
System.out.println(" end back ? : " + vigenere.decode(coded));
System.out.println();
//-------------------------------------------------------------------
// End of automatic tests
// you can remove all the automatic tests code in production
//-------------------------------------------------------------------
// now test from user input
// build a Scanner to read from the console
Scanner scan = new Scanner(System.in);
System.out.print("Enter the key: ");
// read the key and create a Vigenere object with it
String key = scan.nextLine();
Vigenere userVigenere = new Vigenere(key);
// input message from user
System.out.print("Enter message: ");
String message = scan.nextLine();
System.out.println(" Original: " + message);
// code it and decode it back
coded = userVigenere.encode(message);
System.out.println("Encoded message is: " + coded);
System.out.println("translated back ? : " + userVigenere.decode(coded));
}
}
And the Gui version VigenereGui.java
import java.awt.*;
import javax.swing.*;
import javax.swing.event.*;
/**
* A GUI that use the Vigenere class to encode/decode messages
*/
public class VigenereGui extends JFrame {
private static final long serialVersionUID = 1L;
// the Vigenere class to encode/decode
private Vigenere vigenere;
// the key to use
private JTextField keyText;
// The message to encode
private JTextField clearTextIn;
private JLabel encodedTextOut;
// the message to decode
private JTextField codedTextIn;
private JLabel decodedTextOut;
/**
* Constructor
*/
VigenereGui() {
super("Vigenere encoding/decoding");
// we will use a BorderLayout to store our GUI component
setLayout(new BorderLayout());
// to store the key, coded text input output fields
JPanel textPanel = new JPanel(new GridLayout(15, 1));
// the Key
textPanel.add(new JLabel());
textPanel.add(createCenteredLabel("Enter the Key here:"));
textPanel.add(createCenteredLabel("(without a key no transaltion would happen)"));
keyText = new JTextField(50);
// with a documentListener to be informed when the Key changes
keyText.getDocument().addDocumentListener(new KeyListener());
textPanel.add(keyText);
// and a Gap
textPanel.add(new JLabel());
// text to encode header
textPanel.add(createCenteredLabel("Enter text to encode here"));
// the JTextField to enter the text to encode
clearTextIn = new JTextField(50);
// with a documentListener to be informed when the text changes
clearTextIn.getDocument().addDocumentListener(new ClearListener());
textPanel.add(clearTextIn);
// the header for the coded text
textPanel.add(createCenteredLabel("Coded Text"));
// and the JLabel to display it
encodedTextOut = createOutputLabel();
textPanel.add(encodedTextOut);
// same thing for the string to decode
textPanel.add(new JLabel());
textPanel.add(createCenteredLabel("Enter text to decode here"));
// the JTextField to enter the coded text with its listener
codedTextIn = new JTextField(50);
codedTextIn.getDocument().addDocumentListener(new CodedListener());
textPanel.add(codedTextIn);
textPanel.add(createCenteredLabel("Decoded text"));
decodedTextOut = createOutputLabel();
textPanel.add(decodedTextOut);
textPanel.add(new JLabel());
// add the Panel to the frame
add(textPanel, BorderLayout.CENTER);
// init the key to ""
vigenere = new Vigenere("");
// standard operation to show the JFrame
this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
setLocation(30, 30);
pack();
setVisible(true);
}
/**
* A method to create a JLabel with foreground color Blue and with text centered
*/
private JLabel createCenteredLabel(String text) {
JLabel label = new JLabel(text);
label.setHorizontalAlignment(SwingConstants.CENTER);
label.setForeground(Color.BLUE);
return label;
}
/**
* A method to create the output labels with White background and a border
*/
private JLabel createOutputLabel() {
JLabel label = new JLabel();
label.setOpaque(true);
label.setBackground(Color.WHITE);
label.setBorder(BorderFactory.createLineBorder(Color.RED));
return label;
}
/**
* To update the key string
*/
private void updateKeyString() {
vigenere.setKey(keyText.getText());
// and update the coded/decoded Strings
updateCodedString();
updateDecodedString();
}
/**
* To update coded string
*/
private void updateCodedString() {
// get the text from the JTextField
String line = clearTextIn.getText();
// set the label containing the text out with the new conversion
encodedTextOut.setText(vigenere.encode(line));
}
/**
* To update decoded string
*/
private void updateDecodedString() {
// get the text from the JTextField
String line = codedTextIn.getText();
// set the label containing the decoded string
decodedTextOut.setText(vigenere.decode(line));
}
/**
* To start the GUI
*/
public static void main(String[] args) {
new VigenereGui();
}
/**
* A listener to be informed whenever the JTextField for the coded string is changed
*/
class CodedListener implements DocumentListener {
@Override
public void changedUpdate(DocumentEvent arg0) {
updateDecodedString();
}
@Override
public void insertUpdate(DocumentEvent arg0) {
updateDecodedString();
}
@Override
public void removeUpdate(DocumentEvent arg0) {
updateDecodedString();
}
}
/**
* A listener to be informed whenever the JTextField of the clear text is changed
*/
class ClearListener implements DocumentListener {
@Override
public void changedUpdate(DocumentEvent arg0) {
updateCodedString();
}
@Override
public void insertUpdate(DocumentEvent arg0) {
updateCodedString();
}
@Override
public void removeUpdate(DocumentEvent arg0) {
updateCodedString();
}
}
/**
* A listener to be informed whenever the JTextField of the key text is changed
*/
class KeyListener implements DocumentListener {
@Override
public void changedUpdate(DocumentEvent arg0) {
updateKeyString();
}
@Override
public void insertUpdate(DocumentEvent arg0) {
updateKeyString();
}
@Override
public void removeUpdate(DocumentEvent arg0) {
updateKeyString();
}
}
}
Have fun and enjoy





MultiQuote


|