Шифрование Виженера

У меня был проект с шифром Цезаря и шифром Виженера. Я уже разобрался с Цезарем, но борюсь с шифром Виженера.

Мой код шифрования разделен на две части: encrypt() и encrypt1(). Метод encrypt() извлекает каждый символ и передает его encrypt1(), где в основном происходит все шифрование. Я сделал здесь код, но это не дает мне хороших результатов.

Например, если new VigenereCipher("SLIME").encrypt("GREEN"), где "SLIME" — пароль ключа, а "GREEN" — строка, которая должна быть зашифрована как YcMQR. Но мой код дает ?&|{.

Учтите, что объект алфавита покрывает все = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz 1234567890!@#$%^&*()_+-=[]{}\\|;:'\",./?<>"

Может ли кто-нибудь помочь мне с этим?

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;
    }
}

person joshua    schedule 01.03.2015    source источник
comment
Проголосуйте за то, что потрудились написать это правильно. Спасибо.   -  person user207421    schedule 01.03.2015


Ответы (1)


Проблема именно в этой строчке в функции encrypt1:

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

Здесь вы пытаетесь найти ключ в пароле, но на самом деле вы получаете его из алфавита. Что вы хотите, так это найти соответствующий символ из пароля (зацикливаясь, когда вы дойдете до конца), а затем узнать, каков индекс этого символа в вашем алфавите, чтобы вы могли взять текст плоскости и сдвинуть его на это ( индекс) много символов в алфавите.

Для этого вы можете использовать этот код:

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

Когда я изменяю эту строку и запускаю ваш код с SLIME в качестве ключа и GREEN в качестве открытого текста, я получаю результат YcMQR, который вы и ожидали.

person Erwin Bolwidt    schedule 01.03.2015
comment
Привет @ErwinBolwidt, я добавил остальные классы. Вы предполагаете, что int keyIndex = Alphabet.get(passwordPos++ % password.length()); является источником неправильного вывода? - person joshua; 01.03.2015
comment
Да, я предполагаю, что это причина. Теперь пытаемся запустить ваш код. - person Erwin Bolwidt; 01.03.2015
comment
Да, когда я заменил первую строку, которую я упомянул, двумя строками, которые я упомянул вторыми, результат будет YcMQR, что, как вы сказали, вы ожидали. - person Erwin Bolwidt; 01.03.2015
comment
Спасибо @ErwinBolwidt, я еще не пробовал код, но он кажется логически правильным, пока я читал построчно - person joshua; 01.03.2015
comment
извините за беспокойство, для decrypt1() того же класса я сделал это: char passwordChar = password.charAt(passwordPos++ % password.length()); int keyIndex = Alphabet.indexOf (парольChar); результат = Alphabet.get((index - keyIndex) % Alphabet.length()); Но как обернуть char? - person joshua; 01.03.2015
comment
Ответы на этот вопрос должны помочь вам в дальнейшем (он описывает, как всегда получать положительный результат для функции по модулю) stackoverflow.com/questions/14997165/ - person Erwin Bolwidt; 02.03.2015