XOR加密消息长度在C中显示错误

时间:2017-06-23 12:01:23

标签: c pointers xor

使用XOR算法通过以下C程序中的代码加密原始消息。最后,它给出了消息加密的另一个不同价值。即使邮件已加密,它也应返回相同的长度。

但是,使用 strlen(加密),它提供的值比原始邮件长度少。我无法识别为什么XOR加密消息的长度显示小于原始消息长度。请找到以下代码来解决我的问题。

提前致谢!

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

}

2 个答案:

答案 0 :(得分:1)

对字符串执行这些XOR操作时,结果值可能会超出可打印字符的范围。特别是,如果明文字符恰好与用于编码它的关键字符匹配,则结果将为0。

在C中,字符串实际上是由空字节终止的字符序列,即一个值为0的字节。对字符串进行操作的任何函数都会查找此字节以表示字符串的结尾。

因为您的编码可以生成空字节,所以您的加密消息不是字符串而是字节数组。尝试在加密消息上使用字符串函数可能会导致它在消息中间停止处理(如果它包含空字节)。如果消息不包含空字节,则这些字符串函数将继续读取字符数组的末尾,直到找到它为止。读取数组末尾或动态分配的内存块调用undefined behavior

您需要一些其他方法来了解加密邮件的时长。在XOR编码的情况下,您这样做很容易:密文的长度与明文的长度相同。因此,在解码时,传入dataLen以获得密文长度。要打印密文,您需要遍历字节并单独打印每个字节,而不是尝试将其打印为字符串(它不是)。

此外,在解码之后,您仍然没有字符串,因为在解密消息的末尾没有添加空终止字节。您可以在致电解密后手动执行此操作:

// 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';

XORCipher内部分配的缓冲区当前没有为空终止符分配足够的空间,因此需要将此值增加1以允许这样做:

// 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);

答案 1 :(得分:0)

C字符串是以null结尾的字符数组。当您使用字符串的长度分配加密数组时,您不会为空终止留出空间,因此strlen无法判断字符串何时结束,认为字符串在您分配的实际内存之外结束。对xor函数的这种修改将使其工作。

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

此外,如果你是xor函数给出0作为输出,strlen会将其视为字符串的结尾,这将使你的字符串长度比预期的输出短。

更新:我已经测试了代码并且可以正常运行。

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

请注意,xoring可能会导致您分配的数组中出现空字符,从而产生一个您可能没有预期的终止字符。为了弥补这一点,我添加了一个基于长度打印的功能,因为你根据你的信息知道这些信息。 xoring两次之后你应该把原来的字符串恢复,我的代码验证了。