我有一段時間在SUSE Linux Enterprise Server下工作正常。最近,它轉移到了OpenSUSE 13.2系統,遇到了一個問題。程序連接到第三方,數據被接收到我們的程序中,其中數據塊由一些標題信息和AES加密數據組成。使用OpenSSL libcrypto庫,我們成功地在SLES下與此係統連接。但是,在OpenSUSE下,我們始終會看到解密數據的末尾包含垃圾的錯誤。我已經確定了問題發生的位置,並且有一個解決方法,但是在查看代碼時,我不明白爲什麼會有問題。使用OpenSUSE 13.2上的memcpy進行解密時的垃圾字符
我已經創建了一個模擬問題的測試程序。該測試程序在SUSE Linux Enterprise Server 11和Red Hat 7.2企業版Linux下正常工作,但在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, "123456789");
// 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,最終輸出看起來像:
0046this是一個測試這是一個測試這是一個測試這是一個測試
0047this被一個測試這是一個測試這是一個測試這是一個測試
0048這是一個測試這是一個測試這是一個測試這是一個測試
0049這是一個測試這是一個測試這是一個測試這是一個測試
0050這是一個測試這是一個測試這是一個測試這是一個測試
在openSUSE,最終輸出可以是這樣的:
0046this是一個測試這是一個測試這是一個測試這是一個測試
0047this是測試這是一個測試,這是一個測試這是一個測試
0048這是一個測試這是一個測試這是一個測試這是一個測試這是一個測試這是一個測試這是一個測試這是一個測試這是一個測試這是一個testest_s ⌡n}⌐*╘¿μ2└╠LS4=Qüü├;〜╕< ^DD0┤T.OQΣq#≈
個 0050this是一個測試這是一個測試這是一個測試這是一個測試
有什麼想法?
由於
填充搞砸了嗎? – Asaph