Vigenère Cipher Implementation
The Vigenère cipher is a form of polyalphabetic substitution to encrypt alphabetic text by using a keyword. The Vigenère cipher is easy to understand and implement. It consists of several Caesar ciphers in sequence with different shift values.
In a Caesar cipher, each letter of the alphabet is shifted by some places; for example, in a Caesar cipher of shift 3, A
would become D
, B
would become E
, Y
would become B
, and so on.
A table of alphabets is used to encrypt, consisting of the alphabet written out 26 times in different rows. Each alphabet shifted cyclically to the left than the previous alphabet, corresponding to the 26 possible Caesar ciphers. At different points in the encryption process, the cipher uses a different alphabet from one of the rows. The alphabet used at each point depends on a repeating keyword.
For example, suppose that the plaintext to be encrypted is: ATTACKATDAWN
.
The person sending the message chooses a keyword and repeats it until it matches the plaintext’s length, for example, the keyword “LEMON”: LEMONLEMONLE
.
Each row starts with a key letter. The remainder of the row holds the letters A
to Z
(in shifted order). Although there are 26 key rows shown, you will only use as many keys (different alphabets) as there are unique letters in the key string, here just 5 keys, {L, E, M, O, N}
. We will take successive letters of the key string for successive letters of the message and encipher each message letter using its corresponding key row. Choose the next letter of the key, go along that row to find the column heading that matches the message character; the letter at the intersection of [key-row, msg-col] is the enciphered letter.
For example, the first letter of the plaintext, A
, is paired with L
, the first letter of the key. So, use row L
and column A
of the Vigenère square, namely L
. Similarly, for the second letter of the plaintext, the second letter of the key is used; the letter at row E and column T
is X
. The rest of the plaintext is enciphered similarly:
Plaintext: ATTACKATDAWN
Key: LEMONLEMONLE
Ciphertext: LXFOPVEFRNHR
Decryption is performed by going to the row in the table corresponding to the key, finding the position of the ciphertext letter in this row, and then using the column’s label as the Plaintext. For example, in row L
(from LEMON), the ciphertext L
appears in column A
, the first plaintext letter. Next, we go to row E
(from LEMON), locate the ciphertext X
, which is found in column T
; thus, T
is the second plaintext letter.
Implementation:
C
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
#include <stdio.h> #include <ctype.h> #include <stdlib.h> #include <string.h> int table[26][52]; void init_matrix() { int i, j; for (i = 0; i < 26; i++) { for (j = 0; j < 26 - i; j++) { table[i][j] = j + i; } for (j = 26 - i; j < 26; j++) { table[i][j] = (j + i) - 26; } for (j = 26; j < 52 - i; j++) { table[i][j] = j + i - 26; } for (j = 52 - i; j < 52; j++) { table[i][j] = (j + i) - 52; } } } void encrypt(char *filename, char *key, int n) { int i, count = 0, size = 0; char ch; FILE *in, *out; in = fopen(filename, "r"); if (in == NULL) { printf("Cannot open source file.\n"); exit(1); } out = fopen("CipherText.txt", "w+"); if (out == NULL) { printf("Cannot open destination file.\n"); exit(1); } fseek(in, 0, SEEK_END); // seek to end of the file size = ftell(in); // get the current file pointer fseek(in, 0, SEEK_SET); // seek back to the beginning of the file for (i = n; i < size - 1; i++) { key[i] = key[i - n]; } while (count != size) { ch = getc(in); if (isupper(ch)) { putc(table[key[count] - 65][ch - 65] + 65, out); } else { putc(table[key[count] - 65][ch - 97 + 26] + 97, out); } count++; } fclose(in); fclose(out); } void decrypt(char *key) { int i, j, size = 0, count = 0; char ch; FILE *in, *out; in = fopen("CipherText.txt", "r"); if (in == NULL) { printf("Cannot open encrypted file.\n"); exit(1); } out = fopen("DecryptedText.txt", "w+"); if (out == NULL) { printf("Cannot open destination file.\n"); exit(1); } fseek(in, 0, SEEK_END); // seek to end of the file size = ftell(in); // get the current file pointer fseek(in, 0, SEEK_SET); // seek back to the beginning of the file while (count != size) { ch = getc(in); if (isupper(ch)) { for (i = 0; i < 26; i++) { if (table[key[count] - 65][i] == ch - 65) { fputc(i + 65, out); } } } else { for (i = 26; i < 52; i++) { if (table[key[count] - 65][i] == ch - 97) { fputc(i + 97 - 26, out); } } } count++; } fclose(out); fclose(in); } // main function int main() { char filename[] = "PlainText.txt"; char key[] = "techiedelight"; int n = strlen(key); int j; // convert the key to uppercase for (j = 0; j < n; j++) { key[j] = toupper(key[j]); } init_matrix(); // encrypt using Vigenère cipher encrypt(filename, key, n); // decrypt using Vigenère cipher decrypt(key); return 0; } |
Input file: PlainText.txt
Encrypted file: CipherText.txt
Decrypted file: DecryptedText.txt
That’s all about Vigenère cipher implementation.
Reference: https://en.wikipedia.org/wiki/Vigen%C3%A8re_cipher
Thanks for reading.
To share your code in the comments, please use our online compiler that supports C, C++, Java, Python, JavaScript, C#, PHP, and many more popular programming languages.
Like us? Refer us to your friends and support our growth. Happy coding :)