Issues with Caesar Cipher not decrypting correctly in C++ - c++

I am aware that this question has been asked a few times, and I may have missed the question that answers my specific problem however I cannot seem to find one that gives me an answer that works for me.
When I am decrypting a Caesar Cipher it doesn't seem to wrap around correctly, my code seems to follow the specific mathmatics for the caesar cipher but it seems to return junk output when it's supposed to wrap around. My code is as follows, including a system I used to test the problem.
#include "main.h"
#include <QCoreApplication>
#include <QDebug>
String caesarCipher(QString in, int shift, bool decrypt)
/*
* Caesar shift is mathmatically represented as e = (q + s) mod 26
* Decryption is represented as d = (q - s) mod 26
* ROT13 is a caesar shift with 13 shift
*/
{
QString out;
if (!decrypt)
{
for (int i = 0; i < in.length(); ++i)
{
if (in[i] >= 'a' && in[i] <= 'z')
{
int q = (in[i].unicode() - 'a');
int e = (q + shift) % 26;
out += e + 'a';
}
else if (in[i] >= 'A' && in[i] <= 'Z')
{
int q = (in[i].unicode() - 'A');
int e = (q + shift) % 26;
out += e + 'A';
}
else
out += in[i];
}
return out;
}
else
{
for (int i = 0; i < in.length(); ++i)
{
if (in[i] >= 'a' && in[i] <= 'z')
{
int q = (in[i].unicode() - 'a');
int d = (q - shift) % 26;
int r = d + 'a';
out += r;
}
else if (in[i] >= 'A' && in[i] <= 'Z')
{
int q = (in[i].unicode() - 'A');
int d = (q - shift) % 26;
int r = d + 'A';
out += r;
}
else
out += in[i];
}
return out;
}
}
int main() // Testing
{
QString testString = "abcdefghijklmnopqrstuvwxyz";
QString upperTest = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const int shifting = 3;
qDebug() << "Test String: " << testString;
qDebug() << "Test String (Upper): " << upperTest;
{
QString e = caesarCipher(testString, shifting, false);
QString E = caesarCipher(upperTest, shifting, false);
QString d = caesarCipher(e, shifting, true);
QString D = caesarCipher(E, shifting, true);
qDebug() << "Shift amount: " << shifting;
qDebug() << "Encrypt (Lower): " << e;
qDebug() << "Encrypt (Upper): " << E;
qDebug() << "Decrypt (Lower): " << d;
qDebug() << "Decrypt (Upper): " << D;
}
return 0;
}
The expected result is
Test String: "abcdefghijklmnopqrstuvwxyz"
Test String (Upper): "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
Shift amount: 3
Encrypt (Lower): "defghijklmnopqrstuvwxyzabc"
Encrypt (Upper): "DEFGHIJKLMNOPQRSTUVWXYZABC"
Decrypt (Lower): "abcdefghijklmnopqrstuvwxyz"
Decrypt (Upper): "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
Press <RETURN> to close this window...
The result I get:
Test String: "abcdefghijklmnopqrstuvwxyz"
Test String (Upper): "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
Shift amount: 3
Encrypt (Lower): "defghijklmnopqrstuvwxyzabc"
Encrypt (Upper): "DEFGHIJKLMNOPQRSTUVWXYZABC"
Decrypt (Lower): "abcdefghijklmnopqrstuvw^_`"
Decrypt (Upper): "ABCDEFGHIJKLMNOPQRSTUVW>?#"
Press <RETURN> to close this window...
I have tried to move code around, change where the shift is removed, where the modulo is done and where the 'a' character is added
For reference the code was initially before I altered it for readability:
for (int i = 0; i < in.length(); ++i)
{
if (in[i] >= 'a' && in[i] <= 'z')
out.resultString += (((in[i].unicode() - 'a') - shift) % m) + 'a';
else if (in[i] >= 'A' && in[i] <= 'Z')
out.resultString += (((in[i].unicode() - 'A') - shift) % m) + 'A';
else
out.resultString += in[i];
}

The % operator can return negative results when used with negative numbers. In your case, when decrypting an 'a', q will be 0, d will be (-3 % 26), which can be -3.
The solution is to ensure the number is positive before calculating the remainder:
int d = (q - shift + 26) % 26;
Or, if the shift amount is unknown, or can be more than 25, check if d is negative and add 26 to it after your initial calculation.

Related

Affine cipher decryption, output differs for upper case and lower case

I have the problem when decrypting a plaintext using Affine cipher.
Encryption works fine, but applying the same logic for decryption of lower case/upper case characters returns different output.
Here is the output:
Encrypted Message is : ulctkbsjarizqhypgxofwnevmd ULCTKBSJARIZQHYPGXOFWNEVMD
Decrypted Message is: opqrstuvwxyzabcdefghijklmn ABCDEFGHIJKLMNOPQRSTUVWXYZ
I suspect it has something to do with retrieving of ASCII values, can someone correct me?
Here is my code:
#include<bits/stdc++.h>
using namespace std;
//Key values of a and b
const int a = 17;
const int b = 20;
string encryptMessage(string plainText)
{
string cipher = "";
for (int i = 0; i < plainText.length(); i++)
{
if(plainText[i]!=' ')
{
if ((plainText[i] >= 'a' && plainText[i] <= 'z') || (plainText[i] >= 'A' && plainText[i] <= 'Z'))
{
if (plainText[i] >= 'a' && plainText[i] <= 'z')
{
cipher = cipher + (char) ((((a * (plainText[i]-'a') ) + b) % 26) + 'a');
}
else if (plainText[i] >= 'A' && plainText[i] <= 'Z')
{
cipher = cipher + (char) ((((a * (plainText[i]-'A') ) + b) % 26) + 'A');
}
}
else
{
cipher += plainText[i];
}
}
else
{
cipher += plainText[i];
}
}
return cipher;
}
string decryptCipher(string cipher)
{
string plainText = "";
int aInverse = 0;
int flag = 0;
for (int i = 0; i < 26; i++)
{
flag = (a * i) % 26;
if (flag == 1)
{
aInverse = i;
}
}
for (int i = 0; i < cipher.length(); i++)
{
if(cipher[i] != ' ')
{
if ((cipher[i] >= 'a' && cipher[i] <= 'z') || (cipher[i] >= 'A' && cipher[i] <= 'Z'))
{
if (cipher[i] >= 'a' && cipher[i] <= 'z')
{
plainText = plainText + (char) ((((aInverse * (cipher[i]+ 'a') ) - b) % 26) + 'a');
}
else if (cipher[i] >= 'A' && cipher[i] <= 'Z')
{
plainText = plainText + (char) (((aInverse * ((cipher[i]+'A' - b)) % 26)) + 'A');
}
}
else
{
plainText += cipher[i];
}
}
else
plainText += cipher[i];
}
return plainText;
}
//Driver Program
int main(void)
{
string msg = "abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ";
//Calling encryption function
string cipherText = encryptMessage(msg);
cout << "Encrypted Message is : " << cipherText<<endl;
//Calling Decryption function
cout << "Decrypted Message is: " << decryptCipher(cipherText);
return 0;
}
I have been thinking about this for some time and, although I can't provide a complete explanation, I have a couple of 'observations' that may be useful, plus a 'cheat' workaround.
First, although you say you use "the same logic for decryption of lower case/upper case," a character-wise alignment of the code from each of your decryption blocks shows that this isn't quite true:
plainText = plainText + (char) ((((aInverse * (cipher[i]+ 'a') ) - b) % 26) + 'a'); // Lower case
plainText = plainText + (char) (((aInverse * ((cipher[i]+'A' - b)) % 26)) + 'A'); // Upper case
So, 'fixing' the lower case code to be exactly analogous to the (working) code for upper case (and removing redundant parentheses) gives this:
if (cipher[i] >= 'a' && cipher[i] <= 'z')
{
plainText = plainText + (char)( ( (aInverse * (cipher[i] + 'a' - b) ) % 26 ) + 'a' );
}
else if (cipher[i] >= 'A' && cipher[i] <= 'Z')
{
plainText = plainText + (char)( ( (aInverse * (cipher[i] + 'A' - b) ) % 26 ) + 'A' );
}
However, this doesn't actually resolve the issue (it just changes it slightly), as the output then is as follows:
Encrypted Message is : ulctkbsjarizqhypgxofwnevmd ULCTKBSJARIZQHYPGXOFWNEVMD
Decrypted Message is : qrstuvwxyzabcdefghijklmnop ABCDEFGHIJKLMNOPQRSTUVWXYZ
The problem here is that the lowercase values are all 'rotated' by the value 16 - which looks suspiciously close to the value for a. Also, note that, although a is used in the encryption formula, it is not used in your decryption.
So, I have come up with the following workaround, assuming that (for reasons yet to be deduced) when decoding upper case values, this 16 is somehow lost in the bit-representation of the ASCII values:
if ((cipher[i] >= 'a' && cipher[i] <= 'z') || (cipher[i] >= 'A' && cipher[i] <= 'Z'))
{
int offset = ((cipher[i] - 'A') / 26) ? a - 1 : 0;
if (cipher[i] >= 'a' && cipher[i] <= 'z') {
plainText = plainText + (char)( ( (aInverse * (cipher[i] + 'a' - b) - offset ) % 26 ) + 'a' );
}
else if (cipher[i] >= 'A' && cipher[i] <= 'Z') {
plainText = plainText + (char)( ( (aInverse * (cipher[i] + 'A' - b) - offset ) % 26 ) + 'A' );
}
}
Note that your code can be further simplified/clarified using functions provided by the standard library and removing some 'redundant' checks:
for (int i = 0; i < cipher.length(); i++) {
if (isalpha(cipher[i])) {
int offset = islower(cipher[i]) ? a - 1 : 0;
int letter = islower(cipher[i]) ? 'a' : 'A';
plainText = plainText + (char)(((aInverse * (cipher[i] + letter - b) - offset) % 26) + letter);
}
else {
plainText += cipher[i];
}
}

How to cyclically increment and decrement 26 latin characters in a loop

I want to increment or decrement characters, but have them cycle back to a when going beyond z and to z when going before a.
For example incrementing 'w' by 2 gives 'y' and decrementing 'w' by 2 gives 'u'.
Another example decrementing 'w' by 28 gives 'u' and decrementing 'a' by 256 gives 'e'.
I've figure out how to increment: char(int(A[i]+B-97)%26 +97) where B is the shift amount and A[i] is current character.
Don't overcomplicate. Use modulo to keep the increment or decrement amount in a range of 26 characters, then simply do a range check:
char cyclicIncrementDecrement(char ch, int amount)
{
int newValue = int(ch) + (amount % 26);
if (newValue < 'a') newValue += 26;
if (newValue > 'z') newValue -= 26;
return char(newValue);
}
This method of course assumes ch already is in range of 'a' to 'z'. If not, you need to handle that (put it in range or throw an exception or whatever is appropriate for your application).
Running this:
int main()
{
std::cout << cyclicIncrementDecrement('w', -2) << std::endl;
std::cout << cyclicIncrementDecrement('w', 2) << std::endl;
std::cout << cyclicIncrementDecrement('w', -28) << std::endl;
std::cout << cyclicIncrementDecrement('a', -256) << std::endl;
std::cout << cyclicIncrementDecrement('z', -256) << std::endl;
std::cout << cyclicIncrementDecrement('z', -51) << std::endl;
std::cout << cyclicIncrementDecrement('z', -52) << std::endl;
}
gives:
u
y
u
e
d
a
z
Using modular arithmetic, calculate your answer as modulo 26 and then add 'a' (ASCII 97) to your result.
char cyclic_increment(char ch, int n) {
int tmp = ((ch - 97) + n) % 26;
if (tmp < 0 )
tmp += 26;
return (char)(tmp + 97);
}
Alternatively, you could write the above (without an if) as:
char cyclic_increment(char ch, int n) {
return (((ch - 'a') + n) % 26 + 26) % 26 + 'a';
}
This handles both positive and negative offsets:
unsigned char az_cyclic(int in_ch)
{
constexpr int mod = 26; // There are 26 letters in the English alphabet
int offset = (in_ch - 'a') % mod; // (ASCII To zero-based offset) Mod_26 remainder
if (offset < 0) // If negative offset,
offset += mod; // normalize to positive. For example: -1 to 25
return 'a' + offset; // Normalize to ASCII
}
Use-cases:
int main()
{
unsigned char out_ch = '\0';
out_ch = az_cyclic('a' - 1); // 'z'
out_ch = az_cyclic('a' - 1 - 26); // 'z'
out_ch = az_cyclic('a' - 2); // 'y'
out_ch = az_cyclic('a' + 4); // 'e'
out_ch = az_cyclic('a' + 4 + 26); // 'e'
out_ch = az_cyclic('a' + 2); // 'c'
return 0;
}

Caesar cipher : how to calculate with shifting value > 10 ( or larger )?

As i know , the " formula " of Caesar Shifting is (x + k ) % 26 , where k is the shifting value and decryption just replace " + " to " - ".
but my code does not work when k > 10 (after i tested k = 10 , i find that the "shift" of the first few characters is wrong, so I estimate that k > 10 will be wrong (the number of incorrect characters increase) as well. ). I first change the characters to ASCII and then do the calculation. Finally change it back to characters.
Here are my code.
#include <iostream>
#include <string>
using namespace std;
int main() {
string target;
char s;
int k, i, num, length, j;
cin >> s >> k;
getline(cin, target);
for (j = 0; j <= (int)target.length(); j++) {
if ((target[j]) = ' ') {
target.erase(j, 1);
}
}
length = (int)target.length();
if (s == 'e') {
for (num = 0; num <= length; num++) {
if (isupper(target[num]))
target[num] = tolower(char(int(target[num] + k - 65) % 26 + 65));
else if (islower(target[num]))
target[num] = toupper(char(int(target[num] + k - 97) % 26 + 97));
}
}
else if (s == 'd') {
for (num = 0; num <= length; num++) {
if (isupper(target[num]))
target[num] = tolower(char(int(target[num] - k - 65) % 26 + 65));
else if (islower(target[num]))
target[num] = toupper(char(int(target[num] - k - 97) % 26 + 97));
}
}
cout << target;
return 0;
}
Let me put down the case which i failed to run.
input:
d 10 n 3 V 3 D 3 N _ M Y N 3 _ S C _ N 3 L E ( input d / e first, then shifting value, finally the sequence of string require to " change ", the space is required to delete. )
the expected output:
D3l3t3d_cod3_is_d3bu
my output:
D3l3:3d_cod3_i9_d3b;
Thanks!
Your issue is that when decoding you end up with negative numbers. With k == 13 the expression 'T' - k - 65 gives -7. -7 % 26 is still -7. -7+65 is 58 which isn't a letter.
You can avoid negative numbers by simply setting k to 26 - k when decoding.
Your code then simplifies to:
if (s == 'd') {
k = 26 - k;
}
for (num = 0; num <= length; num++) {
if (isupper(target[num]))
target[num] = tolower(char(int(target[num] + k - 'A') % 26 + 'A'));
else if (islower(target[num]))
target[num] = toupper(char(int(target[num] + k - 'a') % 26 + 'a'));
}
Note I've replaced your integer constants with their equivalent characters which makes the code much easier to understand.
Note you also have a bug in your first loop (target[j]) = ' ' should be (target[j]) == ' '.
Using all c++ has to offer you can reduce your code to:
#include <iostream>
#include <string>
#include <algorithm>
int main() {
std::string target = "mXLM";
char s = 'e';
int k = 7;
target.erase(std::remove(target.begin(), target.end(), ' '), target.end());
if (s == 'd') {
k = 26 - k;
}
std::string result;
std::transform(target.begin(), target.end(), std::back_inserter(result), [k](char in) {
if (isalpha(in)) {
char inputOffset = isupper(in) ? 'A' : 'a';
char outputOffset = isupper(in) ? 'a' : 'A';
return char(int(in + k - inputOffset) % 26 + outputOffset);
}
return in;
});
std::cout << result;
return 0;
}

Renaming filenames in two directories IF certain characters between them match - vector subscript out of range

My first job as an intern was to write a program to compare certain characters in the filenames of two different directories, and if they match, rename them. I wrote a custom code to match the characters. The initial few files get renamed in both directories, but it breaks after a point, giving a vector subscript out of range error.
I have an idea of how to fix such a vector range error from all the other posts, but nothing seemed to work. Any input would be appreciated!
PS: I am not a coder and this is my third official program. I understand the code is a bit messy.
Here is the code:
#include<dirent.h>
#include<vector>
#include<sstream>
int main()
{
cout << "Comparer - Renamer v.0.1.beta\n\n";
string dr1, dr2;
int x, y;
DIR *d1;
struct dirent *dir1;
vector<string> a;
a.reserve(25000);
int i = 0;
cout << "Enter the first directory (format : log_2017...) : ";
cin >> dr1;
d1 = opendir(dr1.c_str());
if (d1){
while ((dir1 = readdir(d1)) != NULL){
i++;
a.push_back(dir1->d_name);
}
closedir(d1);
}
x = a.size();
cout << "\nEnter the second directory (format : 2017.12...) : ";
cin >> dr2;
DIR *d2;
struct dirent *dir2;
vector<string> b;
b.reserve(25000);
int j = 0;
d2 = opendir(dr2.c_str());
if (d2){
while ((dir2 = readdir(d2)) != NULL){
j++;
b.push_back(dir2->d_name);
}
closedir(d2);
}
y = b.size();
ostringstream osa, nsa, osb, nsb;
string oldname_a, newname_a, oldname_b, newname_b;
int u, v, w;
for (int l = 2; l < x; l++){
for (int k = l; k < y; k++){
int c = a[l][20] * 10 + a[l][21];
int d = b[k][14] * 10 + b[k][15];
int e = a[l][17] * 10 + a[l][18];
int f = b[k][11] * 10 + b[k][12];
if (a[l][4] == b[k][0] && a[l][5] == b[k][1] && a[l][6] == b[k][2] && a[l][7] == b[k][3] && a[l][9] == b[k][5] && a[l][10] == b[k][6] && a[l][12] == b[k][8] && a[l][13] == b[k][9]){
u = 0;
}
else{
u = 1;
}
if ((e - f) == 0 && abs(c - d) < 12){
v = 0;
}
else{
v = 1;
}
if ((e - f) == 1 && ((c == 58) || (c == 59) || (c == 0) || (c == 1) || (c == 2))){
w = 0;
}
else{
w = 1;
}
if (u == 0 && (v == 0 || w == 0)){
osa.str(string());
osa << dr1 << "\\" << a[l];
nsa.str(string());
nsa << dr1 << "\\" << l - 1 << ". " << a[l];
oldname_a = osa.str();
newname_a = nsa.str();
osb.str(string());
osb << dr2 << "\\" << b[k];
nsb.str(string());
nsb << dr2 << "\\" << l - 1 << ". " << b[k];
oldname_b = osb.str();
newname_b = nsb.str();
rename(oldname_a.c_str(), newname_a.c_str())
rename(oldname_b.c_str(), newname_b.c_str())
break;
}
}
}
return 0;
}
Presently the code is set such that it shows me how the comparison between the filenames is made.
It turns out I was not debugging properly, and the problem was in this part of the code:
int c = a[l][20] * 10 + a[l][21];
int d = b[k][14] * 10 + b[k][15];
int e = a[l][17] * 10 + a[l][18];
int f = b[k][11] * 10 + b[k][12];
I did not know that I couldn't assign an integer from a string/char directly to an int. I converted the char to int (which would give me the ASCII value of the char) and then subtracted it by 48 to convert it to decimal (I do not know if there is an easier way to do this, but this seemed to have worked for me!) The modified part looks like this:
c = ((int)a[l][20] - 48) * 10 + ((int)a[l][21] - 48);
d = ((int)b[k][14] - 48) * 10 + ((int)b[k][15] - 48);
e = ((int)a[l][17] - 48) * 10 + ((int)a[l][18] - 48):
f = ((int)b[k][11] - 48) * 10 + ((int)b[k][12] - 48);
There was also a small manual error in the conditions, which I also rectified.

CString Hex value conversion to Byte Array

I have been trying to carry out a conversion from CString that contains Hex string to a Byte array and have been
unsuccessful so far. I have looked on forums and none of them seem to help so far. Is there a function with just a few
lines of code to do this conversion?
My code:
BYTE abyData[8]; // BYTE = unsigned char
CString sByte = "0E00000000000400";
Expecting:
abyData[0] = 0x0E;
abyData[6] = 0x04; // etc.
You can simply gobble up two characters at a time:
unsigned int value(char c)
{
if (c >= '0' && c <= '9') { return c - '0'; }
if (c >= 'A' && c <= 'F') { return c - 'A' + 10; }
if (c >= 'a' && c <= 'f') { return c - 'a' + 10; }
return -1; // Error!
}
for (unsigned int i = 0; i != 8; ++i)
{
abyData[i] = value(sByte[2 * i]) * 16 + value(sByte[2 * i + 1]);
}
Of course 8 should be the size of your array, and you should ensure that the string is precisely twice as long. A checking version of this would make sure that each character is a valid hex digit and signal some type of error if that isn't the case.
How about something like this:
for (int i = 0; i < sizeof(abyData) && (i * 2) < sByte.GetLength(); i++)
{
char ch1 = sByte[i * 2];
char ch2 = sByte[i * 2 + 1];
int value = 0;
if (std::isdigit(ch1))
value += ch1 - '0';
else
value += (std::tolower(ch1) - 'a') + 10;
// That was the four high bits, so make them that
value <<= 4;
if (std::isdigit(ch2))
value += ch1 - '0';
else
value += (std::tolower(ch1) - 'a') + 10;
abyData[i] = value;
}
Note: The code above is not tested.
You could:
#include <stdint.h>
#include <sstream>
#include <iostream>
int main() {
unsigned char result[8];
std::stringstream ss;
ss << std::hex << "0E00000000000400";
ss >> *( reinterpret_cast<uint64_t *>( result ) );
std::cout << static_cast<int>( result[1] ) << std::endl;
}
however take care of memory management issues!!!
Plus the result is in the reverse order as you would expect, so:
result[0] = 0x00
result[1] = 0x04
...
result[7] = 0x0E