3

I was looking at the Vigene Ciphere source code provided on http://rosettacode.org/wiki/Vigen%C3%A8re_cipher#Java. I tried testing out the program myself, and it wasn't outputting the values I expect based on vigene. For example 'dog' being the word and 'bob' being the key I would expect this to be encrypted to 'ech', but is 'qot' instead.

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

However the output is different. Is this because my understanding of the cipher is incorrect or this has taken a different approach to the well known vigenere cipher.

Cœur
  • 37,241
  • 25
  • 195
  • 267
user2982832
  • 177
  • 9

2 Answers2

0

Because you are setting your text to encrypt to lowercase, try changing these character literals to lowercase as well:

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

When casting an int to a char, you have to take into account that the integer value of 'a' is not equal to 'A'. Because you are checking that your current character is between 'a' and 'z' (as you have set it to lowercase), you should also have an output in lowercase as well.

MrPublic
  • 520
  • 5
  • 16
  • ah thank you! could you explain to me by any chance what this line is actually doing ? – user2982832 Oct 19 '15 at 15:17
  • Because character values in java have different integer values (2 * 'a' is not the same as 2 * 'A'), the resulting character will be slightly off depending on what integer value is calculated, then cast to a character. – MrPublic Oct 19 '15 at 15:19
0

As what was already pointed out by the user, you should change the line to:

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

Alternatively, you can change this:

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

to this:

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

Just ensure when you convert the ASCII back to letters, you are using the correct ASCII value (i.e. 65 (A) for uppercase, 97 (a) for lowercase).

user3437460
  • 17,253
  • 15
  • 58
  • 106
  • 1
    "Alternatively, you can change..." That'd mean that nothing would be encrypted, owing to the `text.toLowerCase()` a few lines before. – Andy Turner Oct 19 '15 at 15:49