我用C写了仿射密码的代码。它正确地加密/解密了大写字母,但错误地加密/解密了小写字母

问题描述 投票:0回答:1
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

# define MAX_LENGTH 100 

int GCD(int a, int b) {
    if(b == 0) {
        return a;
    }
    GCD(b, a%b);
}

struct Pair{
    int x, y;
};

struct Pair Extended_Euclidean_Algorithm(int a, int b) {
    if(b == 0) {
        struct Pair answer;
        answer.x = 1;
        answer.y = 0;
        return answer;
    }

    struct Pair small_answer = Extended_Euclidean_Algorithm(b, a%b);
    struct Pair answer;
    answer.x = small_answer.y;
    answer.y = small_answer.x - (a/b)*small_answer.y;

    return answer;
}

void Encryption(char Plaintext[], char Ciphertext[], int a, int b) {
    int temp_1, temp_2, i;
    i = 0;

    while(Plaintext[i] != '\0') {
        temp_1 = Plaintext[i];

        if(temp_1 >= 65 && temp_1 <= 90) {
            temp_2 = (a*temp_1 + b)%26;
            Ciphertext[i++] = 'A' + temp_2;
        }else if(temp_1 >= 97 && temp_1 <= 122) {
            temp_2 = (a*temp_1 + b)%26;
            Ciphertext[i++] = 'a' + temp_2;
        } else if(temp_1 == 32) {
            Ciphertext[i++] = ' ';
        }
    }

    Ciphertext[i] = '\0';
}

void Decryption(char Ciphertext[], char Decrypted_Plaintext[], int a, int b) {
    struct Pair inverse;
    int temp_a_inverse;
    inverse = Extended_Euclidean_Algorithm(26, a);
    temp_a_inverse = inverse.y;

    if(temp_a_inverse < 0) {
        temp_a_inverse = temp_a_inverse + 26;
    }

    int temp_1, temp_2, i;
    i = 0;

    while(Ciphertext[i] != '\0') {
        temp_1 = Ciphertext[i];

        if(temp_1 >= 65 && temp_1 <= 90) {
            temp_2 = ((temp_1 + 26 - b)*temp_a_inverse)%26;
            Decrypted_Plaintext[i++] = 'A' + temp_2;
        } else if(temp_1 >= 97 && temp_1 <= 122) {
            temp_2 = ((temp_1 + 26 - b)*temp_a_inverse)%26;
            Decrypted_Plaintext[i++] = 'a' + temp_2;
        } else if(temp_1 == 32) {
            Decrypted_Plaintext[i++] = ' ';
        }
    }

    Decrypted_Plaintext[i] = '\0';
}

int main() {
    char Plaintext[MAX_LENGTH], Ciphertext[MAX_LENGTH], Decrypted_Plaintext[MAX_LENGTH];
    char c;
    printf("Enter the plaintext: ");
    int i = 0;

    while((c = getchar()) != '\n') {
        Plaintext[i] = c;
        i++;
    }

    Plaintext[i] = '\0';
    printf("Choose any number from the given numbers: ");
    int a, b, temp_a;

    for(int j = 1; j <= 26; j++) {
        temp_a = GCD(26, j);

        if(temp_a == 1){
            printf("%d |", j);
        }
    }

    printf("\n");
    scanf("%d", &a);
    srand(time(0));
    b = (rand()%(26)) + 1;

    Encryption(Plaintext, Ciphertext, a, b); //Encrypting Plaintext
    Decryption(Ciphertext, Decrypted_Plaintext, a, b); //Decrypting Ciphertext
    printf("The Plaintext is: %s\n", Plaintext);
    printf("a = %d || b = %d\n", a, b);
    printf("The Ciphertext is: %s\n", Ciphertext);
    printf("The Decrypted Plaintext is: %s\n", Decrypted_Plaintext);
    return 0;
}

我已经用C编写了仿射密码的代码。它正确地加密/解密了大写字母,但错误地加密/解密了小写字母所以,当我测试它的大写字母时,它工作正常,但是当我尝试测试它的小写字母时每次都会失败。那么,谁能告诉我哪里出错了。

c encryption cryptography
1个回答
0
投票

使用大写单词和小写单词尝试代码会导致小写单词出现不良行为。

craig@Vera:~/C_Programs/Console/Decipher/bin/Release$ ./Decipher 
Enter the plaintext: HELLO
Choose any number from the given numbers: 1 |3 |5 |7 |9 |11 |15 |17 |19 |21 |23 |25 |
3
The Plaintext is: HELLO
a = 3 || b = 12
The Ciphertext is: ULGGP
The Decrypted Plaintext is: HELLO
craig@Vera:~/C_Programs/Console/Decipher/bin/Release$ ./Decipher 
Enter the plaintext: Hello
Choose any number from the given numbers: 1 |3 |5 |7 |9 |11 |15 |17 |19 |21 |23 |25 |
3
The Plaintext is: Hello
a = 3 || b = 14
The Ciphertext is: Wfaaj
The Decrypted Plaintext is: Hmttw

即使在进行一些简单的调试时,我也无法用小写字符来确定确切的行为问题,除了在小写 if/else 块中进行的“temp_2”计算乘法/计算似乎存在问题。加密和解密。

由于最终结果是一次选择一个字符并对该字符应用加密/偏移量计算,因此最简单的解决方案是始终将该字符视为大写字符,执行加密或解密,然后计算其偏移量小写字符“a”而不是大写字符“A”。

以下是展示重构步骤的代码块。

首先,根据好评,“最大公约数”函数被更正为从函数的递归调用中返回一个整数。

    int GCD(int a, int b)
{
    if(b == 0)
    {
        return a;
    }
    return GCD(b, a%b);     /* Refactored per good comments */
}

然后重构加密和解密函数中的公式,将字符处理为大写值,然后添加“字符'a'”偏移量。

void Encryption(char Plaintext[], char Ciphertext[], int a, int b)
{
    int temp_1, temp_2, i;
    i = 0;

    while(Plaintext[i] != '\0')
    {
        temp_1 = Plaintext[i];

        if(temp_1 >= 65 && temp_1 <= 90)
        {
            temp_2 = (a*temp_1 + b)%26;
            Ciphertext[i++] = 'A' + temp_2;
        }
        else if(temp_1 >= 97 && temp_1 <= 122)
        {
            temp_2 = (a*(temp_1 - 32) + b) % 26;    /* Refactored to treat character as uppercase       */
            Ciphertext[i++] = 'a' + temp_2;         /* Offset value is applied to lowercase reference   */
        }
        else if(temp_1 == 32)
        {
            Ciphertext[i++] = ' ';
        }
    }

    Ciphertext[i] = '\0';
}

void Decryption(char Ciphertext[], char Decrypted_Plaintext[], int a, int b)
{
    struct Pair inverse;
    int temp_a_inverse;
    inverse = Extended_Euclidean_Algorithm(26, a);
    temp_a_inverse = inverse.y;

    if(temp_a_inverse < 0)
    {
        temp_a_inverse = temp_a_inverse + 26;
    }

    int temp_1, temp_2, i;
    i = 0;

    while(Ciphertext[i] != '\0')
    {
        temp_1 = Ciphertext[i];

        if(temp_1 >= 65 && temp_1 <= 90)
        {
            temp_2 = ((temp_1 + 26 - b)*temp_a_inverse)%26;
            Decrypted_Plaintext[i++] = 'A' + temp_2;
        }
        else if(temp_1 >= 97 && temp_1 <= 122)
        {
            temp_2 = ((temp_1 - 32 + 26 - b)*temp_a_inverse)%26;    /* Refactored to treat character as uppercase       */
            Decrypted_Plaintext[i++] = 'a' + temp_2;                /* Offset value is applied to lowercase reference   */
        }
        else if(temp_1 == 32)
        {
            Decrypted_Plaintext[i++] = ' ';
        }
    }

    Decrypted_Plaintext[i] = '\0';
}

以下是一些测试,显示了此重构后的终端输出。

craig@Vera:~/C_Programs/Console/Decipher/bin/Release$ ./Decipher 
Enter the plaintext: Hello
Choose any number from the given numbers: 1 |3 |5 |7 |9 |11 |15 |17 |19 |21 |23 |25 |
3
The Plaintext is: Hello
a = 3 || b = 14
The Ciphertext is: Wniir
The Decrypted Plaintext is: Hello
craig@Vera:~/C_Programs/Console/Decipher/bin/Release$ ./Decipher 
Enter the plaintext: Welcome home
Choose any number from the given numbers: 1 |3 |5 |7 |9 |11 |15 |17 |19 |21 |23 |25 |
7
The Plaintext is: Welcome home
a = 7 || b = 21
The Ciphertext is: Gkhwcok fcok
The Decrypted Plaintext is: Welcome home

这可能不是像希望的那样优雅的解决方案,但它确实提供了一个简化的解决方案,通过后退一步来确定可以简化问题的地方。

从中得到的收获可能是深入研究一些“C”教程,因为它们与字符数组、加密方法和 ASCII 字符集有关。

© www.soinside.com 2019 - 2024. All rights reserved.