2015-10-30 3 views
1

Я пытаюсь зашифровать и расшифровать сообщение, используя кодовую фразу и квадрат vigenere, хранящийся в массиве. Я могу зашифровать сообщение успешно, но я не могу решить, как его расшифровать после этого. Есть идеи?Расширение Vigenere Square в C

#include <stdio.h> 
#include <string.h> 
#include <ctype.h> 

void encrypt(char *text, char *pass, int n, int m, char *vs); 
void decrypt(char *text, char *pass, int n, int m, char *vs); 
void vigsq(char *vs); 

main() 
{ 
    char text[] = "HELLOWORLD"; 
    char pass[] = "MAGIC"; 
    int n, m; 
    char vs[26*26]; 
    char *vsPointer, *textPointer, *passPointer; 
    char command; 
    char inputfile[10]; 
    char outputfile[10]; 
    //printf("Please enter e/d, pass phrase, input file, output file:"); 
    //scanf("%c, %s, %s, %s", &command, &pass, &inputfile, &outputfile); 
    vsPointer = vs; 
    textPointer = text; 
    passPointer = pass; 
    vigsq(vsPointer); 
    //printf("%c, %s, %s, %s\n", command, pass, inputfile, outputfile); 

    n = strlen(text); 
    m = strlen(pass); 
    //printf("%d, %d", n, m); 
    encrypt(textPointer, passPointer, n, m, vsPointer); 
    printf("%s\n", text); 
    decrypt(textPointer, passPointer, n, m, vsPointer); 
    printf("%s\n", text); 
} 

void encrypt(char *text, char *pass, int n, int m, char *vs) 
{ 
    int i; 
    int ascii1; 
    int ascii2; 
    int passcount = 0; 
    char encrypt; 
    for (i = 0; i < n; i++) 
    { 
     ascii1 = (int)text[i]; 
     ascii2 = (int)pass[passcount]; 
     ascii1 = ascii1 - 64; 
     ascii2 = ascii2 - 64; 
     encrypt = vs[((ascii1 -1)*26) + (ascii2)]; 
     // printf("%d, %d, %c\n", ascii1, ascii2, encrypt); 
     text[i] = encrypt; 
     passcount++; 
     if (passcount == m) 
     { 
      passcount = 0; 
     } 
    } 
} 

void decrypt(char *text, char *pass, int n, int m, char *vs) 
{ 
    int i; 
    int ascii1; 
    int ascii2; 
    int passcount = 0; 
    char decrypt; 
    for (i = 0; i < n; i++) 
    { 
     ascii1 = (int)text[i]; 
     ascii2 = (int)pass[passcount]; 
     ascii1 = ascii1 - 64; 
     ascii2 = ascii2 - 64; 
     decrypt = vs[//Don't know what to put here]; 
     //printf("%d, %d, %c\n", ascii1, ascii2, decrypt); 
     text[i] = decrypt; 
     passcount++; 
     if (passcount == m) 
     { 
      passcount = 0; 
     } 
    }  
} 

void vigsq(char *vs) 
{ 
    char alphabet[] = {'A','B','C','D','E','F','G','H','I','J','K', 
     'L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'}; 

    int a = 0, i, j, count = 0; 
    for(i = 1; i <= 26*26; i++) 
    {       
     vs[i] = alphabet[a]; 
     a++; 
     if (i % 26 == 0) 
     { 
      count++; 
      a = count; 
     } 
     if (a == 26)   
     { 
      a = 0; 
     }    
    } 
} 

(Просьба игнорировать материал ввода/вывода я буду реализующим позже.) Спасибо за помощь :)

+0

Голосование, чтобы закрыть * (Вопросы, ищущих отладки помощи («почему не этот код работает?») Должен включать в себя желаемое поведение, конкретную проблему или ошибку и кратчайший код, необходимый для воспроизведения его в самом вопросе. Вопросы без четкой постановки проблемы не полезны другим читателям.) * –

ответ

1

При кодировании письма, вы смотрите письмо в строке письмо с паролем m[j] и столбцы текстовой буквы p[i] в таблице Vigenère. Когда вы декодируете, вы должны найти столбец, в котором зашифрованная буква c[i] находится в строке буквы пароля. В коде шифрование - это простой поиск в таблице, но дешифрования нет.

Вам действительно не нужен стол. Алгоритмически вы можете описать шифр Vigenère. Шифр - это всего лишь шифр Ceasar – простой сдвиг письма & ndash, где сумма сдвига определяется текущей буквой в пароле. Шифрование средства перемещения вперед, дешифрование средства сдвига в обратном направлении:

c[i] = (p[i] + m[j]) % 26 
p[i] = (c[i] - m[j]) & 26 

В этой формуле, буквы представлены числами 0 (A) до 25 (Z). Помните, что индексы начинаются с нуля в C. Это также означает, что вы должны вычесть 'A' (65) из ваших писем, а не 64.

Поскольку дешифрование и шифрование настолько схожи, вы можете реализовать их в одной функции с помощью флаг для режима работы:

enum { 
    Encrypt, 
    Decrypt 
};      

void vigenere(char *text, const char *pass, int mode) 
{ 
    int i; 
    int passcount = 0; 

    for (i = 0; text[i] != '\0'; i++) 
    { 
     int ascii1 = text[i] - 'A'; 
     int ascii2 = pass[passcount] - 'A'; 

     // Negate shift for decryption 
     if (mode == Decrypt) ascii2 = -ascii2; 

     text[i] = 'A' + (26 + ascii1 + ascii2) % 26; 

     passcount++; 
     if (pass[passcount] == '\0') passcount = 0; 
    } 
} 

Вещи отметить:

  • добавление 26 в формуле для предотвращения взятия остатка отрицательного числа, которое будет давать отрицательное число в C .
  • Код работает только в том случае, если все символы являются прописными буквами.
  • Явные длины строк опущены; вы можете проверить, достигли ли вы конца строки C, проверив, что текущий символ является завершающим нулем, '\0'.

Вызов этот код так:

int main() 
{ 
    char text[] = "HELLOWORLD"; 
    const char *pass = "MAGIC"; 

    printf("plain %s\n", text);  

    vigenere(text, pass, Encrypt); 
    printf("crypt %s\n", text); 

    vigenere(text, pass, Decrypt); 
    printf("decpt %s\n", text); 

    return 0; 
} 
+0

Большое спасибо за вашу помощь! Оно работает :) – George