Modified Ceasar cipher help

  • (2 Pages)
  • +
  • 1
  • 2

15 Replies - 12741 Views - Last Post: 16 July 2009 - 12:39 PM Rate Topic: -----

#1 kaaie   User is offline

  • D.I.C Head
  • member icon

Reputation: 3
  • View blog
  • Posts: 93
  • Joined: 22-June 09

Modified Ceasar cipher help

Post icon  Posted 15 July 2009 - 03:53 PM

Hi once again,

I have created a program in which the user inputs a string, then the program outputs the encrypted string(+ a gap, - a gap, + a gap...etc..). So if the gap is 1, AABC becomes B(-A)CB <- but thats the problem! The problem is, is that if the user inputs a value to high or to low, it will give out garbage(because from 0-32? in the ASCII table the values are non printable)(!).

I have tried many different ways to fix it, but none of them have succeeded.

So basically I'm asking if anyone could help me fix this problem(help me to understand how to code a bucleloop(a wrap)).

Here is the code:

#include <iostream>
#include <string>
#include <cstdlib>
#include "macros.h" // a header I made for functions I use allot, here it is only used for Pause() at the end of the program
using namespace std;
char restart;
int nCode;

int main()
{
	do
	{
		if (restart == 'Y'| restart == 'y')
			system("clear");	//CLS for a windows machine
		cout << "Please enter the code: ";
		cin >> nCode;
		srand(nCode);
		int gap = ((rand() % 4) + 1);
		cout << "Please enter your message(Gap=" << gap <<"):\n";
		Clear(); // in macros.h
		string sString;
		getline(cin, sString);
		bool bChose;
		cout << "\nEnter 0 to decrypt.\nEnter 1 to encrypt.\n";
		cin >> bChose;
		cout << "\n";
		if (bChose == 1)
		{
			for ( int i=0; sString[i] != '\0'; ++i )
			{
				sString[i] -= gap;
				++i;
				if (!(i=='\0')) //Because the for loop doesnt check if its the null terninator
					sString[i] += gap;
			}
		}
		else
		{
			for ( int i=0; sString[i] != '\0'; ++i )
			{
				sString[i] += gap;
				++i;
				if(!(i=='\0'))
					sString[i] -= gap;
			}
		}
		for (int i=0; sString[i] != '\0'; ++i )
		{
			cout << sString[i];
		}
		cout << "\n";
		cout << "\nWould you like to do it again? (y/n): ";
		cin >> restart;
	}
	while (restart == 'y' || restart == 'Y');
	Pause(); //all you need to know is that it is in macros.h and waits for the users input(it works)
	return 0;
}


Any help would be appreciated,
Thanks in advance

kaaie

p.s.
Do you think this method would be easy to decipher/crack?

This post has been edited by kaaie: 15 July 2009 - 06:29 PM


Is This A Good Question/Topic? 0
  • +

Replies To: Modified Ceasar cipher help

#2 wildgoose   User is offline

  • D.I.C Regular
  • member icon

Reputation: 67
  • View blog
  • Posts: 468
  • Joined: 29-June 09

Re: Modified Ceasar cipher help

Posted 15 July 2009 - 04:12 PM

did you mean to double increment the (i)
		  for ( int i=0; sString[i] != '\0'; ++i )
			{
				sString[i] += number;
				++i;



Also why are you comparing i to the NULL character?
			  if(!(i=='\0'))//Because the for loop doesnt check if its the null terninator
					sString[i] -= number;
 

This post has been edited by wildgoose: 15 July 2009 - 04:14 PM

Was This Post Helpful? 0
  • +
  • -

#3 Olimicus   User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 14
  • Joined: 07-May 09

Re: Modified Ceasar cipher help

Posted 15 July 2009 - 04:18 PM

A couple of things. One, change your Clear() and system("Clear") to the follow:

 system("cls"); 


Also, your first if statement is missing a pipe ( | ).

 if (restart == 'Y'|| restart == 'y') 


You should also add in something that would prompt the user to enter in numbers only. (Typing in a character in your code now will cause a continual loop). Something likes this:

 cout << "Please enter a numerical one-digit code: "; 


Sometimes it's just the little things ;)
Was This Post Helpful? 0
  • +
  • -

#4 kaaie   User is offline

  • D.I.C Head
  • member icon

Reputation: 3
  • View blog
  • Posts: 93
  • Joined: 22-June 09

Re: Modified Ceasar cipher help

Posted 15 July 2009 - 04:34 PM

To Wildgoose:

First question:
here I'll explain it better:

Lets say the gap is 3 and we come across a "t", it will be encrypted like this:
"t" is number 74 on the ASCII chart, so 164+3 = 167 which is "w"?, so "t" becomes "w".

Now what happens if the character is "~" which is the last letter on the ASCII chart and it is incremented? It has no where to go but back to the start, but since 0-32"?" are unprintable it gives out garbage. What I want is that when it happens it goes to 32+ not 0.


Second question:
To check to see if it is the end of the string(all string end by the null terminator).

Thanks for the help up to know!

p.s. this is not about a compiler error, because it compiles fine.



To Olimicus:
1:
I am on linux so to clear I use clear instead of CLS and Clear() lives in macros.h and is to clear the buffer for getline().
2:
Thanks, I fixed this
3:
fixed, thanks!

This post has been edited by kaaie: 15 July 2009 - 06:30 PM

Was This Post Helpful? 0
  • +
  • -

#5 erimir   User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 22
  • Joined: 07-June 09

Re: Modified Ceasar cipher help

Posted 15 July 2009 - 10:03 PM

Hi, i am learning this c++, and i have a question about your code. where youe wrote:
if (!(i=='\0'))

the same as:
if(i)



because a NULL checks as false?
Was This Post Helpful? 0
  • +
  • -

#6 kaaie   User is offline

  • D.I.C Head
  • member icon

Reputation: 3
  • View blog
  • Posts: 93
  • Joined: 22-June 09

Re: Modified Ceasar cipher help

Posted 15 July 2009 - 10:08 PM

View Posterimir, on 15 Jul, 2009 - 09:03 PM, said:

Hi, i am learning this c++, and i have a question about your code. where youe wrote:
if (!(i=='\0'))

the same as:
if(i)



because a NULL checks as false?


Yes, your right.

Thanks, but it still doesn't solve my initial problem.

This post has been edited by kaaie: 15 July 2009 - 10:12 PM

Was This Post Helpful? 0
  • +
  • -

#7 Guest_c.user*


Reputation:

Re: Modified Ceasar cipher help

Posted 15 July 2009 - 10:57 PM

kaaie said:

I have tried many different ways to fix it, but none of them have succeeded.

Did you try to make:
A - 1 = Z
Z + 1 = A
?
Was This Post Helpful? 0

#8 wildgoose   User is offline

  • D.I.C Regular
  • member icon

Reputation: 67
  • View blog
  • Posts: 468
  • Joined: 29-June 09

Re: Modified Ceasar cipher help

Posted 15 July 2009 - 11:03 PM

First of all
if (!(i=='\0'))


Apples and Oranges.
Characters and integers.
Compare like types, not different types.
i is an integer, these days typically 32-bit.
'\0' is a signed character of value 0. 8-bit

DO NOT DO THAT!!!!
Use either
if (i)
if (!i)
if (i == 0)
if (i != 0)
if (ch == 'd') // ch is char.
if (!ch)
if (ch)
Don't mix and match.

As to the other problem
You're dealing with signed chars versus unsigned char.

char ch; // Is typically 7-bit so
0...7f is 0...127
80...FF is -128...-1

So try this.
It's late and I'm tired so you'll have to test these while single stepping code to verify the results!

char c = buf[ idx ];
v = (int) c;
v += 4;
if (v >= 128)  v -= 96;
c = (char) v;



You can pack that into a single line but I kept it apart for clarity.
if (c + 4 < 0)	c = c - (96-4);


This post has been edited by wildgoose: 15 July 2009 - 11:05 PM

Was This Post Helpful? 0
  • +
  • -

#9 kaaie   User is offline

  • D.I.C Head
  • member icon

Reputation: 3
  • View blog
  • Posts: 93
  • Joined: 22-June 09

Re: Modified Ceasar cipher help

Posted 16 July 2009 - 10:03 AM

View Postwildgoose, on 15 Jul, 2009 - 10:03 PM, said:

So try this.
It's late and I'm tired so you'll have to test these while single stepping code to verify the results!

char c = buf[ idx ];
v = (int) c;
v += 4;
if (v >= 128)  v -= 96;
c = (char) v;



You can pack that into a single line but I kept it apart for clarity.
if (c + 4 < 0)	c = c - (96-4);


Sorry for my newbiness but I don't understand what your trying to do...


char c = buf[ idx ];		 //<----Im guessing c represents the character that we're on,
v = (int) c;				 //<----v is the numeric decimal value for c?
v += 4;						 //<----v+4..I guess 4 represents the gap
if (v >= 128)  v -= 96;			//<----Ok, so if its over 128(I thought 126 was the limit) v -= 96, where does the number 96 come from??
c = (char) v;				//<----convert v back to the char


So basically I need help understanding the fourth line, also, here is a newer version of my code if it helps(I alaso added a new snappy name :) ):

#include <iostream>
#include <string>
#include <cstdlib>
#include "macros.h"
using namespace std;
char restart;
int nCode;

int main()
{
start:
	system("clear");
	do
	{
		if (restart == 'Y' || restart == 'y')
			system("clear");	//CLS for a windows machine
		cout  << "||||||||||||||||||||||||||||||||||||\n"
		<< "||								||\n"
		<< "||	   Aegis Cipher 2009		||\n"
		<< "||								||\n"
		<< "||||||||||||||||||||||||||||||||||||\n";
		cout << "Please enter the code: ";
		cin >> nCode;
		srand(nCode);
		int number = ((rand() % 15) + 1);//To make sure it is between 1 and 16(as you might know, rand is only as good as its seed so the password with be the same every time))
		cout << "Please enter your message(CODE=" << number <<"):\n";
		string str;
		Clear();
		getline(cin, str);
		int bChose;
		cout << "\nEnter 0 to decrypt.\nEnter 1 to encrypt.\n";
		cin >> bChose;
		cout << "\n";
		int n;
		if (bChose == 1)
		{
			for ( int i=0; str[i] != '\0'; ++i )//Encrypt
			{
				str[i] -= number;
				++i;
				if(n >= 5)//Added randomness(every second number will have a gap between 2-5)
					n=1;
				n++;
				if (i)//Because the for loop doesnt check if its the null terninator
					str[i] += n;
			}
		}
		else
		{
			for ( int i=0; str[i] != '\0'; ++i )//Decrypt
			{
				str[i] += number;
				++i;
				if(n >= 5)
					n=1;
				n++;
				if (i) // returns false if it is the null terminator because \0 = false (same as (!(i=='\0'))
					str[i] -= n;//n is a possiblity of 2,3,4 or 5
			}
		}
		for (int i=0; str[i] != '\0'; ++i )
		{
			cout << str[i];
		}
		cout << "\n";
		cout << "\nWould you like to do it again? (y/n): ";
		cin >> restart;
	}
	while (restart == 'y' || restart == 'Y');
	Pause();
	return 0;
}

This post has been edited by kaaie: 16 July 2009 - 10:05 AM

Was This Post Helpful? 0
  • +
  • -

#10 wildgoose   User is offline

  • D.I.C Regular
  • member icon

Reputation: 67
  • View blog
  • Posts: 468
  • Joined: 29-June 09

Re: Modified Ceasar cipher help

Posted 16 July 2009 - 10:12 AM

Haven't looked at your new code yet, but here's the breakdown...

Yes, take one character from your buffer of type <char>
char c = buf[ idx ];		 //<----Im guessing c represents the character that we're on,



Force your 8-bit ASCII character upt to 32-bits (or 16-bits if on an old 16-bit machine
v = (int) c;				 //<----v is the numeric decimal value for c?



Since v is now the value of the character and is 16/32/64-bits in size, then adding values to push it over (127)
thus 128 or more will keep it positive. You would have to cross 32767 (on 16-bit) to become negative.
v += 4;						 //<----v+4..I guess 4 represents the gap



So if the value is 128 or higher then adjust for the base threshold of 32 you talked about.
128 - 32 = 96
if (v >= 128)  v -= 96;			//<----Ok, so if its over 128(I thought 126 was the limit) v -= 96, where does the number 96 come from??



Number is within positive range of a signed 8-bit number so cast the integer back into 8-bit
c = (char) v;				//<----convert v back to the char



I see you have a problem with bits per ranges
 datasize			 unsigned							  signed
8-bit			   0x00...0xFF  ( 0...255 )			  0x80...0xFF,0x00,0x01....0x7f  (-128...0....127)
16-bit			 0x0000...0xFFFF  (0...65535)	   0x8000....0xFFFF,0x00,0x0001....0x7FFF   (-32768...0...32767)


This post has been edited by wildgoose: 16 July 2009 - 10:16 AM

Was This Post Helpful? 1
  • +
  • -

#11 wildgoose   User is offline

  • D.I.C Regular
  • member icon

Reputation: 67
  • View blog
  • Posts: 468
  • Joined: 29-June 09

Re: Modified Ceasar cipher help

Posted 16 July 2009 - 10:26 AM

As to your function, your (i) is hinky on both sides your conditional.



??? You NEVER initialize (n)!!!!
for ( int i=0; str[i] != '\0'; ++i )//Encrypt

   str[i] -= number;
   ++i;

???? (n) initialization??? Where???

   if(n >= 5)//Added randomness(every second number will have a gap between 2-5)
	   n=1;

// You're rolling over (n) so your range is 1....5
				n++;
// ACTUALLY (n) range is now	2....5

// And what is (n) used for??? You set it but don't use it!!

// ??? (i) WILL NOT BE ZERO UNTIL IT TRYS TO ROLL OVER!!!
//	and because it's signed, it will rollover  0x7ffff, 0x8000, 0x8001
//	from 32767 to -32768 on a 16-bit machine.
//   2,147,483,647 to -2,147,483,648 on a 32-bit machine.
// (i) is your index, not the stored value!

				if (i)//Because the for loop doesnt check if its the null terninator
					str[i] += n;
			}


Was This Post Helpful? 0
  • +
  • -

#12 wildgoose   User is offline

  • D.I.C Regular
  • member icon

Reputation: 67
  • View blog
  • Posts: 468
  • Joined: 29-June 09

Re: Modified Ceasar cipher help

Posted 16 July 2009 - 10:35 AM

I think you need to untangle your logic.
Have your character processing loop function in main like you have it,
and create an encoding function.

char CaesarCipherEncode( char c )
{
	if (c < 128-4)
	{
		 c += 4;
	 }
	 else
	 {
		 c = ( c - (128-32)) + 4;
	 }

	 return c;
}



Was This Post Helpful? 0
  • +
  • -

#13 kaaie   User is offline

  • D.I.C Head
  • member icon

Reputation: 3
  • View blog
  • Posts: 93
  • Joined: 22-June 09

Re: Modified Ceasar cipher help

Posted 16 July 2009 - 11:44 AM

View Postwildgoose, on 16 Jul, 2009 - 09:35 AM, said:

char CaesarCipherEncode( char c )
{
	if (c < 128-4)
	{
		 c += 4;
	 }
	 else
	 {
		 c = ( c - (128-32)) + 4;
	 }

	 return c;
}




Ok I think I understand your logic, but where is the variable for the gap in all of this? The caesar cipher should always have a user defined gap between the original and the encoded version. Maybe the 4 is the gap? But anyhow the user should be able to pass a variable to the CaesarCipherEncode finction containing the gap, I cannot see how it would work without some sort of interactivity with the user.

So in my eyes, this should work right?:

#include <string>
#include <iostream>
#include "macros.h"

char CaesarCipherEncode( char c, int gap )
{
	if (c < 128-gap)
	{
		 c += gap;
	 }
	 else
	 {
		 c = ( c - (128-32)) + gap;
	 }

	 return c;
}

int main()
{
	int gap;
	string str;
	cout << "Please enter the string, then the gap: ";
	Clear();//Clears the buffer, in macros.h
	getline(cin, str);
	cin >> gap;
	for(int i=0; i<str.length(); i++)
	{
		CaesarCipherEncode(str[i], 2);
	}
	for(int i; str[i] == '\0'; i++)
	{
		cout << str[i];
	}
	return 0;
}

I'm not exactly sure it works but you get the point?
Was This Post Helpful? 0
  • +
  • -

#14 wildgoose   User is offline

  • D.I.C Regular
  • member icon

Reputation: 67
  • View blog
  • Posts: 468
  • Joined: 29-June 09

Re: Modified Ceasar cipher help

Posted 16 July 2009 - 11:50 AM

Okay you did the gap just fine!

However

	for(int i=0; i<str.length(); i++)
	{
//		CaesarCipherEncode(str[i], 2);
		str[i] = CaesarCipherEncode(str[i],  gap );
   }

 //   for(int i; str[i] == '\0'; i++)
	for(int i=0; i<str.length(); i++)	{
		cout << str[i];
	}



This post has been edited by wildgoose: 16 July 2009 - 11:51 AM

Was This Post Helpful? 0
  • +
  • -

#15 kaaie   User is offline

  • D.I.C Head
  • member icon

Reputation: 3
  • View blog
  • Posts: 93
  • Joined: 22-June 09

Re: Modified Ceasar cipher help

Posted 16 July 2009 - 12:32 PM

Ok, I finally got a working encryptor, thanks to wildgoose <-- Thank you SOO much!

But now I have another problem, im trying to reverse the effect to decrypt it and it kind of works... It usually partially works... for example:

I encoded a message(gap of 15) that says: "Hello world!" (gives out Wf{n~#fs!qs" which is what it is supposed to be.)
Then I try to decrypt it and gives out this(? : incomprehensible character): "Hello wo??d!"

here is the code(I know it is hard to read, but I will work on that later after I get it to function properly):

#include <iostream>
#include <string>
#include <cstdlib>
#include "macros.h"
using namespace std;
char restart;
int nCode;

int main()
{
start:
	system("clear");
	do
	{
		if (restart == 'Y' || restart == 'y')
			system("clear");	//CLS for a windows machine
		cout	<< "|||||||||||||||||||||||||||||||||||\n"
		<< "||							   ||\n"
		<< "||	   Aegis Cipher 2009	   ||\n"
		<< "||							   ||\n"
		<< "|||||||||||||||||||||||||||||||||||\n";
		cout << "Please enter the code: ";
		cin >> nCode;
		srand(nCode);
		int number = ((rand() % 3) + 1);//To make sure it is between 1 and 4(as you might know, rand is only as good as its seed so the password with be the same every time))
		cout << "Please enter your message(CODE=" << number <<"):\n";
		string str;
		Clear();
		getline(cin, str);
		int bChose;
		cout << "\nEnter 0 to decrypt.\nEnter 1 to encrypt.\n";
		cin >> bChose;
		cout << "\n";
		int n = 0;
		int c = 0;
		if (bChose == 1)
		{
			for ( int i=0; str[i] != '\0'; ++i )//Encrypt
			{

				if (str[i] < 128-number)
				{
					str[i] += number;
				}
				else
				{
					str[i] = ( str[i] - (128-32)) + number;
				}
				i++;


				/**############################Second part of encryption####################**/


				if (n > 4)//Added randomness(every second number will have a gap between 1-4)
					n=0;
				n++;
				if (i)//Because the for loop doesnt check if its the null terninator, returns false if it is the null terminator because \0 = false (same as (!(i=='\0'))
				{
					if (c < 128-n)
					{
						str[i] += n;
					}
					else
					{
						str[i] = ( str[i] - (128-32)) + n;
					}
				}
			}
		}

		/**###########################decryption#######################################**/
		/**#########################################################################**/

		else
		{
			for ( int i=0; str[i] != '\0'; ++i )//Decrypt
			{


				if (str[i] > 0+number)
				{
					str[i] -= number;
				}
				else
				{
					str[i] = ( str[i] + (128+32)) - number;
				}

				i++;


				/**#####################second part of decryption####################**/


				if (n > 4)//Added randomness(every second number will have a gap between 1-4)
					n=0;
				n++;
				if (i)//Because the for loop doesnt check if its the null terninator, returns false if it is the null terminator because \0 = false (same as (!(i=='\0'))
				{
					if (str[i] > 0+n)
					{
						str[i] -= n;
					}
					else
					{
						str[i] = ( str[i] + (128+32)) - n;
					}
				}
			}
		}
		for (int i=0; str[i] != '\0'; ++i )
		{
			cout << str[i];
		}
		cout << "\n";
		cout << "\nWould you like to do it again? (y/n): ";
		cin >> restart;
	}
	while (restart == 'y' || restart == 'Y');
	Pause();
	return 0;
}


Macros.h:
#include <iostream>
#include <limits>
#include <ctime>
using namespace std;

void delay(int seconds)
{
	cout << "Waiting " << seconds << " seconds.\n";
	int a = time(0) + seconds;
	while (a != time(0))
	{
	}
}
void Pause()
{
	cout<<"\nPress Enter to exit.";
	if (!cin)
	{
		cin.clear();
	}
	cin.ignore(numeric_limits<streamsize>::max(), '\n');
	cin.get();
}
void Clear()
{
	if (!cin)
	{
		cin.clear();
	}
	cin.ignore(numeric_limits<streamsize>::max(), '\n');
}


Once again Thank you sooo much for all the help, and it is really appreciated.

This post has been edited by kaaie: 16 July 2009 - 12:35 PM

Was This Post Helpful? 0
  • +
  • -

  • (2 Pages)
  • +
  • 1
  • 2