一、可能原因
1、编码格式差异:QString和QByteArray有本质区别。QString是一个Unicode字符串,其受编码格式影响,而QByteArray是一个字节序列。在进行QSting转QByteArray的过程中,最常见的方式是将Unicode字符串转换为UTF-8编码的字节序列。
2、包含空字符:QString 编码结束符为空字符(16进制00,\X00),因此在特殊情况下比如异或加密后会出现空字符,如果通过异或解密便会丢失数据。
二、解决办法
1、编码格式问题可以在转换前指定编码格式,一个采用UTF-8,如下:
QTextCodec *codec=QTextCodec::codecForName("UTF-8");
QByteArray qbtBuffer = codec->fromUnicode(qsData);
2、空字符或特殊字符,在异或加密前转换成QChar或QByteArray,加密数据采用QByteArray存储,解密时对QByteArray格式进行存储。
//测试代码1
QString qsText("Beijing XXXX Technology Co., Ltd");
QString qsEncryption=this->getXOREncryption(qsText,111);
QString qsDecryption=this->getXOREncryption(qsEncryption,111);
qDebug()<<"qsEncryption=="<<qsEncryption;
qDebug()<<"qsDecryption=="<<qsDecryption;
//输出结果
qsEncryption== "-\n\u0006\u0005\u0006\u0001\bO7777O;\n\f\u0007\u0001"
qsDecryption== "Beijing XXXX Techn"
QString getXOREncryption(const QString &qsData, char cKey)
{
//采用异或加密
QTextCodec *codec=QTextCodec::codecForName("UTF-8");
QByteArray qbtBuffer = codec->fromUnicode(qsData);
int iSize = qbtBuffer.size();
for (int i = 0; i < iSize; i++) {
qbtBuffer[i] = qbtBuffer.at(i) ^ cKey;
}
return QLatin1String(qbtBuffer);
}
以上明显可以看出,解密后数据丢失,原因是疑惑加密后字符'O'为空字符,从而导致存储与解密的丢失。
//测试代码2
QString qsText("Beijing XXXX Technology Co., Ltd");
QByteArray bytData=qsText.toLatin1();
QByteArray bytEncryption=this->getXOREncryption(bytData,111);
QByteArray bytDecryption=this->getXOREncryption(bytEncryption,111);
qDebug()<<"bytEncryption=="<<bytEncryption;
qDebug()<<"bytDecryption=="<<bytDecryption;
//输出结果
bytEncryption== "-\n\x06\x05\x06\x01\bO7777O;\n\f\x07\x01\x00\x03\x00\b\x16O,\x00""ACO#\x1B\x0B"
bytDecryption== "Beijing XXXX Technology Co., Ltd"
QByteArray LisenceKey::getXOREncryption(const QByteArray &bytData, char cKey)
{
QByteArray qbtBuffer=bytData;
int iSize = qbtBuffer.size();
for (int i = 0; i < iSize; i++) {
qbtBuffer[i] = qbtBuffer.at(i) ^ cKey;
}
return qbtBuffer;
}
以上可以看出,通过QByteArray存储保留了完整信息。
三、应用
1、将数据加密后存储:注意,由于有特殊格式尤其是空字符,不要采用数据流的方式。
//加密写入文件
QString qsFilePath = qsPath;
if (qsFilePath.isEmpty()) qsFilePath = QString("./lisence.lic");
QFile file(qsFilePath);
if (file.open(QFile::WriteOnly | QIODevice::Text)) {
//QTextStream out(&file);
//out << this->getXOREncryption(lstData.join("|"));
file.write(getXOREncryption(lstData.join("|").toLatin1()));
file.close();
}
//读取数据并解密
QFile keyFile(this->m_qsLisencePath);
if (keyFile.exists() && keyFile.size() > 0 && keyFile.open(QFile::ReadOnly | QIODevice::Text)) {
QString keyData = QString(this->getXOREncryption(keyFile.readAll()));
lstData = keyData.split("|", Qt::KeepEmptyParts);
}
return lstData;