This program is supposed to crypt a certain message with the vigenere cypher. The program is supposed to be 'case sensitive' both the message and the keyword. If the program encounters any special characters or numbers, is also supposed to print them untouched.
The last part seems to be working, and the rest, even though the math seems to be right, it doesn't print as it's supposed to. I'm also converting the ASCII values to A-Z/0-26, doing the cypher formula, and them converting them back to ASCII.
// key validation
string kw = argv[1];
int kwl = strlen(kw);
for (int i = 0; i < kwl; i++)
{
if (!isalpha(kw[i]))
{
printf("Usage: ./vigenere keyword\n");
return 1;
}
}
// get message and length
string mssg;
mssg = GetString();
int lngth = strlen(mssg);
// cryptography
int k = 0;
for (int j = 0; j < lngth; j++)
{
if (isalpha(mssg[j]))
{
if (islower(mssg[j]))
{
if (islower(kw[k % kwl]))
printf("%c", (((mssg[j] - 97) + (kw[k % kwl] - 97)) & 26) + 97);
else
printf("%c", (((mssg[j] - 97) + (kw[k % kwl] - 65)) & 26) + 97);
k++;
}
else if (isupper(mssg[j]))
{
if (isupper(kw[k % kwl]))
printf("%c", (((mssg[j] - 65) + (kw[k % kwl] - 65)) & 26) + 65);
else
printf("%c", (((mssg[j] - 65) + (kw[k % kwl] - 97)) & 26) + 65);
k++;
}
}
else
printf("%c", mssg[j]);
}
printf("\n");
return 0;
}
I'm still getting an error somewhere on the math
The error is that you have & 26 instead of % 26.
Related
I'm trying to re-index my ASCII decimal characters of the alphabet so that they start at 0 with 'A' rather than 65 so I can use a certain formula.
My initial thoughts were to create a string of the alphabet and iterate over it taking away minus 65 at each iteration, I then realised this is only having an effect on the string (which gives a segfault anyway) and does not have any effect on the decimal value of the actual character:
string alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
for (int k = 0, length_ = strlen(alphabet); k < length_ ; k ++)
{
alphabet[k] = alphabet[k] - 65;
printf("Alphabet no.%i is equal to %c", k, alphabet[k]);
}
Any ideas?
void printAlpha(int i){
if(i < 26)
printf("%c", 'A' + i);
else if(i < 52)
printf("%c", i - 26 + 'a');
}
I am trying to perform a Caesar cipher from text from user using modulo operation with the ascii characters. But, my code simply prints the entered test. For example, when the text entered is HELLO the program returns "HELLO". The goal is for a key of 13 it should print URYYB. Thank you.
#include <cs50.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
int key = atoi(argv[1]);
string plaintext = get_string("Enter plaintext: ");
for (int i = 0; i < strlen(plaintext); i++)
{
if (isalpha(plaintext[i]))
{
if (isupper(plaintext[i]))
{
printf("%c", ((plaintext[i] + key) % 26) + 65);
}
else if (islower(plaintext[i]))
{
printf("%c", ((plaintext[i] + key) % 26) + 97);
}
else
{
printf("%c", plaintext[i]);
}
}
}
printf("\n");
Preliminary analysis
Character code of 'H' is 72.
(72 + 13) % 26 + 65 = 85 % 26 + 65 = 7 + 65 ~ 'H'
Let's see if we subtract 65 first:
(72 - 65 + 13) % 26 + 65 = (7 + 13) % 26 + 65 = 20 % 26 + 65 = 20 + 65 = 85 ~ 'U'
Solution
printf("%c", ((plaintext[i] + key - 65) % 26) + 65);
and
printf("%c", ((plaintext[i] + key - 97) % 26) + 97);
respectively.
Proof
If you have a character code, C, where S <= C < S + 26, then the formula you used is:
((C + key) % 26) + S
however, the actual letter is L and we know that
C = S + L,
so the formula is
((S + L + key) % 26) + S
and, since
(A + B) % C = ((A % C) + (B % C)) % C,
replacing A with (S), B with (L + key) and C with 26, we get:
((S % 26) + ((L + key) % 26)) % 26, we see that the result is distorted by (S % 26), which, in the case of 65 is exactly 13. Since a distortion of 13 + the key of 13 you used in the modulo class of 26 will yield the initial letter!
So, the proposed new formula of
((C + key - S) % 26) + S = (((S + L) + key - S) % 26) + S = ((L + key) % 26) + S
is exactly what you need.
You are adding key to the value of each plaintext character, when it is meant to apply to the corresponding letter's index in the alphabet. For example, in case of the 'H' in ASCII, your formula is: (72 + 13) % 26 which gives 7 (which is also the index of H in the alphabet, when starting from zero).
You need to convert the (ASCII) value of the character to its index before applying key, e.g., ((plaintext[i] - 'A' + key) % (1 + 'Z' - 'A')) + 'A'.
The solution for 'H' would then become (72 - 65 + 13) % 26, which gives 20 (the correct answer, 7 + 13, the index of U).
Your cipher function just does nothing if the key is 13:
run a bit amended one and see the result :D
int main()
{
int key = 13;
char plaintext[] = "HELLO";
for (int i = 0; i < strlen(plaintext); i++)
{
if (isalpha(plaintext[i]))
{
if (isupper(plaintext[i]))
{
printf("%d, %d\n", (int)plaintext[i], (int)(((plaintext[i] + key) % 26) + 65));
}
else
{
if (islower(plaintext[i]))
{
//printf("%c", ((plaintext[i] + key) % 26) + 97);
}
else
{
//printf("%c", plaintext[i]);
}
}
}
}
printf("\n");
return 0;
}
I am making a program that decrypts the vigenere cipher. User can only give alphabetical key.
for (int i = 0, counter = strlen(text); i < counter; i++)
{
// prints non-alphabetical characters straight away
if (!isalpha(text[i]))
{
printf("%c", text[i]);
}
else
{
// for index of key
index = meta % strlen(key);
if (islower(text[i]))
{
// separate cases depending upon case of key
if (islower(key[index]))
{
printf("%c", (((text[i] - 97) - (key[index] - 97)) % 26) + 97);
}
else
{
printf("%c", (((text[i] - 97) - (key[index] - 65)) % 26) + 97);
}
}
else
{
if (islower(key[index]))
{
printf("%d", (((text[i] - 65) - (key[index] - 97)) % 26) + 65);
}
else
{
printf("%c", (((text[i] - 65) - (key[index] - 65)) % 26) + 65);
}
}
// incrementing for next key alphabet
meta++;
}
Vigenere:
Input: MyName
key: qwerty
output: CuRrfc
De Vigenere:
Input: CuRrfc
key:qwerty
expected output: MyName
given output: 3_NaSK
How can I fix it?
The problem is the way the modulus operator deals with negative numbers.
For some characters you get negative values and the modulus operation then returns a negative value. You want a value in the range [0, 25].
You can fix it by adding 26 before taking the modulus.
printf("%c", (((text[i] - 97) - (key[index] - 97)) % 26) + 97);
would become
printf("%c", (((text[i] - 97) - (key[index] - 97) + 26) % 26) + 97);
Change all four rows the same way.
I cannot figure out why this thing doesn't scramble correctly. I read some other posts on this cipher and as far as I can tell I'm using the exact same algorithm as they are...
The areas commented out are tests I tried to make sure everything was passing through correctly. I believe it all goes through correctly then fails in the algorithm.
#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
string get_message(void);
string scramble(string key, string message);
int main(int argc, string argv[])
{
if(argc == 2)
{
string key;
string message;
key = argv[1];
//printf("KEY: %s<<",key);
message = get_message();
scramble(key, message);
}
else
{
printf("Please enter 2 arguments.\n");
return 1;
}
}
string get_message(void)
{
string message = "";
do
{
message = GetString();
}
while(strlen(message) < 1);
return message;
}
string scramble(string key,string message)
{
for(int i = 0, len = strlen(message), key_len = strlen(key); i < len; i++)
{
int letter = message[i];
//int Tkey = atoi(key[i % key_len]);
//printf("KEY: %d<<\n",Tkey);
if(islower(letter))
{
//printf("KEY(%d)",(key[i % key_len]-97));
letter = (((letter - 97) + (key[i % key_len])) % 26 + 97);
//printf("(%d)",(letter - 97) + (key[i % key_len])%26);
printf("%c",letter);
}
else if(isupper(letter))
{
//printf("(%d)", key[i]);
//printf("(%c)",letter); WE HAVE CORRECT LETTER
letter = (((letter - 65) + (key[i % key_len])) % 26 + 65);
printf("%c",letter);
}
}
printf("\n");
return 0;
}
I think your calculation is wrong:
You currently have
encryptedLetter = (letter - firstLetterOffset) + key[position % keyLength] % 26 + firstLetterOffset
by check the C operator precedence table we notice that % is evaluated before - or +, meaning that your code actually mean :
encryptedLetter = (letter - firstLetterOffset) + ( key[position % keyLength] % 26 ) + firstLetterOffset
Where you wanted :
encryptedLetter = ( (letter - firstLetterOffset) + key[position % keyLength] ) % 26 + firstLetterOffset
Conclusion : you need to put more parenthese to specify in which order you which to evaluate your expression.
In addition you took the letter number for the text character but not for the key !
Correct expression
encryptedLetter = ( (letter - firstLetterOffset) + key[position % keyLength] - firstLetterOffset ) % 26 + firstLetterOffset
Demonstration in javascript
A general explanation of the Vigenere Cipher:
The Vigenere Cipher is a method of encryption that is similar to the Caesar Cipher. This Cipher takes in a word as an argument and interprets the alphabets of the word as follows- a as 0, b as 1, c as 2 and so on.
So if your input key is abc and you want something like "hi hello" to be encrypted, the output would entail h remaining the same, i shifting by 1 place, h shifting by 2 places, e again remaining the same (as it is being shifted by 0), l shifting by 1 place, the other l by 2 and so on so forth.
The basic idea is that each letter shifts by the corresponding letter in the argument and the spaces and other punctuation marks are ignored. If the argument is shorter than the message (as it is in most cases), the argument simply loops around the message.
My problem:
My message is just being encrypted by the first alphabet of the Vignere Cipher.
For example, ./vc bc ----> message: ABCDE ABCDE becomes BCDEF BCDEF. In other words, the entire message is just being shifted by the value of b when it should instead be shifted by the value of bc (+1 for the first alphabet and +2 for every other alphabet.)
I don't understand why is this happening despite being within a loop.
CODE:
# include <cs50.h>
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <ctype.h>
int main(int argc, string argv[])
{
string word = argv[1];
int i = 0;
int j = 0;
if (argc != 2 || isalpha(word[j]) == false)
{
printf("Please enter a valid command line argument! \n");
return 1;
}
else if (isalpha(word[j]))
{
printf("Message: ");
string message = GetString();
for (int n = strlen(message); i < n; i++)
{
int plaintext = message[i];
int ciphertext = word[j];
int uppcb = (plaintext - 65 + ciphertext - 65);
int upcipher1 = (uppcb) % 26;
int uplc = (plaintext - 65 + ciphertext - 97);
int upcipher2 = (uplc) % 26;
int lopcb = (plaintext - 97 + ciphertext - 97);
int locipher1 = (lopcb) % 26;
int lolp = (plaintext - 97 + ciphertext - 65);
int locipher2 = (lolp) % 26;
if (isupper(word[j]) && isupper(message[i]))
{
j = (j+1)%strlen(word);
int upcode = (upcipher1 + 65);
printf("%c", upcode);
}
else if (isupper(message[i]) && islower(word[j]))
{
j = (j+1)%strlen(word);
int upcode1 = (upcipher2 + 65);
printf("%c", upcode1);
}
else if (islower(message[i]) && islower(word[j]))
{
j = (j+1)%strlen(word);
int locode = (locipher1 + 97);
printf("%c", locode);
}
else if (islower(message[i]) && isupper(word[j]))
{
j = (j+1)%strlen(word);
int locode1 = (locipher2 +97);
printf("%c", locode1);
}
else
{
printf("%c", message[i]);
}
}
printf("\n");
}
}