简体   繁体   English

C中的Vigenere平方解密

[英]Vigenere Square Decryption in C

I'm trying to encrypt and decrypt a message using a passphrase and a vigenere square stored in an array. 我正在尝试使用存储在数组中的密码短语和vigenere正方形来加密和解密消息。 I am able to encrypt the message successfully however I can't work out how to decrypt it again afterwards. 我能够成功加密消息,但是以后无法解决如何解密的问题。 Any ideas? 有任何想法吗?

#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;
        }               
    }
}

(Please ignore the I/O stuff I'll be implementing that later.) Thanks for the help :) (请忽略稍后将要实现的I / O内容。)感谢您的帮助:)

When you encode a letter, you look up letter at the the row of the password letter m[j] and the columns of the plaintext letter p[i] in the Vigenère table. 对字母进行编码时,可以在Vigenère表中的密码字母m[j]和明文字母p[i]的列中查找字母。 When you decode, you must find the column where encrypted letter c[i] is in the row of the password letter. 解码时,必须在密码字母的行中找到加密字母c[i]的列。 In code, encrypting is a simple table lookup, but decrypting is not. 在代码中,加密是简单的表查找,但解密不是。

You don't really need the table, though. 不过,您实际上不需要表。 You can describe the Vigenère cipher algorithmically. 您可以通过算法描述Vigenère密码。 The cipher really is just a Ceasar cipher – a simple letter shift &ndash, where the shift amount is determined by the current letter in the password. 密码实际上只是Ceasar密码-简单的字母移位&ndash,其中移位量由密码中的当前字母确定。 Encrypting means shifting forwards, decrypting means shifting backwards: 加密意味着向前移动,解密意味着向后移动:

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

In this formula, the letters are represented by the numbers 0 (A) to 25 (Z). 在该公式中,字母由数字0(A)至25(Z)表示。 Remember that indices start at zero in C. That also means that you have to subtract 'A' (65) from your letters, not 64. 请记住,索引在C中从零开始。这也意味着您必须从字母中减去'A' (65),而不是64。

Because decryption and encryption are so similar, you can implement them in a single function with a flag for the mode of operation: 因为解密和加密是如此相似,所以您可以在一个带有操作模式标志的函数中实现它们:

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;
    }
}

Things to note: 注意事项:

  • The addition of 26 in the formula is to prevent taking the remainder of a negative number, which will yield a negative number in C. 公式中加26是为了防止取负数的余数,而余数将在C中产生负数。
  • The code works only if all characters are upper-case letters. 该代码仅在所有字符均为大写字母时才有效。
  • The explicit string lengths have been omitted; 显式的字符串长度已被省略; you can test whether you have reached the end of a C string by checking whather the current character is the terminating null, '\\0' . 您可以通过检查当前字符是否为终止null '\\0'来测试是否已到达C字符串的末尾。

Call this code like so: 像这样调用此代码:

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;  
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM