Hi, I'm working my way through a book called "Information Security: Principles and Practice". At the end of each chapter there are problems that the author deals out to make sure you comprehend what you just read. Well, a lot of the problems are encrypted strings using the ceasar cipher, and I'm trying to shift the letters in a string to decrypt the string. How can I do this in C++?
Thanks for the help,
Nathan
namezero111111
December 9th, 2006, 02:30 PM
What kind of string are you using?
char *, std::string or CString?
In case it is a char *, you can do the following:
char *pCursor = pszString;
while('\0' != *pCursor)
{
*pCursor = *pCursor + whatever; // Here you can modify every single char
pCursor++; // advance to next char
}
In case of std::string or CString, there are functions for replacing strings.
Or, you could get a ptr to the bytes and then use what I wrote above.
Hope that helps,
Andy
Nathand
December 9th, 2006, 02:39 PM
I haven't written the program yet, cause I wasn't sure how :) In your code you posted does it actually change a letter? I don't understand it very well, sorry. I'm kind of new to C++ so thanks for the help :)
namezero111111
December 9th, 2006, 02:59 PM
No, but in the loop you can add/subtract the number you want (I understand that is what Caesarian cipher is, adding 3 to 'A', so it becomes 'D'.
E.g.
'A' + 3 = 'D' and
'D' - 3 = 'A'
If you don't understand why, look at an ASCII table.
-Andy
Nathand
December 9th, 2006, 03:22 PM
Ok, but what does pszString mean?
laasunde
December 10th, 2006, 06:16 AM
How about;
int main()
{
std::string s = "Hello";
std::cout << s << std::endl;
for(int index=0; index < s.length(); index++)
{
s[ index ] = s[ index ] + 1;
}
std::cout << s << std::endl;
system("PAUSE");
return 0;
}
Output
Hello
Ifmmp
Nathand
December 10th, 2006, 10:42 AM
So adding a number to a letter will shift the letter by the numbers amount?
Mitsukai
December 10th, 2006, 10:48 AM
So adding a number to a letter will shift the letter by the numbers amount?
as suggested earlier look at the asciitable.
search asciitable on google...
SuperKoko
December 10th, 2006, 11:00 AM
@namezero111111: Warning, your encoded string may contain nul character.
Or, assuming that the source character set contains only A-Za-z and space, the destination character set doesn't match the source character set.
Nathand
December 12th, 2006, 08:29 AM
When I try to compile that C++ program I get: http://rafb.net/paste/results/fHSKTq95.html.
SuperKoko
December 12th, 2006, 08:38 AM
@Nathand: Check that you include the <string> and <iostream> headers (both of them must be included).
TheCPUWizard
December 12th, 2006, 08:38 AM
A proper cipher (assuming only capital letters in the source)
char *in = source;
char *out = *dest; // assuming dest is pre-allocated
while (*in)
{
*out = ((*in -'A') + offset) %26;
in++; // not optimal, but possibly easier to read for a beginner...
out++;
}
*out = 0; // terminate the output.
Nathand
December 12th, 2006, 08:57 AM
You were right :) I forgot to add "#include <string>.
Yes, I know, space characters are not encrypted, it's very weak, but AFAIK, the original caesar encryption algorithm does that.
Nathand
December 12th, 2006, 09:20 AM
Ok, last question :)
When I use this code:
#include <iostream>
#include <string>
int key = 1;
int main()
{
std::string s = "CSYEVIXIVQMREXIH";
std::cout << s << std::endl;
for(int i = 0; i < 26; i++)
{
for(int index=0; index < s.length(); index++)
{
s[ index ] = s[ index ] + key;
}
std::cout << s << std::endl;
key += 1;
}
system("PAUSE");
return 0;
}
The caesar's cipher is "youareterminated", but the program returns "_ouareterminated". Why would this be? This also happens with some other ciphers I tried.
And if someone feels so inclined to compile and run this on their system, let me know if you get a very strange "beeping" noise coming from your computer?
Thanks,
Nathan
Paul McKenzie
December 12th, 2006, 09:36 AM
The caesar's cipher is "youareterminated", but the program returns "_ouareterminated". Why would this be?My new tagline --
Have you debugged your code?
You've written the program and it runs. Debugging is part of the programming process.
Regards,
Paul McKenzie
Nathand
December 12th, 2006, 09:44 AM
What exactly do you mean by "debugged" your code?
SuperKoko
December 12th, 2006, 09:51 AM
Ok, last question :)
When I use this code:
#include <iostream>
#include <string>
int key = 1;
int main()
{
std::string s = "CSYEVIXIVQMREXIH";
std::cout << s << std::endl;
for(int i = 0; i < 26; i++)
{
for(int index=0; index < s.length(); index++)
{
s[ index ] = s[ index ] + key;
}
std::cout << s << std::endl;
key += 1;
}
system("PAUSE");
return 0;
}
The caesar's cipher is "youareterminated", but the program returns "_ouareterminated". Why would this be? This also happens with some other ciphers I tried.
And if someone feels so inclined to compile and run this on their system, let me know if you get a very strange "beeping" noise coming from your computer?
Thanks,
Nathan
It's due to the fact that ('Y' + the_original_encoding_key) / 26 was equal to 1+(any_other_letter_of_the_string + the_original_encoding_key)/26
In other words, 'Y' wrapped around once while other characters don't.
Actually, it's easy to see that the_original_encoding_key==4.
But, your current algorithm is incorrect... It doesn't compute things modulo 26.
Since the_decoding_key is -4 or 26-4==22 modulo 26, your program shouldn't work at all... In fact, you should never screen any value that re-creates anything looking a bit with the original text.
But an amazing thing happened! The lower case a-z characters are above the upper-case A-Z characters in the ASCII table, and, 'a'='A'+32, 'b'='B'+32
So, for decoding_key==28, your program will output something that really looks like the original text, except that you've lower case letters, and 'Y' will be translated to 'y'-26=='a'-2=='_'
But, you'll say that you don't test for decoding_key==28...
But, you do!
You iteratively modify the original string, and consequently, you're testing for decoding_key==0, decoding_key==1, decoding_key==3, decoding_key==6, decoding_key=10 and so on...
0+1+2+3+4+5+6+7 happens to be equal to 28
So, your 8th 'deciphered string' is equal to _ourareterminated
Amazing, isn't it?
#include <iostream>
#include <string>
int main()
{
std::string s = "CSYEVIXIVQMREXIH";
std::cout << s << std::endl;
for(int i = 0; i < 26; i++)
{
for(int index=0; index < s.length(); index++)
{
s[ index ] = 'A'+(s[ index ]-'A' + 1)%26;
}
std::cout << s << std::endl;
}
system("PAUSE");
return 0;
}
Should work better (warning, it has not been tested, currently I've no compiler under the hand).
PS: the 'beeping' is probably character #7 that you get because you end up adding large numbers to your characters that wrap around 256.
Paul McKenzie
December 12th, 2006, 10:07 AM
What exactly do you mean by "debugged" your code?Programming isn't just writing code, running the code, and then hoping everything works. Part of programming is called "debugging", which means finding the errors in the logic in your code. Every programmer must know how to debug their own code.
This is done by using printf() or cout() statements, or using the debugging facilities provided to you by the compiler you're using, or just using pencil and paper to step through the logic in the code. These are skills that should be learned on the first, if not second day of programming.
What if the program was much more complex? How will you find the error? How do programmers such as SupeKoko and others able to find the problem?
The bottom line is that you have a running program, and it doesn't produce the output or results you wanted, then take it on yourself to figure it out by debugging the code. Sure, you got an instant answer, but IMO this takes away from you actually learning the skills needed for programming, especially if you come across another problem. However, sometimes the reasons for the error are not obvious, even during debugging -- then and only then should you call for help in figuring out a problem.
Regards,
Paul McKenzie
exterminator
December 12th, 2006, 10:18 AM
Take a look at the following thread - http://www.codeguru.com/forum/showthread.php?t=398759
Basically, the code in this post - http://www.codeguru.com/forum/showpost.php?p=1451846&postcount=6
Nathand
December 12th, 2006, 08:14 PM
SuperKoko - Thank you for your very informative post. I'm still trying to figure out what you said :)
I really appreciate all the help,
Nathan
Nathand
December 12th, 2006, 08:37 PM
SuperKoko - In your post you said:
"It's due to the fact that ('Y' + the_original_encoding_key) / 26 was equal to 1+(any_other_letter_of_the_string + the_original_encoding_key)/26."
In C++ would that be #include <iostream>
#include <string>
int main()
{
std::string s = "Y";
s[0] = (s[0] - 4) / 26;
std::cout << s;
Because I tried that and got two different values?
Sorry for not being good at programming :(
-Nathan
SuperKoko
December 13th, 2006, 05:05 AM
SuperKoko - In your post you said:
"It's due to the fact that ('Y' + the_original_encoding_key) / 26 was equal to 1+(any_other_letter_of_the_string + the_original_encoding_key)/26."
I was refering to the non-C++ values of characters in the alphabetical table.
In C++, it would be:
#include <iostream>
int main()
{
std::cout << (('Y'-'A')+4)/26 << " equal " << 1+(('O'-'A')+4)/26 << '\n'; // untested, but it should display: 1 equal 1
}
In other words:
'Y'-'A' == 24 (Y is the character #24 in the alphabetical table, starting from zero).
'Y'-'A'+4 == 28 and consequently, it should wrap around with a correctly written caesar encoding algorithm.
i.e. (('Y'-'A')+4)/26==1
For other characters, the base alphabetical value is smaller than 26-4, and consequently, after being added 4, they're still below 26 and ((the_character-'A')+4)/26==0 and ((the_character-'A')+4)%26==
((the_character-'A')+4).
Assuming the key is any number < 26 or >=26 having a remainder equal to 4 modulo 26, the general C++ formula is:
(('Y'-'A')+key)/26 == 1+(('O'-'A')+key)/26
And, given in non-C++ terms (a formula applying on usual alphabetic codes: 'A'=0, 'B'=1, etc.):
('Y'+key)/26 = 1+('O'+key)/26
That is just a mean to say that 'Y' is not added the same absolute value than other characters in the original text sample.
That explains why you can have a resulting "decoded" string that looks a bit like the original except for the 'Y' character.
Nathand
December 16th, 2006, 06:47 PM
Ok, thanks for the help.
I'm having a little trouble understanding this code:
std::cout << (('Y'-'A')+4)/26 << " equal " << 1+(('O'-'A')+4)/26 << '\n';Because the code above (which you posted), prints "1 equal 1" just like you said it would.
But this code:
std::cout << (('Y'-'A')+4) << " equal " << 1+(('O'-'A')+4) << '\n';Prints "28 equal 19". Which doesn't make sense to me, considering the only things I removed were the
/26 So what I'm having trouble understanding is why 28 dived by 26 (1.07) equals 19 divided by 26 (0.73)?
Thank you for the help.
SuperKoko
December 17th, 2006, 03:19 AM
std::cout << (('Y'-'A')+4) << " equal " << 1+(('O'-'A')+4) << '\n';Prints "28 equal 19". Which doesn't make sense to me, considering the only things I removed were the
/26 So what I'm having trouble understanding is why 28 dived by 26 (1.07) equals 19 divided by 26 (0.73)?
Thank you for the help.
/ is the integer division.
In other words, it returns the quotient of the euclidian division.
28 divided by 26 has a quotient equal to 1
18 divided by 26 has a quotient equal to 0, and, adding 1 gives 1.
Note that division has a higher precedence than addition.
Consequently:
1+(('O'-'A')+4)/26
Is NOT 19/26
It is interpreted as:
1+((('O'-'A')+4)/26)
And is equal to 1+(18/26), NOT (1+18)/26
Consequently, it is equal to 1+0
And, 1+0=1 :)
Nathand
December 17th, 2006, 02:51 PM
Right! *smacks himself*
Because when using integers you don't use decimal points right? Just whole numbers?
codeguru.com
Copyright Internet.com Inc., All Rights Reserved.