I have implemented XOR encryption algorithm like so:
string XOR(string data, const char* key)
{
string xorstring = data; //initialize new variable for our xordata
for (int i = 0; i < xorstring.length(); i++) { //for loop for scrambling bits in the string
xorstring[i] = data[i] ^ key[i]; //scrambling the string/descrambling it
}
return xorstring;
}
Which works just fine, like: string ciphertext = XOR("test", "1234"); will return the ciphertext and when decrypting:string plaintext = XOR(ciphertext, "1234"); it will return 'test'.
So, I wanted to create an algorithm that would break the xor cipher by brute forcing, so basically trying to decrypt the ciphertext with every possible key combination.
It (should) work like this:
generate strings from an character array of alphabet
xor(decrypt) the given ciphertext with the given string to get plaintext
after that, xor(encrypt) the generated plaintext and compare it in if statement to see if it matches with the original ciphertext
if it matches, the correct key was found to decrypt the ciphertext.
Simple as that, but I found my self struggling with the algorithm:
const char Numbers[11] = "0123456789";
const char AlphabetUpper[27] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const char AlphabetLower[27] = "abcdefghijklmnopqrstuvwxyz";
string XOR(string data, const char* key)
{
string xorstring = data; //initialize new variable for our xordata
for (int i = 0; i < xorstring.length(); i++) { //for loop for scrambling bits in the string
xorstring[i] = data[i] ^ key[i]; //scrambling the string/descrambling it
}
return xorstring;
}
string cipher, plain; //store the ORIGINAL ciphertext and plaintext
int main()
{
plain = "test"; //set the plaintext
cipher = XOR(plain, "1234"); //encrypt it with the xor function
cout << plain << endl; //output
cout << cipher << endl; //output
cout << "press enter to start bruteforcing!" << endl;
getchar();
while (true) //loop for bruteforcing
{
static int stringlength = 1; //the keylength starts from 1 and then
//expands to 2,3,4,5, etc...
BruteForce(stringlength, cipher, ""); //call the brute force function
stringlength++; //increment the keylength
}
return 0;
}
void BruteForce(int length, string ciphertext, string tempKey)
{
static int count = 0; // for counting how many times key was generated
string decipher, recipher; //for storing new XORed strings.
if (length == 0)
{
//decrypt the given ciphertext with the random key
decipher = XOR(ciphertext, tempKey.c_str());
//encrypt it again with the same key for comparison
recipher = XOR(decipher, tempKey.c_str());
cout << deciphered << endl; //output
//compare the two ciphertexts
if (ciphertext == recipher)
{
//....
cout << "Key found! It was: '" << tempKey << "'" << endl;
cout << "it took " << count << " iterations to find the key!";
getchar();
}
return;
}
count++;
//generate the keys.
for (int i = 0; i < 26; i++) {
std::string appended = tempKey + AlphabetLower[i];
BruteForce(length - 1, ciphertext, appended);
}
for (int i = 0; i < 26; i++) {
std::string appended = tempKey + AlphabetUpper[i];
BruteForce(length - 1, ciphertext, appended);
}
for (int i = 0; i < 10; i++) {
std::string appended = tempKey + Numbers[i];
BruteForce(length - 1, ciphertext, appended);
}
}
The algorithm does not work, for an unknown reason.
Very bizarre, in theory it should work. When the program is ran, it says the key was found on every execution of the bruteforce() function. Try it your self.
Could someone point out that what I am doing wrong here? Help is appreciated. Thanks.
It doesn't work because your task is impossible. The one time pad (xor) has a property known as perfect secrecy which means your cipher text can be decrypted to any plain text with equal probability. So it's impossible to know which plain text was the original.
For your scheme specifically (message XOR key) XOR key is always just the message back again.
This is the property of XOR operations: for every key you would find that
message XOR key XOR key == message
So your way to check that key is correct will indeed return all possible keys.
Moreover, say you have an encrypted message E. Then, for any possible plain text message M you will always find a key K so that
E = M xor K
(though such K can contain arbitrary chars, not just letters etc.) Therefore if you allow arbitrary chars in K, then the cypher is unbreakable even in theory (see one-time pad).
In case you allow only letters and digits in K, not every plain-text message can be received from a given encrypted message. However, you will need some more information on what the plain text could have been to detect "true" message from wrong ones (for example, knowing that plain text contains only letters, or that it is a valid English text, etc.), and you will need to check for this in your code. Anyway, I guess that you will get many possible plain texts even with this additional heuristics.
Related
I'm working on this assignment where I'm taking a user input string, a key of the same or greater length, and using that to perform a Running Key cipher to encrypt and decrypt the text. Encryption is working, but decryption is not.
Looking manually at the Running Key table, I found that "ice" with a key of "did" would encrypt to "lkh" and that checks out. Looking back at the table, I found that for "lkh" to be turned into "ice", the key would have to change to "xsx" and for a moment, thought it'd be easy because I mistakenly thought it was "sxs" which is "did" with each letter shifted forward 15 letters. It's actually more arbitrary than that with the "d"'s shifting 20 letters and the "i" shifting only 10 letters to make "xsx".
I'm not sure what to put in my decrypt(), getDecryptedText(), or decryptionKey() functions to make this work, or if I was even on the right track trying to shift the letters. I imagine I must be, but my current thinking is that it may take some sort of loop to determine how many letters each character in the key should shift forward to.
#include <iostream>
#include <bits/stdc++.h>
#include <algorithm>
#include <cctype>
// Running Key Cipher Explanation
// http://practicalcryptography.com/ciphers/classical-era/running-key/
void encrypt(std::string&, std::string&, std::string&);
void decrypt(std::string&, std::string&, std::string&);
char getEncryptedText(char p, char k);
char getDecryptedText(char p, char k);
std::string decryptionKey(std::string&);
void getKeyIndex(int &i, std::string &key);
int main() {
// Initialization
std::string input;
std::string key;
std::string encryptedText;
std::string decryptedText;
// Assignment
std::cout << "Enter secret message: ";
std::getline(std::cin, input);
std::cout << "Enter key (longer than message): ";
std::getline(std::cin, key);
// Remove spaces
input.erase(remove_if(input.begin(), input.end(), isspace), input.end());
key.erase(remove_if(key.begin(), key.end(), isspace), key.end());
// Exit if key length < secret text
if (key.length() < input.length()) {
std::cout << "The encryption key must be longer than the message."
<< std::endl;
return 1;
}
// Encrypt the text
encrypt(input, key, encryptedText);
// Display encrypted text to user
std::cout << "\nThe encrypted text is:" << std::endl;
std::cout << encryptedText << std::endl;
// Decrypt the text
decrypt(encryptedText, key, decryptedText);
// Display decrypted text to user
std::cout << "\nThe decrypted text is:" << std::endl;
std::cout << decryptedText << std::endl;
return 0;
}
void encrypt(std::string &input, std::string &key, std::string &encryptedText) {
std::string::iterator i;
std::string::iterator j;
// Contains the encrypted version of the text
encryptedText = "";
// Encrypt every character in the input string
for(i = key.begin(), j = input.begin(); j < input.end();) {
// Remove non-letters from text
if (!isalpha(*j)) {
j++;
continue;
}
// get encrypted char
encryptedText += getEncryptedText(tolower(*j),tolower(*i));
i++;
j++;
}
}
char getEncryptedText(char p, char k) {
// Number to be converted into the nth letter in the alphabet
int encryptedText;
encryptedText = p + k;
if (encryptedText >= 219) {
return (char) (encryptedText - 123);
}
return (char)(encryptedText - 97);
}
void decrypt(std::string &encryptedText, std::string &key, std::string &decryptedText) {
std::string::iterator i;
std::string::iterator j;
// Contains the decrypted version of the text
decryptedText = "";
// Change key to decrypt
key = decryptionKey(key);
// Decrypt every character in the input string
for(i = key.begin(), j = encryptedText.begin(); j < encryptedText.end();) {
// get decrypted char
decryptedText += getDecryptedText(tolower(*j),tolower(*i));
i++;
j++;
}
}
char getDecryptedText(char p, char k) {
// Number to be converted into the nth letter in the alphabet
int decryptedText;
decryptedText = p + k;
// If it gets passed z, go back to a
if (decryptedText >= 219) {
return (char) (decryptedText - 123);
}
return (char)(decryptedText - 98);
}
std::string decryptionKey(std::string &key) {
for (int i = 0; i < key.length(); i++) {
// Store integer ASCII value of char
int asc = key[i];
int rem = asc - (26 - (key[i] - 'a'));
int m = rem % 26;
key[i] = (char)(key[i] + 15);
}
// Decryption Key cout for testing
std::cout << "Altered key: " << key;
return key;
}
getEncryptedText can be simplified to:
char getEncryptedText( char p, char k )
{
return ( ( p - 'a' ) + ( k - 'a' ) ) % 26 + 'a';
}
I've replaced magic numbers with the actual character values to make the code easier to read.
If we make sure that getDecryptedText is the exact reverse of getEncryptedText there is no need to modify the key.
char getDecryptedText( char p, char k )
{
return ( ( p - 'a' ) - ( k - 'a' ) + 26 ) % 26 + 'a';
}
The +26 is a fiddle to make sure the value is positive as the modulo won't produce the correct result for negative numbers.
I have a trouble with this. I writing a code for the "vigenere cipher".
I have text and key. But i want to get alphabet from the user. what the user wants etc:"abcdfgh" or "sdgfjdgkfdsgs" just what the user wants.
So but i can't do it.
How do I get alphabet from the user?
Firstly, i want to do get alphabet from the user.
After, I want it to enter the word and encrypt it. But the words alphabet is user's alphabet.
Here is the codes:
#include <iostream>
#include <string>
using namespace std;
// Bu fonksiyon bir key oluşturur.
string generateKey(string str, string key)
{
int x = str.size();
for (int i = 0; ; i++)
{
if (x == i)
i = 0;
if (key.size() == str.size()) // eğer oluşturulan key boyutu girilen
metnin boyutuna eşitse fonksiyonu durdur.
break;
key.push_back(key[i]);
}
return key;
}
string cipherText(string str, string key) // "/Bu fonksiyon orjinal metni şifreler \"
{
string cipher_text;
for (int i = 0; i < str.size(); i++)
{
// converting in range 0-25
int x = (str[i] + key[i]) % 26;
// alfabeyi ASCII kodlarina dönüştür:
x += 'A';
cipher_text.push_back(x);
}
return cipher_text;
}
// "/Bu fonksiyon şifreli metni orjinal hale getirir\"
string originalText(string cipher_text, string key)
{
string orig_text;
for (int i = 0; i < cipher_text.size(); i++)
{
// converting in range 0-25
int x = (cipher_text[i] - key[i] + 26) % 26;
// convert into alphabets(ASCII)
x += 'A';
orig_text.push_back(x);
}
return orig_text;
}
int main()
{
cout << " Sifrelenmesini istediginiz kelimeyi/cumleyi giriniz" << endl;
string str;
getline(cin, str);
//string str = "METINBUGRA";
cout << "Anahtar kelimeyi giriniz." << endl;
string keyword;
getline(cin, keyword);
//string keyword = "ABC";
string key = generateKey(str, keyword);
string cipher_text = cipherText(str, key);
cout << "Sifrelenmis Kelime : "
<< cipher_text << "\n";
cout << "Cozumlenmis kelime : "
<< originalText(cipher_text, key);
system("pause");
return 0;
}
If I correctly understood your question, you want to use a custom alphabet instead of English alphabet. For instance you may add digits.
Instead of actual letters you must operate on numbers: 0, 1, 2, ... N-1, where N is the size of the alphabet. For English alphabet this means you must use 0 instead of A (0x41), 1 instead of B (0x42), ... 25 instead of Z.
If the size of the key is M, the encryption algorithm for letter at position i is:
( L[i] + K[i mod M] ) mod N
Once you have a functional algorithm that operates on numbers, all you have to do is map your input from letters to numbers and your output from numbers to letters.
Mapping numbers to letters is easy; you just have to store the alphabet into a string – this answers your question:
string n_to_letter; // alphabet
//...
int main()
{
//...
cin >> n_to_letter; // read the alphabet
//...
Mapping letters to numbers is probably beyond your current knowledge; you must use a map:
#include <map>
//...
string n_to_letter; // alphabet
map< char, int > letter_to_n;
void init_letter_to_n() //...
If you do not know how to use a map, there is a workaround: just search for the letter in the alphabet string, or use a 256 characters vector/string.
DEMO
I am trying to convert a string to uppercase so I can manipulate it, but while I can successfully manipulate natural uppercase strings, as well as convert lowercase to uppercase, using this method of conversion fails to allow the manipulation.
For example, if I pass "hello" through the encryption, my encrypted string becomes "HELLO", but when I pass "HELLO" through (naturally capitalized), it correctly shifts.
Is there a different way of forcing uppercase that I need to be using or am I doing something wrong?
int Caesar::encrypt (const std::string &message, std::string &emessage) {
int count = 0;
emessage = message;
std::transform(emessage.begin(), emessage.end(), emessage.begin(), ::toupper);
for (std::string::size_type i = 0; i < message.size(); i++) {
for (int j = 0; j < 26; j++) {
if (emessage[i] == std_alphabet[j]) {
std::replace(emessage.begin(), emessage.end(), message[i], c_alphabet[j]);
}
}
count++;
}
return count;
}
constructor:
Caesar::Caesar (int shift) {
// loop to populate vector with 26 letters of English alphabet
// using ASCII uppcase letter codes
for (int i = 0; i < 26; i++) {
std_alphabet.push_back(i + 65);
}
// fills Caesar alphabet with standard generated alphabet
c_alphabet = std_alphabet;
// shifts Caesar alphabet based off the constructor parameter
std::rotate(c_alphabet.begin(), c_alphabet.begin() + shift, c_alphabet.end());
}
test file:
void testCaesar() {
Caesar test(4);
std::string original = "HELLO";
std::string encrypted = "";
test.encrypt(original,encrypted);
std::cout << encrypted << std::endl;
std::cout << original << std::endl;
}
int main() {
testCaesar();
return 0;
}
Obviously there is a header and includes and stuff but that is the basic code
the header file includes the two private vectors
The specific issue you are seeing is that you're replacing the wrong thing here:
std::replace(emessage.begin(), emessage.end(), message[i], c_alphabet[j]);
If message was lowercase, then emessage will be all upper-case letters - none of which will be message[i]. so that replacement won't do anything. You meant:
std::replace(emessage.begin(), emessage.end(), emessage[i], c_alphabet[j]);
^^^^^^^^^^^
That said, your algorithm is totally wrong as HELLO encrypts as BCBBA with a shift of 4. There is a 1-1 mapping on letters, so H and L cannot both go to B. What you want to do is shift each letter as you go by just replacing it with what its next letter should be. That is:
for (std::string::size_type i = 0; i < emessage.size(); ++i) {
emessage[i] = c_alphabet[emessage[i] - 'A'];
}
With which you don't actually need the initial transformation step:
emessage = message;
for (std::string::size_type i = 0; i < emessage.size(); ++i) {
emessage[i] = c_alphabet[::toupper(emessage[i]) - 'A'];
}
The whole thing can be abridged quite a bit by just dropping your count (which is just the size anyway, so is redundant) and taking the message by-value:
std::string encrypt(std::string from) { // intentionally copying
for (char& c : from) {
c = c_alphabet[::toupper(c) - 'A'];
}
return from;
}
Basically, the (Vigenere) decryption works perfectly except for not including the final letter for the decryption. For instance, the decryption for m_text yields 48 letters instead of 49. I even tried to manipulate the loop but it doesn't work out well since i will get a out of range exception with .at(). Any help would be appreciated!
using namespace std;
#include <string>
#include <iostream>
int main()
{
string ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
string m_text = "ZOWDLTRTNENMGONMPAPXVUXADRIXUBJMWEWYDSYXUSYKRNLXU";
int length = m_text.length();
string key = "DA";
string plainText = "";
int shift = 0;
int shift2 = 0;
//Loop that decrypts
for (int k = 0; k < length-1; k+=2)
{
//Key 1 shift
shift = m_text.at(k) - key.at(0);
//Key 2 shift
shift2 = m_text.at(k+1) - key.at(1);
if (shift >= 0)
{
plainText += ALPHABET.at(shift);
}
else
{
shift += 91;
plainText += (char)shift;
}
if (shift2 >= 0)
{
plainText += ALPHABET.at(shift2);
}
else
{
shift2 += 91;
plainText += (char)shift2;
}
}
cout << plainText << endl;
}
By the looks of things, you are decoding two characters at a time. So when you have 49 characters in your string, there is one left over (which doesn't get processed). If you make m_text 48 characters long, you will notice you get the correct result.
It might be easier to replicate your key to match the length of the message, then do character-by-character decoding.
I'm trying to implement an algorithm which will guess at a likely key length of a keyword of a vigenere cipher.
I'm going about the steps of finding the index of coincidence for each possible key length, but I can't figure out a way to split the cipher text into the substrings.
That is, I'm trying to take a certain cipher text like this
ERTEQSDFPQKCJAORIJARTARTAAFIHGNAPROEOHAGJEOIHJA (this is random text, there's no coded message here)
and split it up into different strings like this:
key length 2: ETQDP... (every second letter starting from position 0)
RESFQ... (every second letter starting from position 1)
key length 3: EEDQ.... (every third letter starting from position 0)
and so on.
Any ideas?
UPDATE
I've tried implementing my own code now, and here's what I've done:
void findKeyLength(string textToTest)
{
size_t length = textToTest.length();
vector<char> vectorTextChar;
//keeping key length to half the size of ciphertext; should be reasonable
for (size_t keylength = 1; keylength < length / 2; keylength++)
{
for (size_t i = keylength; i < keylength ; i++)
{
string subString = "";
for (size_t k = i; k < length; k+=i)
{
vectorTextChar.push_back(textToTest[k]);
}
for (vector<char>::iterator it= vectorTextChar.begin(); it!=vectorTextChar.end(); ++it)
{
subString += *it;
}
cout << subString << endl; //just to see what it looks like
cout << "Key Length : " << keylength << "IC: " << indexOfCoincidence(subString) << endl;
vectorTextChar.clear();
}
}
}
Like I've mentioned below, I'll have output which only reflects the substring that is based
on the first characters (i.e. 1, 3, 5, 7, 9 if the keylength is 2, but not 2, 4, 6, 8, 10...)
Not tested, but you could do something like this:
int len = cipherText.length;
char[] text2inspect = char[(len/keyLength) + 1]
for (int startIndex = 0; keyLength > startIndex; startIndex++){
int destIndex = 0;
for (int index = startIndex; len > index; index += keyLength){
text2inspect[destIndex++] = cipherText[index];
}
text2inspect[destIndex] = 0; // String termination
// add your inspection code here
}