Confused about Vigenère cipher implementation in Java
encryption, java, vigenere
Solution
Background
The code uses the ASCII value of the letters. The letters A-Z are ASCII values 65-90.
The idea is to add the two letters together, but wrap around if the values goes above 90 (known as modular arithmetic). So 91 should actually be 65 (i.e. `Z + 1 = A`).
Java provides a `%` operator for doing modular arithmetic (`x % n`). However, this is designed to work on a range of numbers 0→n-1. So, if we subtract 65 from each of our letters, we are then working in the range 0→25. This allows us to use the modulus operator (`x % 26`).
This is what the code is doing:
c + key.charAt(j) - 2 * 'A'
This part adds the two letters together, but also subtracts 65 from each of them. It may be easier to understand if written as:
(c - 'A') + (key.charAt(j) - 'A')
You'll notice that you can do `- 'A'` as a convenient way of doing `- 65`.
Now we have a value that's zero-based, but possibly larger than 25. So we then modulo it:
(c + key.charAt(j) - 2 * 'A') % 26
We then need to add 65 back to the value, to bring it back into the A-Z range for ASCII:
(c + key.charAt(j) - 2 * 'A') % 26 + 'A'
The only remaining step is to cast this to a `char`, since the result is an `int` by default:
res += (char)((c + key.charAt(j) - 2 * 'A') % 26 + 'A');
Example
If the input is `ATTACK` and the keyword is `LEMON`, then at some point we are going to have to consider the input letter `T` (ASCII 84) and the key letter `M` (ASCII 77).
Subtracting 65 from each, we have T=19 and M=12. Added together, we get 31.
`31 % 26 = 5`. So we then calculate `5+65=70`, which is the ASCII value for `F`.
Problem
Please can someone explain the line of code highlighted below. I don't understand at all how this line works. You can use this example to help me: ``` input: ATTACK keyword: LEMON res: LXFOPV ``` I don't understand how that line helps encode `A` to `L` and other letter... ACSII involvement? ``` static String encrypt(String text, final String key) { String res = ""; text = text.toUpperCase(); for (int i = 0, j = 0; i < text.length(); i++) { char c = text.charAt(i); if (c < 'A' || c > 'Z') continue; //////////////////////////////////////////////////////////////////////////// //please someone explain this line res += (char)((c + key.charAt(j) - 2 * 'A') % 26 + 'A'); //////////////////////////////////////////////////////////////////////// j = ++j % key.length(); } return res; } ```