OpenSSL AES_CBC-256解密的字符串并不总是正确的

OpenSSL AES_CBC-256 decrypted string is not always correct

本文关键字:串并 字符 AES CBC-256 解密 OpenSSL 字符串      更新时间:2023-10-16

我对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(),''));
        }
        //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 
        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(),''));
    }
    //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')还是在创建代码时的错误?

对于任何语言错误,我非常抱歉。

问题是输出中的无效字符。构造函数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());
相关文章: