我在C++中编写了以下函数,以使用XOR执行加密/解密。

wchar_t* encryptDecrypt(const wchar_t* toEncrypt, const wchar_t* key)
{
    int strLength = wcslen(toEncrypt);
    int keyLength = wcslen(key);
    wchar_t* output = new wchar_t[strLength];

    for (int i = 0; i < strLength; i++)
    {
        output[i] = toEncrypt[i] ^ key[i % keyLength];
    }
    return output;
}

从理论上讲,使用XOR两次加密字符串应得到原始字符串:
wprintf(L"%ls\n", encryptDecrypt(encryptDecrypt(L"Hello World", L"Key"), L"Key"));

但是,这是上面的代码行所打印的内容:
H??????????????????????

用相同功能的ASCII版本尝试相同的事情似乎更糟。这是函数:
char* encrypt(const char* toEncrypt, const char* key)
{
    int strLength = strlen(toEncrypt);
    int keyLength = strlen(key);
    char* output = new char[strLength];

    for (int i = 0; i < strLength; i++)
    {
        output[i] = toEncrypt[i] ^ key[i % keyLength];
    }
    return output;
}

打印代码,
cout << encrypt(encrypt("Hello World", "key"), "key");

和输出。
H²²²²A

关于什么可能导致此的任何想法?

编辑

正如您中某些人所建议的那样,计算纯文本的长度并将其传入(以及输出数组),可以解决大多数问题。但是,解密后的字符串的末尾仍然有一些垃圾。

功能:
void encryptDecrypt(const wchar_t* toEncrypt, int strLength, const wchar_t* key, wchar_t* output)
{
    int keyLength = wcslen(key);
    for (int i = 0; i < strLength; i++)
    {
        output[i] = toEncrypt[i] ^ key[i % keyLength];
    }
}

主要:
const wchar_t* myString = L"Hello World";
const wchar_t* key = L"Key";
int stringLength = wcslen(myString);
wchar_t* encrypted = new wchar_t[stringLength];
encryptDecrypt(myString, stringLength, key, encrypted);
wchar_t* decrypted = new wchar_t[stringLength];
encryptDecrypt(encrypted, stringLength, key, decrypted);
wprintf(L"%ls\n", decrypted);
delete[] encrypted;
delete[] decrypted;

输出:
Hello World??ver????

最佳答案

我可以立即看到的一个问题(可能还有更多)是在解密功能中,您对加密数据使用了strlen()

但是,strlen()适用于所谓的“asciiz”字符串,这些字符串是以零('\0')字符结尾的字符序列。您的加密数据包含随机字节,因此不是“asciiz”字符串。如果您的加密缓冲区包含零字节,那么strlen()将返回小于加密数据实际长度的数字,并且您的解密将无法正常进行。

具体来说,我注意到“Hello World”和“key”在第二个位置都包含一个“e”,并且将“e”与“e”进行异或运算会得出零,因此,有了它,此特定的文本和键将产生加密的数据,当将其视为asciiz字符串时,看起来只有一个字符长。

为解决此问题,您必须停止将加密数据视为asciiz字符串。每当您传递一个指向加密数据的指针时,您还必须传递数据的长度,并且永远不要使用strlen()来计算数据的长度。

O / P编辑后的修订:

要在字符串末尾修复随机字符,您需要记住,您正在读取加密的字节并构造一个asciiz字符串。因此,构造完asciiz字符串后,您实际上需要通过在字符串后附加一个零字符来使其成为asciiz,如下所示:

decrypted[stringLength] = '\0';

同样,在分配解密的字符串时,您一定不要忘记考虑这个额外的字节。对于零终止符,asciiz字符串始终占用strlen()字符加一个。因此,您需要这样做:
wchar_t* decrypted = new wchar_t[stringLength + 1];

09-07 02:53