我遇到OpenSSL AES CBC-256的问题,导致几乎15%的消息未正确解码。该程序使用QT,这就是我使用QT类型的原因。有没有办法解决这个问题,或者我应该放弃使用AES进行加密。
void fillIV(unsigned char* IN) //Function to fill initialization vector with alphanumerics (for now,in future replaced by RAND())
{
QString charset="ABCDEFGIJKLMNOPQRSTOWXYZabcdefghijklmnopqrstuwxyz0123456789";
for(int i=0;i<AES_BLOCK_SIZE;i++)
{
IN[i]=charset[qrand()%charset.length()].toAscii(); //Random QChar from QString
}
}
bool qorgIO::TEST(QString Password,MainWindow *main)
{
//ENCRYPT SECTION-------------------------------------------------------------------
QString OUT="HEADERHEADERHEA";
{
QString data="<ORG><CALENDAR></CALENDAR></ORG>";
if(data.length()%AES_BLOCK_SIZE==0)
{
data+=".";
}
//To prevent the length of data being multiplicity of 16(AES_BLOCK_SIZE)
//It cause a bunch of trash following the decrypted text
if(Password.length()< 32)
{
Password.append(QString(32-Password.length(),'\0'));
}
//Password is padded to 32 chars == 256 bits
AES_KEY *aesKey = new AES_KEY;
AES_set_encrypt_key((unsigned char*)Password.toAscii().data(), 256, aesKey);
//Setting AES-KEY Password.toAscii().data() is a char*
const size_t encslength = ((data.length() + AES_BLOCK_SIZE) / AES_BLOCK_SIZE) * AES_BLOCK_SIZE;
//Size of output: better have 16 bytes free then 16 bytes too little
unsigned char IV[AES_BLOCK_SIZE+1]; //16 bytes of IV and \0
fillIV(IV); //Create alphanumeric IV
//RAND_bytes(IV, AES_BLOCK_SIZE); //Random IV
OUT.append(QByteArray((const char*)IV).toBase64());
//Add to output data base64 representation of IV(in future IV will be random chars)
//IV during enryption change
unsigned char* aOUT;
aOUT=new unsigned char[encslength]; //Create the output space
memset(aOUT, 0, sizeof(encslength)); //Clear the output space
AES_cbc_encrypt((unsigned char*)data.toAscii().data(),aOUT,data.length(),aesKey,IV,AES_ENCRYPT);
//Encrypt the data
//AES_cbc_encrypt(unsigned char* data,unsigned char* output, AESKEY,unsigned char* IV, MODE)
OUT+="\n";
OUT.append(QByteArray((const char*)aOUT).toBase64());
//Add base64 representation of encoded data
}
//END OF ENCRYPT SECTION------------------------------------------------------------
//Output:
//HEADERHEADERHEA(base64 IV)\n(base64 data)(dot because data is 16*k charactes long)
//In this given example: HEADERHEADERHEA(base64 IV)\n(base64 data).
//DECRYPT SECTION-------------------------------------------------------------------
QString text=OUT;
QString Header=text.mid(0,15); //Get "HEADERHEADERHEA"
QString IV=text.mid(15,text.indexOf("\n")-15); //Get IV(base64)
QString Data=text.mid(text.indexOf("\n")+1,text.length()-text.indexOf("\n")-1);
//Get encrypted data(base64)
QByteArray IVBA=QByteArray::fromBase64(IV.toAscii()); //Decode base64
QByteArray DataBA=QByteArray::fromBase64(Data.toAscii()).data(); //Decode base64
if(Password.length()< 32)
{
Password.append(QString(32-Password.length(),'\0'));
}
//Password padding
AES_KEY *aesKey = new AES_KEY;
AES_set_decrypt_key((unsigned char*)Password.toAscii().data(), 256, aesKey);
//Set decryption key
int sizeofinput=DataBA.size();
//Size of output is <= size of input data
unsigned char *Output;
Output=new unsigned char[sizeofinput]; //Create the output array
memset(Output, 0 , sizeof(sizeofinput)); //Clear the output space
AES_cbc_encrypt((unsigned char*)DataBA.data(),Output,sizeofinput,aesKey,(unsigned char*)IVBA.data(),AES_DECRYPT);
//Decryption
//AES_cbc_encrypt(unsigned char* data,unsigned char* output, AESKEY,unsigned char* IV, MODE)
QString Decrypted=Header; //Header was plain text
Decrypted.append((const char*)Output); //Add output to the text
//END OF DECRYPT SECTION------------------------------------------------------------
if(Decrypted!="HEADERHEADERHEA<ORG><CALENDAR></CALENDAR></ORG>.")
{
qDebug()<<Decrypted; //Show the decrypted string
//up == "cout<<Decrypted.toStdString()";
return false;
}
else
{
return true;
}
}
解码后的字符串并不总是我想要接收的数据(10000次试验中15%的错误字符串)。这是AES算法的问题(不能容忍密码中的'\ 0')或者在创建代码时我是错误的吗?
对于任何语言错误,我很抱歉。
答案 0 :(得分:0)
问题是输出中的空字符。构造函数QByteArray(const char *)将数据收集到第一个\ 0。解决方案是使用构造函数QByteArray(const char *,int),它允许将所有数据从输出char流到QByteArray。
AES_cbc_encrypt((unsigned char*)data.toAscii().data(),aOUT,data.length(),aesKey,IV,AES_ENCRYPT);
//Encrypt the data
//AES_cbc_encrypt(unsigned char* data,unsigned char* output, AESKEY,unsigned char* IV, MODE)
OUT+="\n";
//!!OUT.append(QByteArray((const char*)aOUT).toBase64());
//Here we change line to:
OUT.append(QByteArray((const char*)aOUT,encslength).toBase64());