mirror of
https://github.com/qTox/qTox.git
synced 2024-03-22 14:00:36 +08:00
fixed encryption, major testing required
This commit is contained in:
parent
3607240152
commit
7260fdd38d
170
src/core.cpp
170
src/core.cpp
|
@ -54,7 +54,7 @@ Core::Core(Camera* cam, QThread *coreThread, QString loadPath) :
|
||||||
videoBusyness=0;
|
videoBusyness=0;
|
||||||
|
|
||||||
for (int i = 0; i < ptCounter; i++)
|
for (int i = 0; i < ptCounter; i++)
|
||||||
pwsaltedkey[i] = nullptr;
|
pwsaltedkeys[i] = nullptr;
|
||||||
|
|
||||||
toxTimer = new QTimer(this);
|
toxTimer = new QTimer(this);
|
||||||
toxTimer->setSingleShot(true);
|
toxTimer->setSingleShot(true);
|
||||||
|
@ -1102,10 +1102,10 @@ bool Core::loadConfiguration(QString path)
|
||||||
|
|
||||||
if (Settings::getInstance().getEncryptTox())
|
if (Settings::getInstance().getEncryptTox())
|
||||||
{
|
{
|
||||||
while (!isPasswordSet(ptMain))
|
while (!pwsaltedkeys[ptMain])
|
||||||
{
|
{
|
||||||
emit blockingGetPassword(tr("Tox datafile decryption password"), ptMain);
|
emit blockingGetPassword(tr("Tox datafile decryption password"), ptMain);
|
||||||
if (!isPasswordSet(ptMain))
|
if (!pwsaltedkeys[ptMain])
|
||||||
Widget::getInstance()->showWarningMsgBox(tr("Password error"), tr("Failed to setup password.\nEmpty password."));
|
Widget::getInstance()->showWarningMsgBox(tr("Password error"), tr("Failed to setup password.\nEmpty password."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1120,17 +1120,18 @@ bool Core::loadConfiguration(QString path)
|
||||||
}
|
}
|
||||||
else if (error == 1) // Encrypted data save
|
else if (error == 1) // Encrypted data save
|
||||||
{
|
{
|
||||||
|
uint8_t salt[tox_pass_salt_length()];
|
||||||
|
tox_get_salt(reinterpret_cast<uint8_t *>(data.data()), salt);
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
while (!isPasswordSet(ptMain))
|
while (!pwsaltedkeys[ptMain])
|
||||||
{
|
{
|
||||||
emit blockingGetPassword(tr("Tox datafile decryption password"), ptMain);
|
emit blockingGetPassword(tr("Tox datafile decryption password"), ptMain, salt);
|
||||||
if (!isPasswordSet(ptMain))
|
if (!pwsaltedkeys[ptMain])
|
||||||
Widget::getInstance()->showWarningMsgBox(tr("Password error"), tr("Failed to setup password.\nEmpty password."));
|
Widget::getInstance()->showWarningMsgBox(tr("Password error"), tr("Failed to setup password.\nEmpty password."));
|
||||||
}
|
}
|
||||||
|
|
||||||
error = tox_encrypted_load(tox, reinterpret_cast<uint8_t *>(data.data()), data.size(),
|
error = tox_encrypted_key_load(tox, reinterpret_cast<uint8_t *>(data.data()), data.size(), pwsaltedkeys[ptMain]);
|
||||||
reinterpret_cast<uint8_t *>(barePassword[ptMain].data()), barePassword[ptMain].size());
|
|
||||||
if (error != 0)
|
if (error != 0)
|
||||||
{
|
{
|
||||||
QMessageBox msgb;
|
QMessageBox msgb;
|
||||||
|
@ -1146,59 +1147,24 @@ bool Core::loadConfiguration(QString path)
|
||||||
msgb.exec();
|
msgb.exec();
|
||||||
|
|
||||||
if (msgb.clickedButton() == tryAgain)
|
if (msgb.clickedButton() == tryAgain)
|
||||||
{
|
|
||||||
clearPassword(ptMain);
|
clearPassword(ptMain);
|
||||||
} else if (msgb.clickedButton() == cancel)
|
else if (msgb.clickedButton() == cancel)
|
||||||
{
|
{
|
||||||
configurationFile.close();
|
configurationFile.close();
|
||||||
return false;
|
return false;
|
||||||
} else if (msgb.clickedButton() == wipe)
|
}
|
||||||
|
else if (msgb.clickedButton() == wipe)
|
||||||
{
|
{
|
||||||
clearPassword(ptMain);
|
clearPassword(ptMain);
|
||||||
Settings::getInstance().setEncryptTox(false);
|
Settings::getInstance().setEncryptTox(false);
|
||||||
error = 0;
|
error = 0;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
Settings::getInstance().setEncryptTox(true);
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
Settings::getInstance().setEncryptTox(true);
|
||||||
} while (error != 0);
|
} while (error != 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// tox core is already decrypted
|
|
||||||
if (Settings::getInstance().getEnableLogging() && Settings::getInstance().getEncryptLogs())
|
|
||||||
{
|
|
||||||
bool error = true;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
while (!isPasswordSet(ptHistory))
|
|
||||||
{
|
|
||||||
emit blockingGetPassword(tr("History Log decryption password"), Core::ptHistory);
|
|
||||||
if (!isPasswordSet(ptHistory))
|
|
||||||
Widget::getInstance()->showWarningMsgBox(tr("Password error"), tr("Failed to setup password.\nEmpty password."));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!HistoryKeeper::checkPassword())
|
|
||||||
{
|
|
||||||
if (QMessageBox::Ok == Widget::getInstance()->showWarningMsgBox(tr("Encrypted log"),
|
|
||||||
tr("Your history encrypted with different password\nDo you want to try another password?"),
|
|
||||||
QMessageBox::Ok | QMessageBox::Cancel))
|
|
||||||
{
|
|
||||||
error = true;
|
|
||||||
clearPassword(ptHistory);
|
|
||||||
} else {
|
|
||||||
error = false;
|
|
||||||
clearPassword(ptHistory);
|
|
||||||
Widget::getInstance()->showWarningMsgBox(tr("Loggin"), tr("Due to incorret password logging will be disabled"));
|
|
||||||
Settings::getInstance().setEncryptLogs(false);
|
|
||||||
Settings::getInstance().setEnableLogging(false);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
error = false;
|
|
||||||
}
|
|
||||||
} while (error);
|
|
||||||
}
|
|
||||||
|
|
||||||
configurationFile.close();
|
configurationFile.close();
|
||||||
|
|
||||||
// set GUI with user and statusmsg
|
// set GUI with user and statusmsg
|
||||||
|
@ -1214,6 +1180,58 @@ bool Core::loadConfiguration(QString path)
|
||||||
if (!id.isEmpty())
|
if (!id.isEmpty())
|
||||||
emit idSet(id);
|
emit idSet(id);
|
||||||
|
|
||||||
|
// tox core is already decrypted
|
||||||
|
if (Settings::getInstance().getEnableLogging() && Settings::getInstance().getEncryptLogs())
|
||||||
|
{
|
||||||
|
bool error = true;
|
||||||
|
|
||||||
|
// get salt
|
||||||
|
QFile file(HistoryKeeper::getHistoryPath());
|
||||||
|
file.open(QIODevice::ReadOnly);
|
||||||
|
QByteArray data = file.read(tox_pass_encryption_extra_length());
|
||||||
|
file.close();
|
||||||
|
uint8_t salt[tox_pass_salt_length()];
|
||||||
|
int err = tox_get_salt(reinterpret_cast<uint8_t *>(data.data()), salt);
|
||||||
|
if (err)
|
||||||
|
{ // maybe we should handle this better
|
||||||
|
qWarning() << "Core: history db isn't encrypted, but encryption is set!! No history loaded...";
|
||||||
|
error = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
while (!pwsaltedkeys[ptHistory])
|
||||||
|
{
|
||||||
|
emit blockingGetPassword(tr("History Log decryption password"), Core::ptHistory, salt);
|
||||||
|
if (!pwsaltedkeys[ptHistory])
|
||||||
|
Widget::getInstance()->showWarningMsgBox(tr("Password error"), tr("Failed to setup password.\nEmpty password."));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!HistoryKeeper::checkPassword())
|
||||||
|
{
|
||||||
|
if (QMessageBox::Ok == Widget::getInstance()->showWarningMsgBox(tr("Encrypted log"),
|
||||||
|
tr("Your history is encrypted with different password\nDo you want to try another password?"),
|
||||||
|
QMessageBox::Ok | QMessageBox::Cancel))
|
||||||
|
{
|
||||||
|
error = true;
|
||||||
|
clearPassword(ptHistory);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
error = false;
|
||||||
|
clearPassword(ptHistory);
|
||||||
|
Widget::getInstance()->showWarningMsgBox(tr("Loggin"), tr("Due to incorret password logging will be disabled"));
|
||||||
|
Settings::getInstance().setEncryptLogs(false);
|
||||||
|
Settings::getInstance().setEnableLogging(false);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
error = false;
|
||||||
|
}
|
||||||
|
} while (error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
loadFriends();
|
loadFriends();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1262,8 +1280,8 @@ void Core::saveConfiguration(const QString& path)
|
||||||
|
|
||||||
qDebug() << "Core: writing tox_save to " << path;
|
qDebug() << "Core: writing tox_save to " << path;
|
||||||
|
|
||||||
uint32_t fileSize;
|
uint32_t fileSize; bool encrypt = Settings::getInstance().getEncryptTox();
|
||||||
if (Settings::getInstance().getEncryptTox())
|
if (encrypt)
|
||||||
fileSize = tox_encrypted_size(tox);
|
fileSize = tox_encrypted_size(tox);
|
||||||
else
|
else
|
||||||
fileSize = tox_size(tox);
|
fileSize = tox_size(tox);
|
||||||
|
@ -1271,25 +1289,26 @@ void Core::saveConfiguration(const QString& path)
|
||||||
if (fileSize > 0 && fileSize <= INT32_MAX) {
|
if (fileSize > 0 && fileSize <= INT32_MAX) {
|
||||||
uint8_t *data = new uint8_t[fileSize];
|
uint8_t *data = new uint8_t[fileSize];
|
||||||
|
|
||||||
if (Settings::getInstance().getEncryptTox())
|
if (encrypt)
|
||||||
{
|
{
|
||||||
if (!isPasswordSet(ptMain))
|
if (!pwsaltedkeys[ptMain])
|
||||||
{
|
{
|
||||||
// probably zero chance event
|
// probably zero chance event
|
||||||
Widget::getInstance()->showWarningMsgBox(tr("NO Password"), tr("Will be saved without encryption!"));
|
Widget::getInstance()->showWarningMsgBox(tr("NO Password"), tr("Will be saved without encryption!"));
|
||||||
tox_save(tox, data);
|
tox_save(tox, data);
|
||||||
} else {
|
}
|
||||||
int ret = tox_encrypted_save(tox, data, reinterpret_cast<uint8_t *>(barePassword[ptMain].data()),
|
else
|
||||||
barePassword[ptMain].size());
|
{
|
||||||
|
int ret = tox_encrypted_key_save(tox, data, pwsaltedkeys[ptMain]);
|
||||||
if (ret == -1)
|
if (ret == -1)
|
||||||
{
|
{
|
||||||
qCritical() << "Core::saveConfiguration: encryption of save file failed!!!";
|
qCritical() << "Core::saveConfiguration: encryption of save file failed!!!";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
tox_save(tox, data);
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
tox_save(tox, data);
|
||||||
|
|
||||||
configurationFile.write(reinterpret_cast<char *>(data), fileSize);
|
configurationFile.write(reinterpret_cast<char *>(data), fileSize);
|
||||||
configurationFile.commit();
|
configurationFile.commit();
|
||||||
|
@ -1605,43 +1624,41 @@ QList<CString> Core::splitMessage(const QString &message)
|
||||||
return splittedMsgs;
|
return splittedMsgs;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Core::setPassword(QString& password, PasswordType passtype)
|
void Core::setPassword(QString& password, PasswordType passtype, uint8_t* salt)
|
||||||
{
|
{
|
||||||
if (password.isEmpty())
|
if (password.isEmpty())
|
||||||
{
|
{
|
||||||
clearPassword(passtype);
|
clearPassword(passtype);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!pwsaltedkey[passtype])
|
if (!pwsaltedkeys[passtype])
|
||||||
pwsaltedkey[passtype] = new uint8_t[tox_pass_key_length()];
|
pwsaltedkeys[passtype] = new uint8_t[tox_pass_key_length()];
|
||||||
|
|
||||||
CString str(password);
|
CString str(password);
|
||||||
tox_derive_key_from_pass(str.data(), str.size(), pwsaltedkey[passtype]);
|
if (salt)
|
||||||
|
tox_derive_key_with_salt(str.data(), str.size(), salt, pwsaltedkeys[passtype]);
|
||||||
barePassword[passtype].clear();
|
else
|
||||||
barePassword[passtype].append(password);
|
tox_derive_key_from_pass(str.data(), str.size(), pwsaltedkeys[passtype]);
|
||||||
|
|
||||||
password.clear();
|
password.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Core::clearPassword(PasswordType passtype)
|
void Core::clearPassword(PasswordType passtype)
|
||||||
{
|
{
|
||||||
if (pwsaltedkey[passtype])
|
if (pwsaltedkeys[passtype])
|
||||||
{
|
{
|
||||||
delete[] pwsaltedkey[passtype];
|
delete[] pwsaltedkeys[passtype];
|
||||||
pwsaltedkey[passtype] = nullptr;
|
pwsaltedkeys[passtype] = nullptr;
|
||||||
barePassword[passtype].clear();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray Core::encryptData(const QByteArray& data, PasswordType passtype)
|
QByteArray Core::encryptData(const QByteArray& data, PasswordType passtype)
|
||||||
{
|
{
|
||||||
if (!pwsaltedkey[passtype])
|
if (!pwsaltedkeys[passtype])
|
||||||
return QByteArray();
|
return QByteArray();
|
||||||
uint8_t encrypted[data.size() + tox_pass_encryption_extra_length()];
|
uint8_t encrypted[data.size() + tox_pass_encryption_extra_length()];
|
||||||
// if (tox_pass_key_encrypt(reinterpret_cast<const uint8_t*>(data.data()), data.size(), pwsaltedkey[passtype], encrypted) == -1)
|
// if (tox_pass_key_encrypt(reinterpret_cast<const uint8_t*>(data.data()), data.size(), pwsaltedkeys[passtype], encrypted) == -1)
|
||||||
if (tox_pass_encrypt(reinterpret_cast<const uint8_t*>(data.data()), data.size(),
|
if (tox_pass_key_encrypt(reinterpret_cast<const uint8_t*>(data.data()), data.size(), pwsaltedkeys[passtype], encrypted) == -1)
|
||||||
reinterpret_cast<uint8_t*>(barePassword[passtype].data()), barePassword[passtype].size(), encrypted) == -1)
|
|
||||||
{
|
{
|
||||||
qWarning() << "Core::encryptData: encryption failed";
|
qWarning() << "Core::encryptData: encryption failed";
|
||||||
return QByteArray();
|
return QByteArray();
|
||||||
|
@ -1651,13 +1668,12 @@ QByteArray Core::encryptData(const QByteArray& data, PasswordType passtype)
|
||||||
|
|
||||||
QByteArray Core::decryptData(const QByteArray& data, PasswordType passtype)
|
QByteArray Core::decryptData(const QByteArray& data, PasswordType passtype)
|
||||||
{
|
{
|
||||||
if (!pwsaltedkey[passtype])
|
if (!pwsaltedkeys[passtype])
|
||||||
return QByteArray();
|
return QByteArray();
|
||||||
int sz = data.size() - tox_pass_encryption_extra_length();
|
int sz = data.size() - tox_pass_encryption_extra_length();
|
||||||
uint8_t decrypted[sz];
|
uint8_t decrypted[sz];
|
||||||
// if (tox_pass_key_decrypt(reinterpret_cast<const uint8_t*>(data.data()), data.size(), pwsaltedkey[passtype], decrypted) != sz)
|
// if (tox_pass_key_decrypt(reinterpret_cast<const uint8_t*>(data.data()), data.size(), pwsaltedkeys[passtype], decrypted) != sz)
|
||||||
if (tox_pass_decrypt(reinterpret_cast<const uint8_t*>(data.data()), data.size(),
|
if (tox_pass_key_decrypt(reinterpret_cast<const uint8_t*>(data.data()), data.size(), pwsaltedkeys[passtype], decrypted) != sz)
|
||||||
reinterpret_cast<uint8_t*>(barePassword[passtype].data()), barePassword[passtype].size(), decrypted) != sz)
|
|
||||||
{
|
{
|
||||||
qWarning() << "Core::decryptData: decryption failed";
|
qWarning() << "Core::decryptData: decryption failed";
|
||||||
return QByteArray();
|
return QByteArray();
|
||||||
|
@ -1667,7 +1683,7 @@ QByteArray Core::decryptData(const QByteArray& data, PasswordType passtype)
|
||||||
|
|
||||||
bool Core::isPasswordSet(PasswordType passtype)
|
bool Core::isPasswordSet(PasswordType passtype)
|
||||||
{
|
{
|
||||||
if (pwsaltedkey[passtype])
|
if (pwsaltedkeys[passtype])
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -109,7 +109,7 @@ public slots:
|
||||||
|
|
||||||
void micMuteToggle(int callId);
|
void micMuteToggle(int callId);
|
||||||
|
|
||||||
void setPassword(QString& password, PasswordType passtype);
|
void setPassword(QString& password, PasswordType passtype, uint8_t* salt = nullptr);
|
||||||
void clearPassword(PasswordType passtype);
|
void clearPassword(PasswordType passtype);
|
||||||
QByteArray encryptData(const QByteArray& data, PasswordType passtype);
|
QByteArray encryptData(const QByteArray& data, PasswordType passtype);
|
||||||
QByteArray decryptData(const QByteArray& data, PasswordType passtype);
|
QByteArray decryptData(const QByteArray& data, PasswordType passtype);
|
||||||
|
@ -118,7 +118,7 @@ signals:
|
||||||
void connected();
|
void connected();
|
||||||
void disconnected();
|
void disconnected();
|
||||||
void blockingClearContacts();
|
void blockingClearContacts();
|
||||||
void blockingGetPassword(QString info, int passtype);
|
void blockingGetPassword(QString info, int passtype, uint8_t* salt = nullptr);
|
||||||
|
|
||||||
void friendRequestReceived(const QString& userId, const QString& message);
|
void friendRequestReceived(const QString& userId, const QString& message);
|
||||||
void friendMessageReceived(int friendId, const QString& message, bool isAction);
|
void friendMessageReceived(int friendId, const QString& message, bool isAction);
|
||||||
|
@ -255,8 +255,7 @@ private:
|
||||||
static QList<ToxFile> fileSendQueue, fileRecvQueue;
|
static QList<ToxFile> fileSendQueue, fileRecvQueue;
|
||||||
static ToxCall calls[];
|
static ToxCall calls[];
|
||||||
|
|
||||||
uint8_t* pwsaltedkey[PasswordType::ptCounter]; // use the pw's hash as the "pw"
|
uint8_t* pwsaltedkeys[PasswordType::ptCounter]; // use the pw's hash as the "pw"
|
||||||
QByteArray barePassword[PasswordType::ptCounter]; // to be deleted after tox_pass_key_decrypt/tox_pass_key_encrypt fix
|
|
||||||
|
|
||||||
static const int videobufsize;
|
static const int videobufsize;
|
||||||
static uint8_t* videobuf;
|
static uint8_t* videobuf;
|
||||||
|
|
|
@ -1027,7 +1027,7 @@ void Widget::onGroupSendResult(int groupId, const QString& message, int result)
|
||||||
g->chatForm->addSystemInfoMessage("Message failed to send", "red", QDateTime::currentDateTime());
|
g->chatForm->addSystemInfoMessage("Message failed to send", "red", QDateTime::currentDateTime());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Widget::getPassword(QString info, int passtype)
|
void Widget::getPassword(QString info, int passtype, uint8_t* salt)
|
||||||
{
|
{
|
||||||
Core::PasswordType pt = static_cast<Core::PasswordType>(passtype);
|
Core::PasswordType pt = static_cast<Core::PasswordType>(passtype);
|
||||||
InputPasswordDialog dialog(info);
|
InputPasswordDialog dialog(info);
|
||||||
|
@ -1037,7 +1037,7 @@ void Widget::getPassword(QString info, int passtype)
|
||||||
if (pswd.isEmpty())
|
if (pswd.isEmpty())
|
||||||
core->clearPassword(pt);
|
core->clearPassword(pt);
|
||||||
else
|
else
|
||||||
core->setPassword(pswd, pt);
|
core->setPassword(pswd, pt, salt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -122,7 +122,7 @@ private slots:
|
||||||
void playRingtone();
|
void playRingtone();
|
||||||
void onIconClick(QSystemTrayIcon::ActivationReason);
|
void onIconClick(QSystemTrayIcon::ActivationReason);
|
||||||
void onUserAway();
|
void onUserAway();
|
||||||
void getPassword(QString info, int passtype);
|
void getPassword(QString info, int passtype, uint8_t* salt);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void init();
|
void init();
|
||||||
|
|
Loading…
Reference in New Issue
Block a user