Page 1 of 1

Secret Code I - Ceasar Cipher The oldest secret code Rate Topic: ***** 1 Votes

#1 pbl  Icon User is offline

  • There is nothing you can't do with a JTable
  • member icon

Reputation: 8347
  • View blog
  • Posts: 31,913
  • Joined: 06-March 08

Posted 16 September 2010 - 09:15 PM

*
POPULAR

Many times we have question in the forum about the oldest known secret code: the Ceasar cipher which is quite easy to break.

More details on Wikipedia

http://en.wikipedia....i/Caesar_cipher

A lot of comments in the code.

First: Ceasar.java
This file is a console version that will allow you to encode/decode messages using the Ceasar code.

Second: CeasarGui.java
This file is a GUI version that calls the preceding one and allow, in a GUI environment, to encode/decode messages changing with JRadioButton the number of shifts to apply.

Ceasar.java
import java.util.Scanner;
/*
 * The first registered secret code that was used by Julius Ceasar (or at least his army)
 * during the Gaul war 50 BC
 * All letters in the alphabet are shifted by a certain number of letters
 * The number of shifts must be known by the sender and the receiver
 * So if shift == 1
 * abcdefghijklmnopqrstuvwxyz will be coded as
 * BCDEFGHIJKLMNOPQRSTUVWXYZA
 * if shift == 5
 * abcdefghijklmnopqrstuvwxyz will be coded as
 * FGHIJKLMNOPQRSTUVWXYZABCDE
 */
public class Ceasar {
	// the number of letter(s) we shifted
	private int nbShift;
	
	/**
	 *  constructor that receives the number of letters we will shift
	 * @param nbShift
	 */
	public Ceasar(int nbShift) {
		setShiftValue(nbShift);
	}
	
	/**
	 * To set the initial or change the shift value
	 * @param nbShift
	 */
	public void setShiftValue(int nbShift) {
		// wrap around shift > 26 and accept only positive shifts
		if(nbShift < 0)
			nbShift = -nbShift;
		// store the number of shift to be applied
		this.nbShift = nbShift % 26;		
	}

	/** 
	 * this method returns the encrypted String from the String received as parameter
	 * according to the current number of letter(s) to shift in the alphabet
	 */  
	public String encode(String clear) {
		// ignore if null
		if(clear == null)
			return "";
		// 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();
		// 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;
	
			// 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 a new String made of these shifted characters
		return new String(digit);
	}
	
	/** 
	 * this method returns the decrypted String from the String received as parameter
	 * according to the current number of letter(s) to shift in the Ceasar code
	 */  
	public String decode(String coded) {
		// ignore if null
		if(coded == null)
			return "";
		// 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();
		// pass through all input coded 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 upperrcase)
			if(digit[i] < 'A' || digit[i] > 'Z') {
				continue;
			}
			// 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 a new String made of these shifted characters
		return new String(digit);
	}
	
	/**
	 *  the main() method to test our Ceasar class
	 *  @param args
	 */
	public static void main(String[] args) {
		
		//--------------------------------------------------------
		// Automatic tests
		//--------------------------------------------------------
		
		// to test with all possible shifts 
		// the following line can be removed (or commented) in production code
		testAllShifts();	// <---- to be removed in  production code
		
		//--------------------------------------------------------
		// End of Automatic tests
		//--------------------------------------------------------
		
		// now test a real case
		// Creates a Scanner to read use input
		Scanner scan = new Scanner(System.in);
		// read the number of shift
		// init number of shift to an integer valid value
		int nbShift = 0;
        // loop until we break for a valid value
		while(true) {
			System.out.print("Enter number of letters to shift: ");
			String str = scan.nextLine();
			// try to translale String inputed as Integer
			try {
				nbShift = Integer.parseInt(str);
				// if the catch case was not invoked it means this is a valid integer input
				// so we break out the loop
				break;
			}
			catch(Exception e) {
				System.out.println("Sorry your nbumber of shifts is invalid");
			}
		}
		
		// now that we have a valid shift create a Ceasar object with the number of shifts
		Ceasar ceasar = new Ceasar(nbShift);
		// input the line to be coded
		System.out.print("Enter message to be coded: ");
		String clearMsg = scan.nextLine();
		// code the user input
		String codedString = ceasar.encode(clearMsg);
		// print the coded string
		System.out.println("The coded String is:         " + codedString);
		// and its translation decoded
		System.out.println("And its translation back is: " + ceasar.decode(codedString));
	}
	
	/**
	 * Used to test with all the letters of the alphabet that all the shifts work
	 */
	private static void testAllShifts() {
		String alphabet = "abcdefghijklmnopqrstuvwxyz";
		// test the 26 possible shifts... and a little bit more just to make sure that 
		// our modulo operation works correctly
		System.out.println("             " + alphabet);
		for(int i = 0; i < 30; i++) {
			Ceasar ceasar = new Ceasar(i);
			System.out.format("Shift: %02d -> %s\n", i, ceasar.encode(alphabet));
		}
		System.out.println();
	}
}



CeasarGui.java
import java.awt.*;
import java.awt.event.*;

import javax.swing.*;
import javax.swing.event.*;

/**
 * A GUI that use the Ceasar class to encode/decode messages
 */
public class CeasarGui extends JFrame implements ActionListener {

	private static final long serialVersionUID = 1L;

	// the CheckBox to select the number of shifts
	private JRadioButton[] shiftRadio;
	// the Ceasar class to encode/decode
	private Ceasar ceasar;

	// The message to encode
	private JTextField clearTextIn;
	private JLabel encodedTextOut;
	// the message to decode
	private JTextField codedTextIn;
	private JLabel decodedTextOut;
	
	/**
	 * Constructor
	 */
	CeasarGui() {
		super("Ceasar encoding/decoding");
		// we will use a GridLayout to store our GUI component
		JPanel mainPanel = new JPanel(new GridLayout(1, 2, 4, 4));

		// to store the coded text input output fiels
		JPanel textPanel = new JPanel(new GridLayout(14, 1));
		// a little gap at the beginning of the Panel
		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(30);
		// 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(30);
		codedTextIn.getDocument().addDocumentListener(new CodedListener());
		textPanel.add(codedTextIn);
		textPanel.add(createCenteredLabel("Decoded text"));
		decodedTextOut = createOutputLabel();
		textPanel.add(decodedTextOut);

		// the left panel constains a lot less lines than the right panel
		// will make a GridLayout(2,1) with empty bottom
		JPanel leftPanel = new JPanel(new GridLayout(2,1));
		leftPanel.add(textPanel);
		leftPanel.add(new JLabel());
		mainPanel.add(leftPanel);
		

		// init the number of shifts to 1
		ceasar = new Ceasar(1);
		// creates the right panel with all the possible shifts
		JPanel shiftPanel = createShiftPanel();
		shiftRadio[1].setSelected(true);
		mainPanel.add(shiftPanel);

		// the panel stored in the center of the JFrame
		add(mainPanel, BorderLayout.CENTER);

		// standard operation to show the JFrame
		this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		setLocation(30, 30);
		pack();
		setVisible(true);
	}

	/**
	 * A radio button to change the shifts has been selected
	 */
	public void actionPerformed(ActionEvent e) { 
	    // get the radio button that fired the event
		Object o = e.getSource();
		// scan the list to find which one
		for(int i = 0; i < shiftRadio.length; i++) {
			// when found
			if(o == shiftRadio[i]) {
				// set the Ceasar with this new value
				ceasar.setShiftValue(i);
				// exit the loop
				break;
			}
		}
		// update both strings to code and decode with the new shift
		updateCodedString();
		updateDecodedString();
	}

	/**
	 * 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 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(ceasar.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(ceasar.decode(line));
	}
	
	/**
	 * To create the JPanel containing the possible shifts
	 */
	private JPanel createShiftPanel() {
		// a double alphabet we will display the 26 letters from 0, 1, 2, 3...
		String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ";
		// a Panel for the 26 possible shifts plus a header
		JPanel panel = new JPanel(new GridLayout(27, 1));
		panel.setBorder(BorderFactory.createLineBorder(Color.BLUE));
		
		// the header atthe top of the Panel
		JLabel label = new JLabel("Number of letters for the shift");
		label.setHorizontalAlignment(SwingConstants.CENTER);
		label.setForeground(Color.BLUE);
		panel.add(label);
		
		// a ButtonGroup only one radioButton can be selected at each time
		ButtonGroup bg = new ButtonGroup();
		shiftRadio = new JRadioButton[26];
		// add the 26 JRadioButton
		for(int i = 0; i < 26; i++) {
			// format its text 00 - ABCDEF...
			String str = String.format("%02d - %s", i, alphabet.substring(i, i+26));
			shiftRadio[i] = new JRadioButton(str);
			shiftRadio[i].addActionListener(this);
			// add it to the ButtonGroup
			bg.add(shiftRadio[i]);
			// and to the panel
			panel.add(shiftRadio[i]);
		}
		return panel;
	}
	
	/**
	 * To start the GUI
	 */
	public static void main(String[] args) {
		new CeasarGui();
	}

	/**
	 * 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();
		}

	}

}



Have fun

Is This A Good Question/Topic? 6
  • +

Replies To: Secret Code I - Ceasar Cipher

#2 Dogstopper  Icon User is offline

  • The Ninjaducky
  • member icon



Reputation: 2876
  • View blog
  • Posts: 11,051
  • Joined: 15-July 08

Posted 17 September 2010 - 12:42 PM

This code looks good pbl! I like the concept of starting with a console application and then moving to a GUI application. That's something we see frequently not happening.

If I were to write this application, I would have used a JScrollPane instead of a group of the JRadioButtons. However, it is a very good tutorial. Well done.
Was This Post Helpful? 0
  • +
  • -

#3 pbl  Icon User is offline

  • There is nothing you can't do with a JTable
  • member icon

Reputation: 8347
  • View blog
  • Posts: 31,913
  • Joined: 06-March 08

Posted 17 September 2010 - 06:02 PM

View PostDogstopper, on 17 September 2010 - 01:42 PM, said:

This code looks good pbl! I like the concept of starting with a console application and then moving to a GUI application.

Seperating the GUI from the business rules is the first concept that you should learn in GUI programming. No need to have each of them interfere with the other.
Every class should have it's main() method for unit test.

When you know that your business class works, here the console application, no need when you build your GUI to go back to it if something goes wrong

I also though of replacing the JRadioButton by a JComboBox but thought that the JRadioButton would show more GUI concepts
Was This Post Helpful? 0
  • +
  • -

#4 ahmaag951  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 1
  • Joined: 25-October 11

Posted 25 October 2011 - 09:52 PM

you are genious.
Was This Post Helpful? 0
  • +
  • -

#5 Benzoate  Icon User is offline

  • D.I.C Head


Reputation: 51
  • View blog
  • Posts: 234
  • Joined: 29-February 12

Posted 10 March 2012 - 11:49 AM

whoah... much respect sir.
Was This Post Helpful? 0
  • +
  • -

#6 farrell2k  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 866
  • View blog
  • Posts: 2,657
  • Joined: 29-July 11

Posted 18 March 2012 - 04:38 PM

Entirely too complex.

Shift based on 5.

public static String encodeWord(String word) {
	    StringBuffer r = new StringBuffer();
	    for (int i = 0; i < word.length(); i++) {
	      char c = word.charAt(i);                  
	      c = (char)('a' + (c -'a'+ 5) % 26);      
	      r.append(c);                         
	    }
	    return r.toString();                    
	  } // encode()

	  public static String decodeWord(String word) {
	    StringBuffer r = new StringBuffer();
	    for (int i = 0; i < word.length(); i++) {
	       char c = word.charAt(i);
	       c = (char)('a' + (c - 'a' + 21) % 26);
	       r.append(c);                      
	    }
	    return r.toString();                    
	  }



Was This Post Helpful? 2
  • +
  • -

#7 pbl  Icon User is offline

  • There is nothing you can't do with a JTable
  • member icon

Reputation: 8347
  • View blog
  • Posts: 31,913
  • Joined: 06-March 08

Posted 18 March 2012 - 05:52 PM

View Postfarrell2k, on 18 March 2012 - 07:38 PM, said:

Entirely too complex.

May be for you :)
All previous posts congratulates me
Was This Post Helpful? 0
  • +
  • -

#8 farrell2k  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 866
  • View blog
  • Posts: 2,657
  • Joined: 29-July 11

Posted 18 March 2012 - 08:12 PM

View Postpbl, on 19 March 2012 - 12:52 AM, said:

View Postfarrell2k, on 18 March 2012 - 07:38 PM, said:

Entirely too complex.

May be for you :)
All previous posts congratulates me


I am not attacking you. Your code obviously works. You did a great job with it, but my code is just better and easier to understand. Now someone can learn how to do it the less efficient way and the more efficient way.
Was This Post Helpful? 0
  • +
  • -

#9 cMcInerney  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 1
  • Joined: 06-February 13

Posted 06 February 2013 - 05:54 PM

This is great! How would you change the code to include lowercase? say: ABCdef shifted by 2 -- CDEfgh or if XYZ shifted by 2 -- abc
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1