0

I'm rather new at Java, and I tried to create a vigenere cipher. It's sort of a Caesar shift, only the key is more than one letter, and it's repeated, so the cipher will be harder to break. I've only finished the encrypting portion of the program, but I stopped when I realized it wasn't working well. I mean, it works somewhat, I think, only, when I enter longer strings, the program decides to fail on me. It tells me

Exception in thread "main"

java.lang.ArrayIndexOutOfBoundsException: 26
at Cipher.encrypt(Cipher.java:30)
at Cipher.main(Cipher.java:51)

Um, I do know there are "standard" ways of making vigenere ciphers on Java, but I haven't learned some things they are using, so I would like to know what you find wrong with this program. Thank you so much!!!

import java.util.Scanner;


public class Cipher 
{

public static void encrypt (char[]alpha,String p, String key)

{
String cipher=("");


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


{ 


char c = p.charAt(i);


 int j=-1;


 int k=i%key.length();


 int l=-1;

        do // this one finds the letter character c corresponds to in the alphabet
        {
            j=j+1;
        }while(c!=alpha[j]);

        do// this one finds the letter that the key (or the letter used in the key) corresponds to in the alphabet
        {
            l=l+1;
        }while(key.charAt(k)!=alpha[l]);

         if (j+l>26)//if, say, the key is z and the character is z, then they would minus the shift by 26 so it stays inside the alphabet
        {
            c=alpha[j+l-26];
        }
        else
        {
            c=alpha[j+l];
        }

            cipher=cipher+c;
        }
        System.out.println(cipher.toUpperCase());
}
public static void main(String[] args) 
{
    char[] alpha = "abcdefghijklmnopqrstuvwxyz".toCharArray();
    Scanner scan = new Scanner(System.in);  
    System.out.println("Please enter a key for your vigenere cipher");
    String key= scan.nextLine().toLowerCase().replaceAll("[\\W]", "");
    System.out.println("Your key is "+key.toUpperCase());
    System.out.println("Would you like to encrypt or decrypt a message?");
    String ans=scan.nextLine();
    if (ans.equalsIgnoreCase("encrypt"))
    {
    System.out.println("Please enter your plaintext");
    String p= scan.nextLine().toLowerCase().replaceAll("[\\W]", "");
    System.out.println("Your plaintext is "+p);
    encrypt(alpha,p,key);
    }
    else
    {
    }
    }

}

}

CMedina
  • 4,034
  • 3
  • 24
  • 39
Hello
  • 11
  • 1
  • 1

3 Answers3

0

Here's a Vigenere Cipher that I put together.

Vigenere Cipher

I used a GUI, but you can use the cipher and uncipher methods of the TranslateTextListener class with console input and output.

Here's the code:

package com.ggl.testing;

import java.awt.Component;
import java.awt.Container;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;

public class VigenèreCipher implements Runnable {

    private static final Insets normalInsets = new Insets(10, 10, 0, 10);
    private static final Insets finalInsets = new Insets(10, 10, 10, 10);

    private JTextArea originalTextArea;
    private JTextArea keyTextArea;
    private JTextArea cipherTextArea;
    private JTextArea uncipheredTextArea;

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new VigenèreCipher());
    }

    @Override
    public void run() {
        JFrame frame = new JFrame("Vigenère Cipher");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.add(createCipherPanel());

        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    private JPanel createCipherPanel() {
        JPanel panel = new JPanel();
        panel.setLayout(new GridBagLayout());

        int gridy = 0;

        JLabel originalTextLabel = new JLabel("Original Text:");
        addComponent(panel, originalTextLabel, 0, gridy, 1, 1, normalInsets,
                GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL);

        originalTextArea = new JTextArea(5, 30);
        originalTextArea.setLineWrap(true);
        originalTextArea.setWrapStyleWord(true);
        JScrollPane originalTextScrollPane = new JScrollPane(originalTextArea);
        addComponent(panel, originalTextScrollPane, 1, gridy++, 1, 1,
                normalInsets, GridBagConstraints.LINE_START,
                GridBagConstraints.HORIZONTAL);

        JLabel keyTextLabel = new JLabel("Key Text:");
        addComponent(panel, keyTextLabel, 0, gridy, 1, 1, normalInsets,
                GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL);

        keyTextArea = new JTextArea(5, 30);
        keyTextArea.setLineWrap(true);
        keyTextArea.setWrapStyleWord(true);
        JScrollPane keyTextScrollPane = new JScrollPane(keyTextArea);
        addComponent(panel, keyTextScrollPane, 1, gridy++, 1, 1, normalInsets,
                GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL);

        JLabel cipherTextLabel = new JLabel("Cipher Text:");
        addComponent(panel, cipherTextLabel, 0, gridy, 1, 1, finalInsets,
                GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL);

        cipherTextArea = new JTextArea(5, 30);
        cipherTextArea.setLineWrap(true);
        JScrollPane cipherTextScrollPane = new JScrollPane(cipherTextArea);
        addComponent(panel, cipherTextScrollPane, 1, gridy++, 1, 1,
                finalInsets, GridBagConstraints.LINE_START,
                GridBagConstraints.HORIZONTAL);

        JLabel uncipheredTextLabel = new JLabel("Unciphered Text:");
        addComponent(panel, uncipheredTextLabel, 0, gridy, 1, 1, finalInsets,
                GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL);

        uncipheredTextArea = new JTextArea(5, 30);
        uncipheredTextArea.setLineWrap(true);
        uncipheredTextArea.setWrapStyleWord(true);
        JScrollPane uncipheredTextScrollPane = new JScrollPane(
                uncipheredTextArea);
        addComponent(panel, uncipheredTextScrollPane, 1, gridy++, 1, 1,
                finalInsets, GridBagConstraints.LINE_START,
                GridBagConstraints.HORIZONTAL);

        JButton submitButton = new JButton("Translate text");
        submitButton.addActionListener(new TranslateTextListener());
        addComponent(panel, submitButton, 0, gridy++, 2, 1, finalInsets,
                GridBagConstraints.CENTER, GridBagConstraints.NONE);

        return panel;
    }

    private void addComponent(Container container, Component component,
            int gridx, int gridy, int gridwidth, int gridheight, Insets insets,
            int anchor, int fill) {
        GridBagConstraints gbc = new GridBagConstraints(gridx, gridy,
                gridwidth, gridheight, 1.0D, 1.0D, anchor, fill, insets, 0, 0);
        container.add(component, gbc);
    }

    public class TranslateTextListener implements ActionListener {

        private char[] cipherAlphabet;

        private int lowerLimit;
        private int upperLimit;

        public TranslateTextListener() {
            this.lowerLimit = 32;
            this.upperLimit = 126;
            this.cipherAlphabet = new char[upperLimit - lowerLimit + 1];
            // Grab all the ASCII characters between space and ~, inclusive
            for (int i = lowerLimit; i <= upperLimit; i++) {
                cipherAlphabet[i - lowerLimit] = (char) i;
            }
        }

        @Override
        public void actionPerformed(ActionEvent event) {
            String text = originalTextArea.getText().trim();
            String key = keyTextArea.getText().trim();
            String cipher = cipherTextArea.getText().trim();
            String uncipher = "";

            if (!text.equals("") && !key.equals("")) {
                cipher = cipher(text, key);
            }

            if (!key.equals("") && !cipher.equals("")) {
                uncipher = uncipher(cipher, key);
            }

            cipherTextArea.setText(cipher);
            uncipheredTextArea.setText(uncipher);
        }

        private String cipher(String text, String key) {
            StringBuilder builder = new StringBuilder(text.length());
            int keyIndex = 0;
            for (int i = 0; i < text.length(); i++) {
                char c = text.charAt(i);
                int pos = (int) c;
                if (pos < lowerLimit || pos > upperLimit) {
                    builder.append(c);
                } else {
                    char k = key.charAt(keyIndex);
                    pos = getCharacterPosition(c);
                    int pos2 = getCharacterPosition(k);
                    int sum = (pos + pos2) % cipherAlphabet.length;
                    builder.append(getCharacter(sum));
                    keyIndex = ++keyIndex % key.length();
                }
            }
            return builder.toString();
        }

        private String uncipher(String cipher, String key) {
            StringBuilder builder = new StringBuilder(cipher.length());
            int keyIndex = 0;
            for (int i = 0; i < cipher.length(); i++) {
                char c = cipher.charAt(i);
                int pos = (int) c;
                if (pos < lowerLimit || pos > upperLimit) {
                    builder.append(c);
                } else {
                    char k = key.charAt(keyIndex);
                    pos = getCharacterPosition(c);
                    int pos2 = getCharacterPosition(k);
                    int sum = pos - pos2;
                    while (sum < 0) {
                        sum += cipherAlphabet.length;
                    }
                    sum = sum % cipherAlphabet.length;
                    builder.append(getCharacter(sum));
                    keyIndex = ++keyIndex % key.length();
                }
            }
            return builder.toString();
        }

        private int getCharacterPosition(char c) {
            for (int i = 0; i < cipherAlphabet.length; i++) {
                if (c == cipherAlphabet[i]) {
                    return i;
                }
            }

            return -1;
        }

        private char getCharacter(int index) {
            if (index >= 0 && index < cipherAlphabet.length) {
                return cipherAlphabet[index];
            } else {
                return '?';
            }
        }

    }
}
Gilbert Le Blanc
  • 50,182
  • 6
  • 67
  • 111
0

Try different approach? Here's mine, it simply makes a new variable that will hold encrypted message and stores changed characters there based on ASCII value. I still have to add spaces, so far it only encrypts messages without any spaces, but it can be as long as I want.

public class vigenere {
public static void main(String[] args) {
    String encryptedMessage = "";
    String extended = "";
    int temp, counter;

    String plain_text = JOptionPane.showInputDialog("Enter the text you wish to encrypt: ");
    String keyword = JOptionPane.showInputDialog("Enter the keyword: ");

    counter = plain_text.length() / keyword.length() + 3;

    for (int i = 0; i < counter; i++){
        extended += keyword;
    }

    for (int j = 0; j < plain_text.length(); j++) {


            if (plain_text.charAt(j) + ((extended.charAt(j) - 97)) > 122) {
                temp = (int)(plain_text.charAt(j) + (extended.charAt(j) -123 ));
                encryptedMessage += (char)temp;
            } else {
                temp = (int)(plain_text.charAt(j) + (extended.charAt(j) - 97 ));
                encryptedMessage += (char)temp;
            }
        }
    }
    JOptionPane.showMessageDialog(null, encryptedMessage);
}

}

"Counter" is for how many times must we prolong keyword to match the length of the plaintext, i put +3 at the end to be sure but i think +1 is enough. Also, I am VERY new to this, so this code is as basic as it can get xD

0

There are 26 characters in alpha, so valid indexes are 0–25.

You check to see if j+l > 26, and shift if needed, but you should be checking whether j+l > 25.

Better yet, don't test with if and handle different cases, just do this unconditionally:

c = alpha[(j + l) % 26];

Also, rather than searching for a character in the alphabet, use subtraction:

j = c - 'a';

I'd put it all together like this:

static String encrypt(String message, String key) {
  StringBuilder buf = new StringBuilder(message.length());
  for (int idx = 0; idx < message.length(); ++idx) {
    char p = message.charAt(idx);
    int j = p - 'a';
    char k = key.charAt(i % key.length());
    int l = k - 'a';
    char c = (char) ('a' + ((j + l) % 26));
    buf.append(c);
  }
  return buf.toString();
}
erickson
  • 265,237
  • 58
  • 395
  • 493