2014-03-06 34 views
0

我有一个OpenSSL AES CBC-256的问题,它导致几乎15%的邮件没有正确解码。该程序使用QT,这就是为什么我使用QT类型。有什么办法可以解决这个问题,还是应该放弃使用AES进行加密。OpenSSL AES_CBC-256解密字符串并不总是正确的

void fillIV(unsigned char* IN) //Function to fill initialization vector with alphanumerics (for now,in future replaced by RAND()) 
{ 
QString charset="ABCDEFGIJKLMNOPQRSTOWXYZabcdefghijklmnopqrstuwxyz"; 
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

问题在输出中为空字符。构造函数QByteArray(const char *)将数据收集到第一个\ 0。解决方案是使用构造函数QByteArray(const char *,int),它允许从输出字符流到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()); 
相关问题