3

I've tried to create a c++ program which takes some input and encrypts it using a vignere cypher.

my input is:

the swift brown fox jumps over the lazy dog

which, given the key "hello", outputs this:

alpdvpjemqvayqnenfxozsgpqalpwgcozfg

which decrypted, spells out the following:

theshiftbcownfzxjumasovecthelsvkous

a bit over 50% of the cyphering is correct and I have no idea how I've managed to do this.

My code is the following:

#include <iostream>
#include <string>
#include <cstring>
#include <fstream>
#include <sstream>
#include <streambuf>
#include <locale>

class Passcode {
private:
    std::string passcode;
public:
    void set_passcode(const std::string pc){
        passcode = pc;
    }
    char get_char(std::size_t index){ 
        return passcode[index];
    }
    std::size_t get_size(){ 
        return passcode.length();
    }
};

int find_index(char* arr, const std::size_t SIZE, const char flag){
    for(std::size_t i=0; i<SIZE; ++i){
        if (arr[i]==flag) return i;
    }
    return -1;
}

int main() {
  char alphabet[26] = {'a','b','c','d','e','f','g','h',
               'i','j','k','l','m','n','o','p',
               'q','r','s','t','u','v','w','x',
               'y','z'};

  //grab input
  std::ifstream input("input.txt");
  std::stringstream buf;
  buf << input.rdbuf();
  std::string str = buf.str();

  //codify string 
  //no spaces, no caps, etc.
  std::locale loc;
  std::string uncyphered_text;
  for(std::size_t i=0; i<str.length(); ++i){
    if(str[i]!=' ') uncyphered_text+=std::tolower(str[i],loc);
  }

  //grab key
  std::cout << "Enter your passcode: "; 
  std::string in; std::cin >> in;
  Passcode pass; pass.set_passcode(in);

  //encypher text
  std::string encyphered_text;
  for(std::size_t i=1; i<=uncyphered_text.length(); ++i){
    char current_char = pass.get_char(i%pass.get_size()-1);
    int current_char_index = find_index(alphabet, 26, current_char);
    int current_cypher_index = find_index(alphabet, 26, uncyphered_text[i-1]);
    encyphered_text+=alphabet[(current_char_index+current_cypher_index)%26];
  }

  std::cout << encyphered_text << std::endl;

  return 0;
}

I feel like I am probably doing something incorrectly with the modulus operator.

Cœur
  • 32,421
  • 21
  • 173
  • 232
  • 1
    Do you know what the encrypted text *should* be? Are you sure it's a problem in your encryption and not in the decryption? Have you tried stepping through the code line by line in a debugger? – Some programmer dude Jun 22 '16 at 11:00
  • @Joachim Here's how it should look encrypted, proper encryption in caps, my failed attempt in lowercase: (sorry i suck at formatting) ALPDK PJEMF VAYQC ENFXD ZSGPF ALPWO GCOZU alpdv pjemq vayqn enfxo zsgpq alpwg cozfg – Kevin Koehler Jun 22 '16 at 11:02
  • Well, the -1 should not be necessary at least, mod operator results in a value [0..n-1]. Your for loop should start with 0, use < and please use `i++` as `++i` may confuse readers. – Maarten Bodewes Jun 22 '16 at 11:32
  • @MaartenBodewes I feel like a complete idiot, I did your suggestions and now it seems to work! I confused the principle that n%0=undefined with 0%n not being undefined. Thanks so much! – Kevin Koehler Jun 22 '16 at 11:39

1 Answers1

2

Problems: bad use of modulo and bad indexing.

  //encypher text
  std::string encyphered_text;
  for(std::size_t i=0; i<uncyphered_text.length(); ++i){
    char current_char = pass.get_char(i%pass.get_size());
    int current_char_index = find_index(alphabet, 26, current_char);
    int current_cypher_index = find_index(alphabet, 26, uncyphered_text[i]);
    encyphered_text+=alphabet[(current_char_index+current_cypher_index)%26];
  }

That worked for me.

Jean-Baptiste Yunès
  • 30,872
  • 2
  • 40
  • 66