gpt4 book ai didi

c++ - 字符串加密函数适用于 char[],但不适用于普通字符串

转载 作者:搜寻专家 更新时间:2023-10-31 00:10:42 24 4
gpt4 key购买 nike

我正在使用维基百科的 xtea 加密版本,它是用 C++ 编写的。我写了一个函数来加密一个字符串

const char* charPtrDecrypt(const char* encString, int len, bool encrypt)
{

/********************************************************
* This currently uses a hard-coded key, but I'll implement
* a dynamic key based on string length or something.
*********************************************************/
unsigned int key[4] = { 0xB5D1, 0x22BA, 0xC2BC, 0x9A4E };

int n_blocks=len/BLOCK_SIZE;
if (len%BLOCK_SIZE != 0)
++n_blocks;

for (int i = 0; i < n_blocks; i++)
{
if (encrypt)
xtea::Encrypt(32, (uint32_t*)(encString + (i*BLOCK_SIZE)), key);
else
xtea::Decrypt(32, (uint32_t*)(encString + (i*BLOCK_SIZE)), key);
}
return encString;
}

当我提供一个 const char encString[] = "Hello, World!" 时它起作用,但是当我提供一个原始字符串时,例如const char* a = charPtrDecrypt("Hello, World!", 14, true) 它崩溃了。

最佳答案

有一句老话(我知道这句话很老,因为我在 1992 年左右第一次将它发布到 Usenet 上)是:“如果你对编译器撒谎,它会报复的。”这就是这里发生的事情。

这里:

const char* charPtrDecrypt(const char* encString, int len, bool encrypt)

...您保证不会修改encString 指向的字符。这就是 const 所说/意味着/所做的。

然而,这里:

xtea::Encrypt(32, (uint32_t*)(encString + (i*BLOCK_SIZE)), key);

...您抛弃了 constness(转换为 uint32_t *,没有 const 限定符),并将指针传递给修改它指向的缓冲区的函数。

然后编译器开始报复:它允许您将指针传递给您不能修改的数据,因为您 promise 不修改它——但是当您转身尝试修改它时无论如何修改它,你的程序会崩溃并烧毁,因为你试图修改只读数据。

这可以通过多种方式避免。一种是摆脱你现在使用的相对低级的构造,并传递/返回 std::string 而不是指向 [const] 字符

代码的问题远不止于此。一方面,它将输入视为 uint32_t 项的 block ,并将其长度 up 的 View 舍入到 uint32_t 大小的下一个倍数(通常为 4)。不幸的是,它实际上并没有改变缓冲区的大小,所以即使缓冲区是可写的,它也不能真正正常工作——它仍然会读取和写入缓冲区的末尾。

这里,std::string 将再次提供帮助:它让我们将字符串的大小调整为正确的大小,而不是仅仅读取/写入超过固定大小缓冲区的末尾。

除此之外,有一个事实编译器不会关心,但您(和这段代码的任何读者)会(或至少应该):函数的名称具有误导性,并且具有含义不正确的参数一点都不明显——尤其是控制是加密还是解密的 bool 值。我建议改用枚举,并将函数重命名为可以包含加密或解密的内容:

最后,我将确定是在循环外加密还是解密的 if 语句移动,因为我们不会在处理一个输入字符串时从一个更改为另一个。

考虑到所有这些因素,我们最终可以得到如下代码:

enum direction { ENCRYPT, DECRYPT };

std::string xtea_process(std::string enc_string, direction d) {

unsigned int key[4] = { 0xB5D1, 0x22BA, 0xC2BC, 0x9A4E };

size_t len = enc_string.size();

len += len % BLOCK_SIZE; // round up to next multiple of BLOCK_SIZE

enc_string.resize(len); // enlarge the string to that size, if necessary

if (direction == DECRYPT)
for (size_t i = 0; i < len; i+=BLOCK_SIZE)
xtea::Decrypt(32, reinterpret_cast<uint32_t *>(&encString[i]), key);
else
for (size_t i = 0; i < len; i += BLOCK_SIZE)
xtea::Encrypt(32, reinterpret_cast<uint32_t *>(&encString[i]), key);
}
return encString;
}

这仍然(至少)留下一点我没有费心去处理:一些机器对 uint32_t 的对齐要求可能比对 char 的对齐要求更严格, 从理论上讲, string 中使用的缓冲区可能无法满足那些更严格的对齐要求。您可能会遇到需要将数据从 string 复制到为 uint32_t 访问正确对齐的缓冲区,进行加密/解密,然后复制结果返回。

关于c++ - 字符串加密函数适用于 char[],但不适用于普通字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37054522/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com