简体   繁体   中英

Affine Cipher in C doesn't work correctly

Disclaimer: Whatever is below, it's related to Affine Cipher. For whomever doesn't know it, it's a encrypting method that uses a mathematical function Ax+B to shift each letter in a given plaintext according to the letter's index in the alphabet.

I've written a code that encrypts and decrypts a given plaintext or ciphered text using Affine Cipher. It consists of these three functions:

char *encryption(char Plaintext[MAXSIZE], int A, int B);
int modularinverse(int number, int modulo);
char *decryption(char Ciphered[MAXSIZE], int A, int B, int inverse);

The part that concerns me sites in the decryption function. Around three or four letters are miss-calculated.

Let's consider the following plaintext: "abcde"

Using the encryption function:

char *encryption(char Plaintext[MAXSIZE], int A, int B) {
    static char Ciphered[MAXSIZE];
    int i;
    int y;
    int index;
    for (i = 0; i < strlen(Plaintext) - 1; i++) {
        if (Plaintext[i] == ' ') {
            Ciphered[i] = ' ';
        } else {
            index = (int)Plaintext[i] - 'a';
            y = (A * index + B) % 26;
            Ciphered[i] = (char)y + 97;
        }
    }
    return Ciphered;
}

it turns the plaintext into: "fmtah". Which is correct.

Decrypting the plaintext should obviously give: "abcde". But instead, it gives: "abc J e".

char *decryption(char Ciphered[MAXSIZE], int A, int B, int inverse) {
    static char NewPlaintext[MAXSIZE];
    int i;
    unsigned int x;
    int y;
    int index;
    for (i = 0; i < strlen(Ciphered); i++) {
        if (Ciphered[i] == ' ') {
            NewPlaintext[i] = ' ';
        } else {
            index = (int)Ciphered[i] - 'a';
            x = inverse * (index - B) % 26;
            NewPlaintext[i] = (char)x + 97;
        }
    }
    return NewPlaintext;
}

The letter d is miss-calculated for a reason I don't know. Printing the values of variables index , inverse , B and x for each one of the characters fmtah will respectively return this:

5         15        5         0
12        15        5         1
19        15        5         2
0         15        5         -23
7         15        5         4

First column represents indexes of the letters fmtah .

Second column represents the inverse of A=7 , which is 15 . (Totally harmful, you may ignore it).

Third column represents B which is a constant for now (You may ignore it).

Fourth column represents x which is the result of inverse*(index-B) % 26 . Adding 97 (ASCII number of 'a') to each of number in this column will result to the ASCII number of each letter.

ie 0+97 = 97 which is 'a'. By consequence Decryption(f)=a.

But if you can notice. the result of x for the letter 'a' is -23. -23+97=74 which is J in ASCII. It should rather be 100 as it's the ASCII number for d. Therefore the result of x should rather be 3, not -23.

The reason behind this miss-calculation is buzzing me and I haven't figured out what's causing it.

Your code has several problems:

  • you stop before the end of the string: i<strlen(Plaintext)-1
  • you do not null terminate the destination strings.
  • your return a pointer to static storage: only one string can be encrypted/decyphered at a time.
  • depending on the values, you may take the modulo of negative numbers, which will be negative too. Use this instead: x = ((inverse * (index - B) % 26) + 26) % 26;

Your code has few issues which are causing this strange behavior;

  1. Don't use int type if you are dealing with character. Use char
  2. In decryption() handle if the value of x is negative.

you can modify your decryption() like this.

char *decryption(char Ciphered[MAXSIZE],int A, int B, int inverse)
{
    static char NewPlaintext[MAXSIZE];
    char x;
    char index;
    for(int i=0;i<strlen(Ciphered);i++)
    {
        if(Ciphered[i]==' ')
        {
            NewPlaintext[i]=' ';
        }
        else
        {
            index=(int)Ciphered[i] - 'a';
            x=inverse*(index-B) % 26;
            if(x < 0)
            {
                // add 26 to take care of negative values; since you are using %
                x += 26;
            }
            NewPlaintext[i]=(char)x+97;
        }
    }
    return NewPlaintext;
}

I tested it few entries and it works fine.

Hope this helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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