Search code examples
javaencryptionvigenere

Vigenère encryption


I've been having a project with Caesar cipher and Vigenère cipher. I already figured out Caesar one but I'm struggling with Vigenère cipher.

My encryption code is divided into two parts: encrypt() and encrypt1(). encrypt() method extracts every character and passes it to encrypt1() where all of the encryption takes place basically. I did here the code but it's not giving me any good results.

For example, if new VigenereCipher("SLIME").encrypt("GREEN") where "SLIME" is a key password and "GREEN" is the String which should be encrypted as YcMQR. But my code gives ?&|{.

Consider that the alphabet object covers everything = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz 1234567890!@#$%^&*()_+-=[]{}\\|;:'\",./?<>"

Could please somebody help me with that?

public class VigenereCipher extends SymmetricCipher {

    protected String password;
    protected int passwordPos;

    public VigenereCipher(String password, Alphabet alphabet)
    {
        super(alphabet);
        this.password = password;
    }
    public VigenereCipher(String password)
    {
        super(Alphabet.DEFAULT);
        this.password = password    ;
    }

    public String getPassword()
    {
        return this.password;
    }



    public String encrypt(String s)
    {
        passwordPos = 0;
        String encrypted = "";
        for(int i = 0; i < s.length(); i++)
        {
            char c = s.charAt(i);
            encrypted += encrypt1(c);

        }


        return encrypted;
    }

    protected char encrypt1(char c)
    {
        //Alphabet temp = new Alphabet(s);
        int index = 0;
        char result = 0;

        index = alphabet.indexOf(c); //Found index of a character 

        if(index != -1)
        {
            int keyIndex = alphabet.get(passwordPos++ % password.length());
            result = alphabet.get((keyIndex + index) % alphabet.length());
        }
        else 
            throw new NotInAlphabetException(c, alphabet);
        return result;
    }

    public String decrypt(String c)
    {
        return c;
    }

    protected char decrypt1(char c)
    {
        return c;
    }

    public String toString()
    {
        return "Vigenere Cipher (password =\'"+this.password+"\')"; 
    }



}


public abstract class SymmetricCipher extends Cipher {

    protected Alphabet alphabet;

    public SymmetricCipher (Alphabet alphabet)
    {
        this.alphabet = alphabet;
    }

    public int wrapInt(int i)
    {
        int index = 0;
        if (i >= alphabet.length())
            index = Math.abs(i) % alphabet.length();
        else if (i < 0)
        {
            int temp = Math.abs(i) % alphabet.length();
            index = alphabet.length() - temp;
        }
        else 
            index = i;

        return index;
    }

    public int rotate(int index, int shift)
    {
        int result = 0;

        if (shift > 0)
        {
            result = (index + shift) % alphabet.length();
        }

        else if (shift < 0)
        {
            if(index < Math.abs(shift))
            {
                int temp = Math.abs(index + shift);
                result = alphabet.length() - temp;

            }
            else 
                result = index + shift ;
        }   


        return result;
    }

    public Alphabet getAlphabet()
    {
        return this.alphabet;
    }

    public String encrypt(String s) 
    {
        String string = "";
        char c = 0;
        char encrypted = 0;
        for (int i = 0; i < s.length(); i++)
        {
            c = s.charAt(i);
            encrypted = encrypt1(c);
            string += encrypted;
        }
        return string;


    }

    public String decrypt(String s) throws NotInAlphabetException
    {
        String string = "";
        char c = 0;
        char encrypted = 0;
        for (int i = 0; i < s.length(); i++)
        {
            c = s.charAt(i);
            encrypted = encrypt1(c);
            string += encrypted;
        }
        return string;


    }

    protected abstract char encrypt1(char c);

    protected abstract char decrypt1(char c);


}



public class Alphabet {


    private String symbols;
    public static final Alphabet DEFAULT = new Alphabet("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz 1234567890!@#$%^&*()_+-=[]{}\\|;:'\",./?<>");

    public Alphabet(String symbols)
    {
        this.symbols = symbols;
    }

    public int indexOf(char c) 
    {
        Alphabet temp = new Alphabet(symbols);
        for(int i = 0; i < symbols.length(); i++)
        {
            if(c == symbols.charAt(i))
                return symbols.indexOf(c) ;
        }

        throw new NotInAlphabetException (c, temp); 
    }

    public char get(int i) 
    {
        Alphabet temp = new Alphabet(symbols);
        char c = 0;
        if (i > this.symbols.length())
            throw new NotInAlphabetException (c, temp);
        else 
            return symbols.charAt(i);
    }

    public int length()
    {
        return symbols.length();
    }

    public String getSymbols()
    {
        return symbols;
    }

    public String toString()
    {
        return "Alphabet("+this.symbols+")";
    }

    public boolean equals(Object other)
    {
        if(other instanceof Alphabet)
        {
            Alphabet temp = (Alphabet) other;
            return this.symbols.equals(temp.symbols);

        }
        else 
            return false;
    }
}

Solution

  • The problem is in this line in the encrypt1 function:

    int keyIndex = alphabet.get(passwordPos++ % password.length());
    

    Here you're trying to look up a key in the password, but you're actually getting it from the alphabet. What you want is to find the relevant character from the password (looping around when you reach the end), and then find out what the index of that character is in your alphabet, so you can take the plane text and shift it by that (index) many characters in the alphabet.

    To do that, you can use this code:

    char pwChar = password.charAt(passwordPos++ % password.length());
    int keyIndex = alphabet.indexOf(pwChar);
    

    When I change this line and run your code with SLIME as the key and GREEN as the plaintext, I get the resul YcMQR, which is what you said you expected.