0

Im Encrypting the Original Messages using XOR algorithm by following code in C program. And Finally it gives another different value that message has encrypted. It should return same length even after the message has encrypted.

But, Using strlen(encrypted) it gives less value than original message length. I couldn't recognize why the length of XOR encrypted message is showing less than the original message length. Please find the following the code to solve my problem.

Thanks in Advance!

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

char* XORCipher(char* data, char* key, int dataLen, int keyLen) {
    char* output = (char*)malloc(sizeof(char)*dataLen);

    for(int i = 0; i < dataLen; ++i) {
      output[i] = data[i] ^ key[i % keyLen];
    }

    return output;
}

int main(){

char *msg = "This is a Message from Boss";
char *key = "nandha";

int dataLen = strlen(msg);
int keyLen = strlen(key);

char *encrypt = XORCipher(msg,key,dataLen,keyLen);
printf("\nEncrypted msg is :\n %s",(char*)encrypt);

//The Length of encrypted char size is showing wrongly.
printf("size of Encrypted msg is: %d\n",strlen(encrypt));

encrypt = XORCipher(encrypt,key,strlen(encrypt),keyLen);
printf("\nOriginal msg converted is : %s\n",encrypt);

return 0;

}
Nandhakumar Kittusamy
  • 1,066
  • 12
  • 32
  • 8
    C odes not have a string type. Read what constitutes a C-string. Then use the debugger to inspect the encrypted data. **Then think about what you learned and what you saw** and why `strlen` is not useful anymore. As you are at reading: learn what pointers are and why they are not arrays. – too honest for this site Jun 23 '17 at 12:03
  • 3
    And don't cast the result of `malloc` & friends! – too honest for this site Jun 23 '17 at 12:05
  • then just tell that, how to get correct length of **char *encrypt** – Nandhakumar Kittusamy Jun 23 '17 at 12:15
  • If you had understood my comment, you would not ask this! That's exactly the proof you need to learn the basics. – too honest for this site Jun 23 '17 at 12:27
  • im just beginner @Olaf.I understood that char* storing printable characters.XOR message only gives like byte values. Please let you tell me how to print that length of encrypt without using strlen. please give me a solution@Olaf – Nandhakumar Kittusamy Jun 23 '17 at 13:56
  • 1
    @NandhaKumar you have a rep of 348 and have been an SO member for 2 years, 3 months. You may be a beginner in C, but you should be able to understand what your problem is, (as clearly hinted at by Oalf), and fix it yourself without hand-holding;( – ThingyWotsit Jun 23 '17 at 14:46
  • store the length separately. And [don't cast the result of `malloc` in C](http://stackoverflow.com/q/605845/995714) – phuclv Jun 23 '17 at 17:07
  • @LưuVĩnhPhúc: There is no need to store the length seperately. Call ne nasty, but I will not tell OP why. Figuring out is a good practice and can be expected (it is not even a programming problem). – too honest for this site Jun 23 '17 at 19:00
  • @Olaf even i added output[dataLen]=0, it shows wrong length – Nandhakumar Kittusamy Jun 24 '17 at 02:37
  • @Olaf please give me a solution to this problem in this chat room. https://chat.stackoverflow.com/rooms/147514/pointers-c – Nandhakumar Kittusamy Jun 24 '17 at 12:56
  • Your input is a string (weakly defined as that is in C) but your output is not, it is just a char array. And you always have to maintain the length of an array yourself. – H H Jun 26 '17 at 07:35

2 Answers2

1

When you perform these XOR operations on your string, the resulting values could fall outside the range of printable characters. In particular, if a plaintext character happens to match the key character used to encode it the result will be 0.

In C, a string is actually a sequence of characters terminated by a null byte, i.e. a byte with value 0. Any function that operates on strings looks for this byte to denote the end of the string.

Because your encoding can generate null bytes, your encrypted message is not a string but an array of bytes. Attempting to use a string function on the encrypted message can cause it to stop processing in the middle of the message if it contains a null byte. If the message does not contain a null byte, these string functions will continue to read past the end of the character array until it finds one. Reading past the end of an array or dynamically allocated block of memory invoked undefined behavior.

You need some other way to know how long the encrypted message is. In the case of the XOR encoding you're doing this is easy: the length of the ciphertext is the same as the length of the plaintext. So when decoding, pass in dataLen for the ciphertext length. To print the ciphertext, you need to loop through the bytes and print each one individually rather that trying to print it as a string (which it is not).

Also, after you've decoded, you still don't have a string because there was no null terminating byte added to the end of the decrypted message. You can do this manually after calling decrypting:

// pass in plaintext length as ciphertext length since they are the same
encrypt = XORCipher(encrypt,key,dataLen,keyLen);
// null terminate decrypted string
encrypt[dataLen] = '\0';

The buffer allocated inside of XORCipher doesn't currently allocate enough space for the null terminator, so you need to increase this by 1 to allow for this:

// no need to cast the return value of malloc
// sizeof(char) is guaranteed to be 1, so no need to multiply by it
char* output = malloc(dataLen + 1);
dbush
  • 205,898
  • 23
  • 218
  • 273
0

C strings are character arrays that are null terminated. When you allocate your encrypted array with the length of the string, you don't leave room for null termination, so strlen is unable to tell when the string ends, thinking the string ends outside of the actual memory that you allocated. This modification to your xor function will make it work.

char* XORCipher(char* data, char* key, int dataLen, int keyLen) {
    char* output = (char*)malloc(sizeof(char)*dataLen+1);
    output[dateLen] = 0;
    for(int i = 0; i < dataLen; ++i) {
        output[i] = data[i] ^ key[i % keyLen];
    }
    return output;
}

Additionally, if you're xor function gives 0 as an output, strlen will see that as the end of the string, which would give you a string length shorter than the expected output.

Update: I have tested the code and it works.

char* XORCipher(char* data, char* key, unsigned long dataLen, unsigned long keyLen) {
    char* output = (char*)malloc(sizeof(char)*dataLen+1);
    output[dataLen] = 0;
    for(int i = 0; i < dataLen; ++i) {
        output[i] = data[i] ^ key[i % keyLen];
    }
    return output;
}

void printLn(char* toPrint, unsigned long len){
    for (unsigned long i = 0; i < len; i++) {
        printf("%c", toPrint[i]);
    }
    printf("\n");
}

int main(){

    char *msg = "This is a Message from Boss";
    char *key = "nandha";

    unsigned long dataLen = strlen(msg);
    unsigned long keyLen = strlen(key);

    printLn(msg, dataLen);
    char* xorMessage = XORCipher(msg, key, dataLen, keyLen);
    printLn(xorMessage, dataLen);
    xorMessage = XORCipher(xorMessage, key, dataLen, keyLen);
    printLn(xorMessage, dataLen);


    return 0;
}

Be reminded that xoring can result in null characters in the array that you've allocated, resulting in a terminating character which you might have not intended. To compensate for this, I have added a function to print out based on length since you know this information based on your msg. After xoring twice you should have your original string back, which I my code verified.

Chris
  • 566
  • 2
  • 7
  • 22