我有一个在suse linux企业服务器下运行了一段时间的程序。最近,它被移到了opensuse 13.2系统中,遇到了一个问题。程序与第三方接口,数据被接收到我们的程序中,其中的数据块由一些头信息和aes加密数据组成。使用openssl libcrypto库,我们在sles下成功地与这个系统连接。但是,在opensuse下,我们始终看到一个错误,即解密数据的结尾包含垃圾。我已经确定了问题发生的位置,并且已经找到了解决方法,但是在查看代码时,我不明白为什么会出现问题。
我已经创建了一个模拟问题的测试程序。该测试程序在suse linux企业服务器11和red hat 7.2enterpriselinux上运行良好,但在opensuse 13.2上使用不同版本的openssl库失败。在sles和red hat下,解密的数据被干净地返回。在opensuse下,除了出现在数据块末尾的一些垃圾之外,大多数数据都是干净解密的。返回的数据块正确,然后包含一些垃圾,最后正确结束。下面是我的示例程序的代码,但导致问题的一行是memcpy(),我将加密的数据移到数据块的前面进行处理。我的示例程序中的行如下:
// Generates Garbage
memcpy(encbuf, encbuf+100, enclen);
如果在将加密数据移动到encbuf的开头之前将其移动到临时缓冲区,则不会生成垃圾。
// This does not generate garbage
memcpy(tmpbuf, encbuf+100, enclen);
memcpy(encbuf, tmpbuf, enclen);
我的示例程序获取定义的明文缓冲区,使用密钥和iv对其进行加密,然后将其解密并显示结果。压缩代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <fcntl.h>
#include <sys/types.h>
#include <openssl/evp.h>
#define EVP_DECRYPT 0
#define EVP_ENCRYPT 1
char clrbuf[100000];
char encbuf[100000];
char tmpbuf[100000];
int clrlen;
int enclen;
char enckey[1024];
unsigned char enciv[16];
main()
{
int rc;
// Set clear text to 50 lines of text
sprintf(clrbuf,
"0001this is a test this is a test this is a test this is a test\n" \
"0002this is a test this is a test this is a test this is a test\n" \
"0003this is a test this is a test this is a test this is a test\n" \
// etc etc etc……………….
"0048this is a test this is a test this is a test this is a test\n" \
"0049this is a test this is a test this is a test this is a test\n" \
"0050this is a test this is a test this is a test this is a test\n"
sprintf(enckey, "this is the key this is the key ");
sprintf(enciv, "1234567890123456");
// Encrypt the data and simulate a 100 byte header by returning encrypted data 100 bytes into the data block
//
memcpy(encbuf, "Some header stuff that will need to be removed", 46);
rc = evp_aes256_cbc(clrbuf, strlen(clrbuf), encbuf+100, &enclen, enckey, enciv, EVP_ENCRYPT);
// Now remove the header by shifting the encrypted data to the start of the data block and decrypt
// This is where doing the memcpy() as coded in OpenSUSE results in garbage at the end of clrbuf
// but everything is returned correctly in SLES and Red Hat
//
// This work fines on all OSes:
// memcpy(tmpbuf, encbuf+100, enclen);
// memcpy(encbuf, tmpbuf, enclen);
memcpy(encbuf, encbuf+100, enclen);
rc = evp_aes256_cbc(encbuf, enclen, clrbuf, &clrlen, enckey, enciv, EVP_DECRYPT);
printf("Decrypt: rc=%d EncLen=%d ClrLen=%d\n", rc, enclen, clrlen);
printf("Data:\n\n<\n%s\n>\n\n", clrbuf);
}
/****************************************************************************/
evp_aes256_cbc(char *InBuf, int InLen, char *OutBuf, int OutLen, char *Key, char *IV, int EncryptFlag)
{
EVP_CIPHER_CTX ctx;
int padlen;
EVP_CIPHER_CTX_init(&ctx);
if (! EVP_CipherInit_ex(&ctx, EVP_aes_256_cbc(), NULL, Key, IV, EncryptFlag))
return(0);
if (! EVP_CipherUpdate(&ctx, OutBuf, OutLen, InBuf, InLen))
return(0);
if (! EVP_CipherFinal_ex(&ctx, OutBuf+(*OutLen), &padlen))
return(0);
*OutLen = *OutLen + padlen;
EVP_CIPHER_CTX_cleanup(&ctx);
return(1);
}
在SLES和Red Hat上,最终输出如下:
0046这是测试这是测试这是测试这是测试
0047这是测试这是测试这是测试这是测试
0048这是测试这是测试这是测试这是测试
0049这是测试这是测试这是测试这是测试
0050这是测试这是测试这是测试这是测试
在opensuse上,最终输出可以如下所示:
0046这是测试这是测试这是测试这是测试
0047这是测试这是测试这是测试这是测试
0048这是一个测试这是一个测试
|τzk½_p≥ii w p 8 t g{y e_
n}*2_ ls4=qü_;~<^ d0 t.oq∑q≈
0050这是测试这是测试这是测试这是测试
有什么想法吗?
谢谢
最佳答案
// Generates Garbage
memcpy(encbuf, encbuf+100, enclen);
重叠缓冲区和cc是C/C++中未定义的行为。改为使用
memcpy
。听起来你有一个glibc版本,它可以向前或向后记忆。在您的例子中,您是在通过memmove
的处理器上执行的。这里有一个关于这个问题的典型错误报告:Strange sound on mp3 flash website。但adobe不会让你吃惊的。有一个原因是他们是地球上最不安全的软件。
此外,如果在valgrind下运行二进制文件,该工具有时会标记有问题的代码。我记得我看到过瓦尔格林为“AA”做的标记:
size_t ArraySink::Put2(const byte *begin, size_t length, int messageEnd, bool blocking)
{
// Avoid passing NULL pointer to memcpy. Using memmove due to
// Valgrind finding on overlapping buffers.
size_t copied = 0;
if (m_buf && begin)
{
copied = STDMIN(length, SaturatingSubtract(m_size, m_total));
memmove(m_buf+m_total, begin, copied);
}
m_total += copied;
return length - copied;
}
关于c - 在OpenSUSE 13.2上使用memcpy解密期间的垃圾字符,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/35301736/