Vigenere ciphers are supposedly easy to use (well, to some extent), but when converting it directly into program code, that's a whole other story. Apparently.
Let's say I have a method that can encrypt text using the Vigenere Square cipher, while still maintaining the spaces and special characters (or most of them).
static string EncryptedText(string plaintext, string keyword)
{
string tempStore = "";
string KeyToUse = ExpandKey(RemoveAllNonAlpha(plaintext), keyword);
string[] tempList;
int iSelector = 0;
for (int ii = 0; ii < RemoveAllNonAlpha(plaintext).Length; ii++)
{
tempList = GetNewAlphaList(KeyToUse[ii].ToString());
if (RemoveAllNonAlpha(plaintext)[ii].ToString() != " ")
{
iSelector = NeverOver26(GetNumericFromLetter(RemoveAllNonAlpha(plaintext)[ii].ToString())) - 1;
tempStore += tempList[iSelector].ToLower();
}
else
{
tempStore += " ";
}
}
return ReplaceAllNonAlpha(tempStore, plaintext);
}
If we assume that for the above, the following functions are as so...
string ExpandKey(string input) => Lengthen the key until it matches the plaintext.
string RemoveAllNonAlpha(string input) => Basically remove anything that is not an alphabet. Uses Regex Replace.
int GetNumericFromLetter(string char) => Just converts a letter to a number, with A = 1, and Z = 26. Adapted version of this accepted answer.
string ReplaceAllNonAlpha(string processed, string original) => Basically it just checks the original string, and then replaces all the non alphabetical characters. It's mainly using a regex string to check if a character is not an alphabet.
int NeverOver26(int input) => Basically it just subtracts 26 from the value whenever it goes over 26.
string[] GetNewAlphaList(string char) => Generates a column or row of the vigenere cipher to lookup from, with the letter passed in being the first letter in the array. For example, if the passed letter is "L", then it returns { "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K" }.
Now, the above snippet of code has been found to be working perfectly, and could be said to be literally translated from the way humans would use the Vigenere Square table.
However, the decryption method doesn't seem to like the approach, though:
static string DecryptedText(string ciphertext, string keyword)
{
//Broken, non deciphering
string tempStore = "";
string KeyToUse = ExpandKey(RemoveAllNonAlpha(ciphertext), keyword);
string[] tempList;
for (int ii = 0; ii < RemoveAllNonAlpha(ciphertext).Length; ii++)
{
tempList = GetNewAlphaList(RemoveAllNonAlpha(ciphertext)[ii].ToString());
for (int iii = 0; iii < tempList.Length; iii++)
{
if (tempList[iii].ToString().ToLower() == KeyToUse[ii].ToString().ToLower())
{
tempStore+= GetAlphaFromNumber(iii).ToLower();
break;
}
}
}
return ReplaceAllNonAlpha(tempStore, ciphertext);
}
In the (not working as expected) decryption method, we can see that it uses most of the same functions as the encryption method, with the addition of...
string GetAlphaFromNumber(int input) => Does the exact opposite of GetNumericFromLetter() Adapted version of this accepted answer.
It has been determined that the issue is within the second for-loop of the decryption method itself. It is a sort of primitive lookup process, where it just looks within a string array that corresponds to a row/column of the Vigenere Square table.
Is there something wrong with the logic, or just something wrong with the code itself? Pseudocode is okay, I do admit I'm not quite sure how to translate the human method of decoding using the Vigenere Square table into pseudocode (then finally into the language of choice I am using)
Please note, that I am aware of these questions, and I am not looking for how to do it, but rather, where I went wrong:
I guess my question is very similar to this question, though I doubt the issue is the same:
Input: ATTACK ON DAWN. LOL
Keyword: LEMON
Output: lxfopv ef rnhr. xcy
Input: lxfopv ef rnhr. xcy
Keyword: LEMON
Output: ahhayq ah xaen. pmp
It turns out that I was using the wrong method of looking up the table in the first place. There was nothing wrong with the coding of my program, as it worked as intended. It was just the way it was looking up the values, or in other words, the logic that was wrong. Below is the amended code for the decryption method, which now works fine:
internal static string DecryptedText(string ciphertext, string keyword)
{
string tempStore = "";
string KeyToUse = ExpandKey(RemoveAllNonAlpha(ciphertext), keyword);
string[] tempList;
int iSelector = 0;
for (int ii = 0; ii < RemoveAllNonAlpha(ciphertext).Length; ii++)
{
tempList = GetNewAlphaList(KeyToUse[ii].ToString());
for (int iii = 0; iii < tempList.Length; iii++)
{
////seperated the two to verify they were not returning the wrong values
//string FromList = tempList[iii].ToString().ToLower();
//string FromCipher = RemoveAllNonAlpha(ciphertext)[ii].ToString().ToLower();
if (tempList[iii].ToString().ToLower() == RemoveAllNonAlpha(ciphertext)[ii].ToString().ToLower())//if (FromList == FromCipher)
{
tempStore += GetAlphaFromNumber(iii).ToLower();
break;
}
}
}
return ReplaceAllNonAlpha(tempStore, ciphertext);
}
Input: this is just a simple test. complete with punctuations galore, wohoo!
Keyword: stackoverflowisthebest
Output: laiu sg eyjy l geuhel xfwl. vgfpnohz azys dqvumbeumggk zanyfz, afmzc!
Input: laiu sg eyjy l geuhel xfwl. vgfpnohz azys dqvumbeumggk zanyfz, afmzc!
Keyword: stackoverflowisthebest
Output: this is just a simple test. complete with punctuations galore, wohoo!
Guess it's time for me to try to find a way for it to preserve the capitalization as well after conversion.