Skip to content

Commit

Permalink
Add new cipher option, Vigenere Cipher
Browse files Browse the repository at this point in the history
  • Loading branch information
TERNION-1121 committed Feb 14, 2024
1 parent 8578ad2 commit 1c4fc71
Show file tree
Hide file tree
Showing 6 changed files with 179 additions and 74 deletions.
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,16 @@ To use this program, a basic knowledge of ciphers would be a prerequisite.
Currently it features the below cipher algorithms:
1. [Caesar](https://github.com/TERNION-1121/ezCipher/tree/main/cipher-descriptions/caesar.md)
2. [Substitution](https://github.com/TERNION-1121/ezCipher/tree/main/cipher-descriptions/substitution.md)

3. [Vigenère]()

Click on a cipher name to view its description/explanation.

### How to run the program?
__Requirements__: A C compiler, such as GCC or Clang.

1. Clone this repository
2. Open the terminal, and navigate to the repository `~/ezCipher`
3. Run the command `clang -o ec src/ec.c src/utils/utils.c src/ciphers/caesar.c src/ciphers/substitution.c`
3. Run the command `clang -o ec src/ec.c src/utils/utils.c src/ciphers/caesar.c src/ciphers/substitution.c src/ciphers/vigenere.c`
> You can also use `gcc` instead of `clang`
4. Run `./ec`
5. You'll be prompted with this message
Expand All @@ -44,6 +45,7 @@ USAGE: ./ec <cipher> <encrypt/decrypt_mode> <key>
<cipher>:
caesar
substitution
vigenere
<encrypt/decrypt_mode>:
encrypt
Expand Down Expand Up @@ -100,6 +102,7 @@ Where,
<cipher_algorithm_option>
caesar
substitution
vigenere
<encrypt_or_decrypt_mode>
encrypt
Expand Down
47 changes: 21 additions & 26 deletions src/ciphers/caesar.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,61 +24,56 @@ bool valid_caesar_key(const char *key)
return n >= 1 && n <= 26;
}


/*
Assume caller passes a valid integer key in the range [1, 26)
*/

// caesar_encrypt: encrypt plaintext with the given integer key
char *caesar_encrypt(const char *plainText, int key)
char *caesar_encrypt(const char *plaintext, int key)
{
int size = strlen(plainText);
char *cipherText = (char *) malloc(size+1);
int size = strlen(plaintext);
char *ciphertext = (char *) malloc(size + 1);

if (cipherText == NULL)
if (ciphertext == NULL)
return NULL;

char ch;
for (int i = 0; (ch = plainText[i]) != '\0'; ++i)
for (int i = 0; (ch = plaintext[i]) != '\0'; ++i)
{
if (!isalpha(ch))
{
cipherText[i] = ch;
ciphertext[i] = ch;
continue;
}

if (isupper(ch))
cipherText[i] = ((ch - 'A') + key) % 26 + 'A';
else
cipherText[i] = tolower(((ch - 'a') + key) % 26 + 'A');

int asciishift = (isupper(ch) ? 'A' : 'a');
ciphertext[i] = (ch - asciishift + key) % 26 + asciishift;
}
cipherText[size] = '\0';
return cipherText;
ciphertext[size] = '\0';
return ciphertext;
}

// caesar_decrypt: decrypt ciphertext with the given integer key
char *caesar_decrypt(const char *cipherText, int key)
char *caesar_decrypt(const char *ciphertext, int key)
{
int size = strlen(cipherText);
char *plainText = (char *) malloc(size+1);
int size = strlen(ciphertext);
char *plaintext = (char *) malloc(size + 1);

if (plainText == NULL)
if (plaintext == NULL)
return NULL;

char ch;
for (int i = 0; (ch = cipherText[i]) != '\0'; ++i)
for (int i = 0; (ch = ciphertext[i]) != '\0'; ++i)
{
if (!isalpha(ch))
{
plainText[i] = ch;
plaintext[i] = ch;
continue;
}

if (isupper(ch))
plainText[i] = (ch - 'A' + 26 - key) % 26 + 'A';
else
plainText[i] = (ch - 'a' + 26 - key) % 26 + 'a';
int asciishift = (isupper(ch) ? 'A' : 'a');
plaintext[i] = (ch - asciishift + 26 - key) % 26 + asciishift;
}
plainText[size] = '\0';
return plainText;
plaintext[size] = '\0';
return plaintext;
}
5 changes: 5 additions & 0 deletions src/ciphers/ciphers.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,9 @@ bool valid_substitution_key(const char *key);
char *substitution_encrypt(const char *plainText, const char *key);
char *substitution_decrypt(const char *cipherText, const char *key);

bool valid_vigenere_key(const char *key);

char *vigenere_encrypt(const char *plaintext, const char *key);
char *vigenere_decrypt(const char *plaintext, const char *key);

#endif
45 changes: 22 additions & 23 deletions src/ciphers/substitution.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,62 +22,61 @@ bool valid_substitution_key(const char *key)
return length == 26; // key is valid by length
}


/*
Assume caller passes a valid key,
which is a 26 character long uppercase permutation of the English Alphabet
*/

// substitution_encrypt: encrypt the given plaintext with the given key
char *substitution_encrypt(const char *plainText, const char *key)
char *substitution_encrypt(const char *plaintext, const char *key)
{
int size = strlen(plainText);
char *cipherText = (char *) malloc(size+1);
int size = strlen(plaintext);
char *ciphertext = (char *) malloc(size + 1);

if (cipherText == NULL)
if (ciphertext == NULL)
return NULL;

char ch;
for (int i = 0; (ch = plainText[i]) != '\0'; ++i)
for (int i = 0; (ch = plaintext[i]) != '\0'; ++i)
{
if (!isalpha(ch))
{
cipherText[i] = ch;
ciphertext[i] = ch;
continue;
}
// lowercase char in plaintext remains lowercase in the cipher text, same with uppercase char
// lowercase char in plaintext remains lowercase in the ciphertext, same with uppercase char
if (islower(ch))
cipherText[i] = tolower(key[ch - 'a']);
ciphertext[i] = tolower(key[ch - 'a']);
else
cipherText[i] = key[ch - 'A'];
ciphertext[i] = key[ch - 'A'];
}
cipherText[size] = '\0';
return cipherText;
ciphertext[size] = '\0';
return ciphertext;
}

// substitution_decrypt: decrypt the given plaintext with the given key
char *substitution_decrypt(const char *cipherText, const char *key)
// substitution_decrypt: decrypt the given ciphertext with the given key
char *substitution_decrypt(const char *ciphertext, const char *key)
{
int size = strlen(cipherText);
char *plainText = (char *) malloc(size+1);
int size = strlen(ciphertext);
char *plaintext = (char *) malloc(size + 1);

if (plainText == NULL)
if (plaintext == NULL)
return NULL;

char ch;
for (int i = 0; (ch = cipherText[i]) != '\0'; ++i)
for (int i = 0; (ch = ciphertext[i]) != '\0'; ++i)
{
if (!isalpha(ch))
{
plainText[i] = ch;
plaintext[i] = ch;
continue;
}

if (islower(ch))
plainText[i] = strchr(key, toupper(ch)) - key + 'a';
plaintext[i] = strchr(key, toupper(ch)) - key + 'a';
else
plainText[i] = strchr(key, ch) - key + 'A';
plaintext[i] = strchr(key, ch) - key + 'A';
}
plainText[size] = '\0';
return plainText;
plaintext[size] = '\0';
return plaintext;
}
78 changes: 78 additions & 0 deletions src/ciphers/vigenere.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#include "ciphers.h"

#include <ctype.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>


// valid_vigenere_key: return true if key is an all alphabet string, else false
bool valid_vigenere_key(const char *key)
{
for (int i = 0; key[i] != '\0'; ++i)
if (!isalpha(key[i]))
return false;
return true;
}

/*
Assume caller passes a valid all-alphabetical and capitalized string
*/

// vigenere_encrypt: encrypt the given plaintext with the given key
char *vigenere_encrypt(const char *plaintext, const char *key)
{
int N = strlen(key);
int size = strlen(plaintext);
char *ciphertext = (char *) malloc(size + 1);

if (ciphertext == NULL)
return NULL;

char ch;
for (int i = 0; (ch = plaintext[i]) != '\0'; ++i)
{
if (!isalpha(ch))
{
ciphertext[i] = ch;
continue;
}

int asciishift = (isupper(ch) ? 'A' : 'a');
char charPos = ch - asciishift;
int shift = key[ i % N ] - 'A';

ciphertext[i] = (charPos + shift) % 26 + asciishift;
}
ciphertext[size] = '\0';
return ciphertext;
}

// vigenere_decrypt: decrypt the given ciphertext with the given key
char *vigenere_decrypt(const char *ciphertext, const char *key)
{
int N = strlen(key);
int size = strlen(ciphertext);
char *plaintext = (char *) malloc(size + 1);

if (plaintext == NULL)
return NULL;

char ch;
for (int i = 0; (ch = ciphertext[i]) != '\0'; ++i)
{
if (!isalpha(ch))
{
plaintext[i] = ch;
continue;
}

int asciishift = (isupper(ch) ? 'A' : 'a');
char charPos = ch - asciishift;
int shift = key[ i % N ] - 'A';

plaintext[i] = (charPos - shift + 26) % 26 + asciishift;
}
plaintext[size] = '\0';
return plaintext;
}
Loading

0 comments on commit 1c4fc71

Please sign in to comment.