Выход шифра Виженера

Я просматривал исходный код Vigene Ciphere, представленный на http://rosettacode.org/wiki/Vigen%C3%A8re_cipher#Java. Я попытался протестировать программу самостоятельно, и она не выдавала значений, которые я ожидаю на основе Вигена. Например, «собака» — это слово, а «боб» — это ключ. Я ожидаю, что это будет зашифровано как «ech», но вместо этого будет «qot».

public static void main(String[] args) {
    String key = "bob";
    String ori = "dog";
    String enc = encrypt(ori, key);
    System.out.println(enc);

}

static String encrypt(String text, final String key) {
    String res = "";
    text = text.toLowerCase();
    for (int i = 0, j = 0; i < text.length(); i++) {
        char c = text.charAt(i);
        if (c < 'a' || c > 'z') continue;
        res += (char)((c + key.charAt(j) - 2 * 'A') % 26 + 'A');
        j = ++j % key.length();
    }
    return res;
}

Однако выход разный. Это потому, что мое понимание шифра неверно, или это использует другой подход к хорошо известному шифру Виженера.


person user2982832    schedule 19.10.2015    source источник
comment
Однако вывод отличается. Что это вместо этого?   -  person Andy Turner    schedule 19.10.2015
comment
@RishavKundu, если предположить, что это не просто аббревиатура, которую я не слышал, лучше включить это в вопрос - добавлено.   -  person Andy Turner    schedule 19.10.2015
comment
@AndyTurner помните, что вывод был в верхнем регистре; Хотя не знаю важно это или нет.   -  person xrisk    schedule 19.10.2015


Ответы (2)


Как уже было указано пользователем, вы должны изменить строку на:

res += (char)((c + key.charAt(j) - 2 * 'a') % 26 + 'a');

Кроме того, вы можете изменить это:

if (c < 'a' || c > 'z') continue;

к этому:

if (c < 'A' || c > 'Z') continue;

Просто убедитесь, что при преобразовании ASCII обратно в буквы вы используете правильное значение ASCII (например, 65 (A) для верхнего регистра, 97 (a) для нижнего регистра).

person user3437460    schedule 19.10.2015
comment
В качестве альтернативы вы можете изменить... Это означало бы, что ничего не будет зашифровано из-за text.toLowerCase() несколькими строками ранее. - person Andy Turner; 19.10.2015

Поскольку вы настраиваете свой текст для шифрования в нижнем регистре, попробуйте также изменить эти литералы символов на нижний регистр:

res += (char)((c + key.charAt(j) - 2 * 'a') % 26 + 'a');

При преобразовании int в char необходимо учитывать, что целочисленное значение «a» не равно «A». Поскольку вы проверяете, что ваш текущий символ находится между «a» и «z» (поскольку вы установили его в нижний регистр), вы также должны иметь вывод в нижнем регистре.

person MrPublic    schedule 19.10.2015
comment
ах спасибо! не могли бы вы объяснить мне случайно, что на самом деле делает эта строка? - person user2982832; 19.10.2015
comment
Поскольку значения символов в java имеют разные целочисленные значения (2 * 'a' не совпадает с 2 * 'A'), результирующий символ будет немного отличаться в зависимости от того, какое целочисленное значение вычисляется, а затем приводится к символу. - person MrPublic; 19.10.2015