close

簡易版Vigenère cipher程式撰寫

維吉尼亞密碼(Vigenère cipher)是由一些偏移量不同的凱撒密碼所組成。

為了生成密碼,需要使用0到9的數字。

例如,假設明文為:

HEISREADING

選擇某一關鍵詞並重複而得到密鑰,如關鍵詞為0471781時,密鑰為:

04717810471

對於明文的第一個字母H,對應密鑰的第一個數字0,首先把H換成0到25的數字的話為7,則密文的第一個字母為: ( 7 + 0 ) mod 26 = 7 ,數字7再換算回英文字母的H。類似地,明文第二個字母為E,對應密鑰的第一個數字4,則密文的第二個字母為: ( 4 + 4 ) mod 26 = 8 ,數字8再換算回英文字母的I。以此類推,可以得到:

       明文:HEISREADING

       密鑰:04717810471

       密文:HIPTYMBDMUH

解密的過程則與加密相反。例如:根據密文第一個字母H所對應的密鑰的第一個數字0,首先把H換成0到25的數字的話為7,則明文的第一個字母為: ( 7 – 0 ) mod 26 = 7 ,數字7再換算回英文字母的H。類似地,密文第二個字母為I,對應密鑰的第一個數字4,則密文的第二個字母為: ( 8 - 4 ) mod 26 = 4 ,數字4再換算回英文字母的E。以此類推便可得到明文。

以算式來寫的話為:

Ci = Pi +ki ( mod 26 )

Pi = Ci - ki ( mod 26 )

 

以下為程式碼部分:

/* Vigenere cipher */ 
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

int main(){
    char *data;                                     //輸入    
    char *target=malloc(100 * sizeof(char));        //輸出 
    int key[7]={0,4,7,1,7,8,1};                     //金鑰 
    FILE *fPtr;
    unsigned long leng, count, i;
    int ch;
    
    //讀檔 
    //註:必須先建立source.txt 
    fPtr = fopen("source.txt", "r");
    fseek(fPtr, 0, SEEK_END);
    leng = ftell(fPtr);
    fseek(fPtr, 0, SEEK_SET);
    data = (char *) malloc((leng + 1) * sizeof(char));
    fread(data, 1, leng, fPtr);  
    fclose(fPtr);
    data[leng] = '\0';
      
    printf("\n讀入檔案: %s\n\n", data);
    
    printf("請選擇加密或解密 1.加密 2.解密 :");
    scanf("%d",&ch);
    switch(ch){
        case 1:
            //轉小寫 
            count = 0;
            for (i=0; i<leng; i++)
            if (isalpha(data[i])) data[count++] = tolower(data[i]);
            data[count] = '\0';
            //printf("\n明文: %s\n\n", data);
              
            // 將字串編碼
            i = 0; 
            while (data[i] != '\0') {
            if (isalpha(data[i])){
            target[i]=data[i] - 97;
            target[i]=(target[i]+key[i%7])%26;
            target[i]=target[i]+65;
            } 
            else target[i] = data[i]; 
            i++; 
            }
            target[i] = '\0';
            printf("\n密文: %s\n\n", target); 
            break;
        case 2:
            //轉大寫 
            count = 0;
            for (i=0; i<leng; i++)
            if (isalpha(data[i])) data[count++] = toupper(data[i]);
            data[count] = '\0';
            //printf("\n密文: %s\n\n", data);
              
            // 將字串編碼
            i = 0; 
            while (data[i] != '\0') {
            if (isalpha(data[i])){
            target[i]=data[i] - 65;
            target[i]=(target[i]+26-key[i%7])%26;
            target[i]=target[i]+97;
            } 
            else target[i] = data[i]; 
            i++; 
            }
            target[i] = '\0';
            printf("\n明文: %s\n\n", target); 
            break;
        default:
            printf("\n錯誤\n");
            break;    
    }
    
    //輸出檔案 
    fPtr = fopen("result.txt", "w");
    fwrite(target, 1, count, fPtr);
    fclose(fPtr);
    
    return 0;
}

 

加密:

未命名.png

解密:

未命名1.png

arrow
arrow

    ATing 發表在 痞客邦 留言(0) 人氣()