在 C 中将 Int 附加到 char *

Posted

技术标签:

【中文标题】在 C 中将 Int 附加到 char *【英文标题】:Appending an Int to a char * in C 【发布时间】:2013-08-30 09:20:07 【问题描述】:

所以我希望将密文的长度附加到我存储密码的 char 数组的末尾。我不是 C 的本地人,下面是我设计的测试 sn-p我认为有效。

...
int cipherTextLength = 0;
unsigned char *cipherText = NULL;
...
EVP_EncryptFinal_ex(&encryptCtx, cipherText + cipherTextLength, &finalBlockLength);
cipherTextLength += finalBlockLength;
EVP_CIPHER_CTX_cleanup(&encryptCtx);

// Append the length of the cipher text onto the end of the cipher text
// Note, the length stored will never be anywhere near 4294967295 
char cipherLengthChar[1];
sprintf(cipherLengthChar, "%d", cipherTextLength);
strcat(cipherText, cipherLengthChar);
printf("ENC - cipherTextLength: %d\n", cipherTextLength);
...

问题是我认为在处理二进制数据时使用strcat 不会有问题。谁能提出更好的方法来做到这一点?

谢谢!

编辑

好的,所以我将添加一些上下文,说明我为什么要附加长度。在我的encrypt 函数中,函数EVP_EncryptUpdate 需要加密plainText 的长度。因为这更容易获得,所以这部分不是问题。然而,类似地,在我的decrypt 函数中使用EVP_DecryptFinal_ex 需要解密ciperText 的长度,所以我需要将它存储在某个地方。

在我正在实现此功能的应用程序中,我所做的只是将一些糟糕的哈希更改为正确的加密。为了增加麻烦,应用程序的方式是我首先需要解密从 XML 读取的信息,对其进行处理,然后对其进行加密并再次将其重写为 XML,因此我需要以某种方式将此密码长度存储在密码中。我也没有重新设计这个的余地。

【问题讨论】:

【参考方案1】:

与您现在所做的不同,将密文大小编码到密文本身之前的位置可能更聪明。一旦开始解密,最后找到大小就不是很有用了。您需要知道结束才能找到结束的大小,这不是很有帮助。

此外,密文是二进制的,因此您无需将任何内容转换为字符串。您想将其转换为固定数量的字节(否则您不知道 size 的大小 :P )。因此,创建一个更大的缓冲区(比密文所需的多 4 个字节),并开始加密以向前偏移 4 个。然后将密文的大小复制到缓冲区的开头。

如果您不知道如何对整数进行编码,请查看 - 例如 - this question/ answer。请注意,对于2^32 的最大密文大小,这只会编码 32 位,大约 4 GiB。此外,该链接指向使用 Big Endian 编码。您应该使用 Big Endian(首选加密代码)或 Little Endian 编码 - 但不要将两者混合使用。

密文和编码大小都不能用作字符串。如果需要字符串,我的建议是对缓冲区进行 base 64 编码,直到密文结尾。

【讨论】:

是的,在阅读了其他 cmets 之后,我决定添加长度。我喜欢偏移缓冲区的想法,这样我就知道密文将从哪里开始。非常感谢!【参考方案2】:

我希望您有足够大的数组用于 cipherText 和 cipheLegthChar 来存储所需的文本。因此,而不是

unsigned char *cipherText = NULL;

你可以拥有

unsigned char cipherText[MAX_TEXT];

类似

cipherLenghthChar[MAX_INT];

或者您可以让它们动态分配。

其中 MAX_TEXT 和 MAX_INT 存储文本和整数的最大缓冲区大小。同样在第一次调用 EVP_EncryptFinal_ex NULL 后终止 cipherText 以便您 strcat 工作。

【讨论】:

【参考方案3】:

问题是我认为在处理二进制数据时使用 strcat 不会有问题。

正确!不过,这不是您唯一的问题:

// Note, the length stored will never be anywhere near 4294967295 
char cipherLengthChar[1];
sprintf(cipherLengthChar, "%d", cipherTextLength);

即使cipherTextLength 在这里是 0,你已经超出了界限,因为sprintf 将添加一个空终止符,总共有两个字符 - 但cipherLengthChar 只能容纳一个字符。 如果你考虑,例如4294967295,作为一个字符串,即 10 个字符 + '\0' = 11 个字符。

看起来finalBlockLength 是放入cipherText 的数据的长度。但是,EVP_EncryptFinal_ex() 调用可能会以某种方式失败,或者至少不会做你想做的事,因为cipherText == NULL。然后将 0 添加到该值(== 0 aka。仍然为 NULL)并将其作为参数提交。要么你需要一个指向那里的指针(如果EVP_EncryptFinal_ex 将为你分配空间),或者你必须确保cipherText 有足够的空间开始。

关于将文本(或其他)添加到末尾,您可以直接使用 sprintf:

sprintf(cipherText + finalBlockLength, "%d", cipherTextLength);

假设cipherText 是非NULL 并且有足够的extra 空间(参见前几段)。

但是,我很怀疑这样做以后会有用,但由于我没有任何进一步的背景,我不能说更多。

【讨论】:

以上是关于在 C 中将 Int 附加到 char *的主要内容,如果未能解决你的问题,请参考以下文章

有人可以解释如何在 C 编程中将元素附加到数组中吗?

使用system(),fgets和sprintf在C中将文本附加到文件的问题

如何在 C++ 中将 int 附加到字符串? [复制]

C自动将空字符附加到字符串?

C 将 char 附加到 char*

如何在 Robot Framework 中将数据附加到 csv 文件?