topdawg_coder
topdawg_coder

Reputation: 13

how to make this lowercase and uppercase

I am making an encryption program based on Vigenere cipher.

I am stuck on the lowercase and uppercase part.

For instance, if I wanted to encrypt/decrypt the text:

"This is a STRING"

The uppercase letters encrypt/decrypt fine, but the lowercase letters do not decrypt correctly. Also, the key that I use is all uppercase. Shouldn't the code below work for uppercase and lowercase?

if (isupper(OriginalText[i])) {
    int x = (OriginalText[i] + key[i]) % 26;
    x = x + 'A';

    EncryptText.push_back((x));
} else if (islower(OriginalText[i])) {
    int y = (OriginalText[i] + key[i]) % 26;

    y = y + 'a';

    EncryptText.push_back((y));
}

Below is for decryption:

if (EncryptedText[i] != space[j]) {

    if (isupper(EncryptedText[i])) {
        int x = (EncryptedText[i] - key[i] + 26) % 26;
        x += 'A';

        DecryptedText.push_back((x));
    } else if (islower(EncryptedText[i])) {
        int y = (EncryptedText[i] - key[i] + 26) % 26;
        y += 'a';

        DecryptedText.push_back((y));
    }
}

EDIT: Instead of the above code, I tried approaching it with the code below in order to cover all aspects.

I was able to get these two conditions to work:

So, I know a lowercase cipher key will work. Now, I need to get these conditions to work:

Here is the code below:

        if (EncryptedText[i] != space[j]) {

        if (isupper(EncryptedText[i]) && isupper(key[i])) {
            x = ((((EncryptedText[i] + 'A') - (key[i] - 'A')) % 26) + 'A');
            DecryptedText.push_back(x);
        }
        if (isupper(EncryptedText[i]) && islower(key[i])) {
            x = ((((EncryptedText[i] + 'A') - (key[i] - 'a')) % 26) + 'A');
            DecryptedText.push_back(x);
        }
        if (islower(EncryptedText[i]) && isupper(key[i])) {
            x = ((((EncryptedText[i] + 'a') - (key[i] + 'A')) % 26) + 'a');
            DecryptedText.push_back(x);
        }
        if (islower(EncryptedText[i]) && islower(key[i])) {
            x = ((((EncryptedText[i] + 'a') - (key[i] + 'a')) % 26) + 'a');
            DecryptedText.push_back(x);
        }

I need help with last two if statements.

BELOW IS A LINK TO REDDIT WHICH HAS A LINK TO THE GITHUB PROJECT: https://www.reddit.com/r/CodingHelp/comments/91c3tv/need_some_help_on_vigenere_cipher_program/

Upvotes: 1

Views: 1569

Answers (3)

David C. Rankin
David C. Rankin

Reputation: 84559

As I read the Vigenere cipher, you are limited to a single 26x26 table for encoding. (at least as explained in the Wikipedia page). That means you have no way to mix and uppercase key with a lowercase character or vice versa, without making the cases match.

You are free to add to the cipher to extend the "tabula recta, Vigenère square, or Vigenère table" to include lowercase character resulting in a 52x52 and build the offset gymnastics into your cipher -- but then it wouldn't be the Vigenere cipher.

That doesn't mean you can't handle both uppercase and lowercase characters, you just have to make the key/character case-consistent for both encoding and decoding. You can do that by simply using the tolower or toupper conversions as you work through the encoding/decoding, e.g.

#include <iostream>
#include <string>

using namespace std;

int main (int argc, char **argv) {

    string  key = argc > 1 ? argv[1] : "LEMON",
            line,       /* input to encode */
            cipher,     /* encoded input  */
            decode;     /* decoded cipher */
    auto& k = key;
    size_t kdx = 0;        /* key index */

    if (!k[kdx]) {  /* validate key has at least one char */
        cerr << "invalid key.\n";
        return 1;
    }

    while (getline (cin, line)) {   /* read each line of input */
        /* encode line into cipher */
        for (auto& c : line) {      /* for each char in input */
            if (islower(c))         /* if lower, force key lower */
                cipher.push_back((tolower(k[kdx]) - 'a' + c - 'a') % 26 + 'a');
            else if (isupper (c))   /* if upper, force key upper */
                cipher.push_back((toupper(k[kdx]) - 'A' + c - 'A') % 26 + 'A');
            else {  /* otherwise -- character not supported */
                cerr << "error: unsupported char '" << c << "' removing.\n";
                continue;
            }
            kdx++;  /* increment key index */
            if (kdx == key.length())    /* if end of key, reset key index */
                kdx = 0;
        }
        /* decode cipher into decode */
        kdx = 0;                    /* reset key index */
        for (auto& c : cipher) {    /* for each char in cipher */
            if (islower (c)) {      /* if lower, force key lower */
                int off = c - tolower (k[kdx]);
                if (off >= 0)       /* if offset >= 0, mod 26 */
                    decode.push_back (off % 26 + 'a');
                else                /* if offset < 0, + 26 */
                    decode.push_back (off + 26 + 'a');
            }
            else if (isupper (c)) { /* do the same for upper case */
                int off = c - toupper (k[kdx]);
                if (off >= 0)
                    decode.push_back (off % 26 + 'A');
                else
                    decode.push_back (off + 26 + 'A');        
            }
            else {  
                cerr << "error: invalid char in cipher '" << c << "'.\n";
                return 1;
            }
            kdx++;  /* increment key index */
            if (kdx == key.length())    /* if end of key, reset key index */
                kdx = 0;
        }
        cout << "input : " << line << '\n' <<
                "key   : " << key <<  '\n' <<
                "cipher: " << cipher << '\n' <<
                "decode: " << decode << '\n';

        cipher.clear();     /* clear both cipher and decode */
        decode.clear();
        kdx = 0;            /* reset key index */
    }
}

Example Use/Output

Using the example provided on the Wikipedia page, and forcing the case-consistency, you can encode and decode upper and lower case characters (it's just the same cipher preserving upper/lower case of the original string)

$ echo "ATTACKATDAWN" | ./bin/vigenere
input : ATTACKATDAWN
key   : LEMON
cipher: LXFOPVEFRNHR

$ echo "AttackAtDawn" | ./bin/vigenere lEMoN
input : AttackAtDawn
key   : lEMoN
cipher: LxfopvEfRnhr
decode: AttackAtDawn

$ echo "Attack At Dawn" | ./bin/vigenere lEMoN
error: unsupported char ' ' removing.
error: unsupported char ' ' removing.
input : Attack At Dawn
key   : lEMoN
cipher: LxfopvEfRnhr
decode: AttackAtDawn

Upvotes: 2

solarflare
solarflare

Reputation: 441

You have to use the two sets of letters (upper and lower) back to back to form a longer version of your alphabet and decimate on that. Or alternatively simplify it and just use a single case for your cipher which will work just as fine. You'll just have to make your letters "toUpper" or toLower before parsing through the logic.

Upvotes: 0

jkl0619
jkl0619

Reputation: 37

Well walk through ur code with an example. Lets take the text 'a'. It has a value of 97 according to the ascii table I found. assuming Encrypted[i] == 'a'

I'm also going to assume your DecryptedText is of char types.

int y = (97 - key[i] + 26) % 26
y = y + 97;

I don't know what your key[i] is. Do the math with your key[i] and see if the behavior is expected.

One very simple way to do this esp when you are beginner is to just insert some print statements in there

int y = (97 - key[i] + 26) % 26
std::cout << key[i] << " <-- is the key value;
y = y + 97;
std::cout << y << " <-- resulting y value". 

Upvotes: 0

Related Questions