前言? ??
作業要求:明文中的空格在密文中也有對應空格,明文中的大小寫在密文中也有對應大小寫。
一、維吉尼亞(Vigenère)密碼原理及介紹
在一個凱撒密碼中,字母表中的每一字母都會作一定的偏移,例如偏移量為3時,A就轉換為了D、B轉換為了E……而維吉尼亞密碼則是由一些偏移量不同的愷撒密碼組成。
在生成密碼的時候,可以通過查表的方式(維吉尼亞密碼表),通過密鑰,來確定明文所對應的密文。
這一表格包括了26行字母表,每一行都由前一行向左偏移一位得到。
例如,假設明文為:
GOODSTUDY
密鑰為:
HNUN
由于密鑰比明文短,因此需要重復密鑰,直至密鑰和明文一樣長。對于密鑰來說,每個字母代表的偏移量為該字母在字母表中的位置
對于第一個字母G,對應密鑰第一個字母H,那么由表格中的G行H列加密得到字母N,以此類推,可以得到:
明文:GOODSTUDY ? ?密鑰:HNUN ? ?密文:NBIQZGOQF
二、加密/解密算法介紹
1.加密算法
主要思路:通過ASCII碼來計算偏移量
附ASCII碼對照表:
代碼如下:
int Encryption(char* Plaintext, char* key) //加密算法 { int i = 0, j = strlen(key), k = strlen(Plaintext),m=0; char result[MAXSIZE] = {0}; for (i = 0; i < k; i++) { if (Plaintext[i] != ' '&& Plaintext[i] >= 'a' && Plaintext[i] <= 'z')//明文是小寫字母 { if (key[m % j] >= 'a' && key[m % j] <= 'z')//密鑰為小寫字母 { result[i] = (Plaintext[i] + key[m % j] - 2 * 'a') % 26 + 'a'; } else if (key[m % j] >= 'A' && key[m % j] <= 'Z')//密鑰為大寫字母 { result[i] = (Plaintext[i] + key[m % j] - 'A'-'a') % 26 + 'a'; } m++; } else if (Plaintext[i] != ' ' && Plaintext[i] >= 'A' && Plaintext[i] <= 'Z')//明文是大寫字母 { if (key[m % j] >= 'a' && key[m % j] <= 'z')//密鑰為小寫字母 { result[i] = (Plaintext[i] + key[m % j] - 'a' - 'A') % 26 + 'A'; } else if (key[m % j] >= 'A' && key[m % j] <= 'Z')//密鑰為大寫字母 { result[i] = (Plaintext[i] + key[m % j] - 'A' - 'A') % 26 + 'A'; } m++; } else result[i] = ' '; } printf("加密后的密文為:%s\n",result); return 0; }
思路介紹:由于要求<明文中的空格在密文中也有對應空格,明文中的大小寫在密文中也有對應大小寫>,所以需要判斷輸入的明文是否有空格符和密鑰中字母的大小寫。
key[m%j]是為了確保在明文/密文比密鑰長時重復密鑰。
2.解密算法
主要思路:加密算法的逆過程
代碼如下(示例):
int Decrypt(char* Ciphertext, char* key)//解密算法 { int i = 0, j = strlen(key), k = strlen(Ciphertext),m=0; char result[MAXSIZE] = { 0 }; for (i = 0; i < k; i++) { if (Ciphertext[i] != ' ' && Ciphertext[i] >= 'a' && Ciphertext[i] <= 'z')//明文是小寫字母 { if (key[m % j] >= 'a' && key[m % j] <= 'z')//密鑰為小寫字母 { result[i] = (Ciphertext[i] + 26 - (key[m % j] - 'a') - 'a') % 26 + 'a'; } else if (key[m % j] >= 'A' && key[m % j] <= 'Z')//密鑰為大寫字母 { result[i] = (Ciphertext[i] + 26 - (key[m % j] - 'A') - 'a') % 26 + 'a'; } m++; } else if (Ciphertext[i] != ' ' && Ciphertext[i] >= 'A' && Ciphertext[i] <= 'Z')//明文是大寫字母 { if (key[m % j] >= 'a' && key[m % j] <= 'z')//密鑰為小寫字母 { result[i] = (Ciphertext[i] + 26 - (key[m % j] - 'a') - 'A') % 26 + 'A'; } else if (key[m % j] >= 'A' && key[m % j] <= 'Z')//密鑰為大寫字母 { result[i] = (Ciphertext[i] + 26 - (key[m % j] - 'A') - 'A') % 26 + 'A'; } m++; } else result[i] = ' '; } printf("解密后的明文為:%s\n", result); return 0; }
三、完整代碼展示
#include <stdio.h> #include <string.h> #define MAXSIZE 100 #define KEY 50 int Encryption(char* Plaintext, char* key) //加密算法 { int i = 0, j = strlen(key), k = strlen(Plaintext),m=0; char result[MAXSIZE] = {0}; for (i = 0; i < k; i++) { if (Plaintext[i] != ' '&& Plaintext[i] >= 'a' && Plaintext[i] <= 'z')//明文是小寫字母 { if (key[m % j] >= 'a' && key[m % j] <= 'z')//密鑰為小寫字母 { result[i] = (Plaintext[i] + key[m % j] - 2 * 'a') % 26 + 'a'; } else if (key[m % j] >= 'A' && key[m % j] <= 'Z')//密鑰為大寫字母 { result[i] = (Plaintext[i] + key[m % j] - 'A'-'a') % 26 + 'a'; } m++; } else if (Plaintext[i] != ' ' && Plaintext[i] >= 'A' && Plaintext[i] <= 'Z')//明文是大寫字母 { if (key[m % j] >= 'a' && key[m % j] <= 'z')//密鑰為小寫字母 { result[i] = (Plaintext[i] + key[m % j] - 'a' - 'A') % 26 + 'A'; } else if (key[m % j] >= 'A' && key[m % j] <= 'Z')//密鑰為大寫字母 { result[i] = (Plaintext[i] + key[m % j] - 'A' - 'A') % 26 + 'A'; } m++; } else result[i] = ' '; } printf("加密后的密文為:%s\n",result); return 0; } int Decrypt(char* Ciphertext, char* key)//解密算法 { int i = 0, j = strlen(key), k = strlen(Ciphertext),m=0; char result[MAXSIZE] = { 0 }; for (i = 0; i < k; i++) { if (Ciphertext[i] != ' ' && Ciphertext[i] >= 'a' && Ciphertext[i] <= 'z')//明文是小寫字母 { if (key[m % j] >= 'a' && key[m % j] <= 'z')//密鑰為小寫字母 { result[i] = (Ciphertext[i] + 26 - (key[m % j] - 'a') - 'a') % 26 + 'a'; } else if (key[m % j] >= 'A' && key[m % j] <= 'Z')//密鑰為大寫字母 { result[i] = (Ciphertext[i] + 26 - (key[m % j] - 'A') - 'a') % 26 + 'a'; } m++; } else if (Ciphertext[i] != ' ' && Ciphertext[i] >= 'A' && Ciphertext[i] <= 'Z')//明文是大寫字母 { if (key[m % j] >= 'a' && key[m % j] <= 'z')//密鑰為小寫字母 { result[i] = (Ciphertext[i] + 26 - (key[m % j] - 'a') - 'A') % 26 + 'A'; } else if (key[m % j] >= 'A' && key[m % j] <= 'Z')//密鑰為大寫字母 { result[i] = (Ciphertext[i] + 26 - (key[m % j] - 'A') - 'A') % 26 + 'A'; } m++; } else result[i] = ' '; } printf("解密后的明文為:%s\n", result); return 0; } int main() { int n; char Plaintext[MAXSIZE] = {0}; char Ciphertext[MAXSIZE] = {0}; char key[KEY] = {0}; while (1) { printf("===============\n"); printf(" 1.加密\n"); printf(" 2.解密\n"); printf(" 0.退出\n"); printf("===============\n"); printf("請輸入要執行的操作:"); scanf_s("%d",&n); getchar(); switch (n) { case 1: printf("請輸入明文:"); scanf_s("%[^\n]", Plaintext, MAXSIZE); getchar(); printf("請輸入密鑰:"); scanf_s("%[^\n]", key, KEY); Encryption(Plaintext, key); break; case 2: printf("請輸入密文:"); scanf_s("%[^\n]", Ciphertext, MAXSIZE); getchar(); printf("請輸入密鑰:"); scanf_s("%[^\n]", key, KEY); Decrypt(Ciphertext, key); break; case 0: exit(0); break; } } return 0; }
做了一個菜單方便選擇加密解密。
總結
主要是ASCII碼的運用,對照維吉尼亞密碼表算出每個字母的偏移量,對邏輯要求可能比較高,需要,計算偏移量以及循環密鑰較為繁瑣。
原文地址:https://blog.csdn.net/qq_65057022/article/details/125572544