mirror of
https://github.com/qTox/qTox.git
synced 2024-03-22 14:00:36 +08:00
Tox datafile/encrypted history: different passwords
This commit is contained in:
parent
dfd5b6411a
commit
5c0370eaed
132
src/core.cpp
132
src/core.cpp
|
@ -53,6 +53,9 @@ Core::Core(Camera* cam, QThread *coreThread, QString loadPath) :
|
|||
videobuf = new uint8_t[videobufsize];
|
||||
videoBusyness=0;
|
||||
|
||||
for (int i = 0; i < ptCounter; i++)
|
||||
pwsaltedkey[i] = nullptr;
|
||||
|
||||
toxTimer = new QTimer(this);
|
||||
toxTimer->setSingleShot(true);
|
||||
connect(toxTimer, &QTimer::timeout, this, &Core::process);
|
||||
|
@ -116,7 +119,8 @@ Core::~Core()
|
|||
if (alInDev)
|
||||
alcCaptureCloseDevice(alInDev);
|
||||
|
||||
clearPassword();
|
||||
clearPassword(Core::ptMain);
|
||||
clearPassword(Core::ptHistory);
|
||||
}
|
||||
|
||||
Core* Core::getInstance()
|
||||
|
@ -1096,10 +1100,10 @@ bool Core::loadConfiguration(QString path)
|
|||
|
||||
if (Settings::getInstance().getEncryptTox())
|
||||
{
|
||||
while (!isPasswordSet())
|
||||
while (!isPasswordSet(ptMain))
|
||||
{
|
||||
emit blockingGetPassword(tr("Tox datafile decryption password"));
|
||||
if (!isPasswordSet())
|
||||
emit blockingGetPassword(tr("Tox datafile decryption password"), ptMain);
|
||||
if (!isPasswordSet(ptMain))
|
||||
QMessageBox::warning(nullptr, tr("Password error"), tr("Failed to setup password.\nEmpty password."));
|
||||
}
|
||||
}
|
||||
|
@ -1116,15 +1120,15 @@ bool Core::loadConfiguration(QString path)
|
|||
{
|
||||
do
|
||||
{
|
||||
while (!isPasswordSet())
|
||||
while (!isPasswordSet(ptMain))
|
||||
{
|
||||
emit blockingGetPassword(tr("Tox datafile decryption password"));
|
||||
if (!isPasswordSet())
|
||||
emit blockingGetPassword(tr("Tox datafile decryption password"), ptMain);
|
||||
if (!isPasswordSet(ptMain))
|
||||
QMessageBox::warning(nullptr, tr("Password error"), tr("Failed to setup password.\nEmpty password."));
|
||||
}
|
||||
|
||||
error = tox_encrypted_load(tox, reinterpret_cast<uint8_t *>(data.data()), data.size(),
|
||||
reinterpret_cast<uint8_t *>(barePassword.data()), barePassword.size());
|
||||
reinterpret_cast<uint8_t *>(barePassword[ptMain].data()), barePassword[ptMain].size());
|
||||
if (error != 0)
|
||||
{
|
||||
QMessageBox msgb;
|
||||
|
@ -1140,14 +1144,14 @@ bool Core::loadConfiguration(QString path)
|
|||
|
||||
if (msgb.clickedButton() == tryAgain)
|
||||
{
|
||||
clearPassword();
|
||||
clearPassword(ptMain);
|
||||
} else if (msgb.clickedButton() == cancel)
|
||||
{
|
||||
configurationFile.close();
|
||||
return false;
|
||||
} else if (msgb.clickedButton() == wipe)
|
||||
{
|
||||
clearPassword();
|
||||
clearPassword(ptMain);
|
||||
Settings::getInstance().setEncryptTox(false);
|
||||
error = 0;
|
||||
}
|
||||
|
@ -1161,46 +1165,35 @@ bool Core::loadConfiguration(QString path)
|
|||
// tox core is already decrypted
|
||||
if (Settings::getInstance().getEnableLogging() && Settings::getInstance().getEncryptLogs())
|
||||
{
|
||||
if (isPasswordSet())
|
||||
bool error = true;
|
||||
do
|
||||
{
|
||||
while (!isPasswordSet(ptHistory))
|
||||
{
|
||||
emit blockingGetPassword(tr("History Log decpytion password"), Core::ptHistory);
|
||||
if (!isPasswordSet(ptHistory))
|
||||
QMessageBox::warning(nullptr, tr("Password error"), tr("Failed to setup password.\nEmpty password."));
|
||||
}
|
||||
|
||||
if (!HistoryKeeper::checkPassword())
|
||||
{
|
||||
QMessageBox::warning(nullptr, tr("Different passwords!"),
|
||||
tr("Tox datafile and history log encrypted with different passwords."));
|
||||
Settings::getInstance().setEncryptLogs(false);
|
||||
Settings::getInstance().setEnableLogging(false);
|
||||
}
|
||||
} else {
|
||||
bool error = true;
|
||||
do
|
||||
{
|
||||
while (!isPasswordSet())
|
||||
if (QMessageBox::Ok == QMessageBox::warning(nullptr, tr("Encrypted log"),
|
||||
tr("Your history encrypted with different password\nDo you want to try another password?"),
|
||||
QMessageBox::Ok | QMessageBox::Cancel))
|
||||
{
|
||||
emit blockingGetPassword(tr("History Log decpytion password"));
|
||||
if (!isPasswordSet())
|
||||
QMessageBox::warning(nullptr, tr("Password error"), tr("Failed to setup password.\nEmpty password."));
|
||||
}
|
||||
|
||||
if (!HistoryKeeper::checkPassword())
|
||||
{
|
||||
if (QMessageBox::Ok == QMessageBox::warning(nullptr, tr("Encrypted log"),
|
||||
tr("Your history encrypted with different password\nDo you want to try another password?"),
|
||||
QMessageBox::Ok | QMessageBox::Cancel))
|
||||
{
|
||||
error = true;
|
||||
clearPassword();
|
||||
} else {
|
||||
error = false;
|
||||
clearPassword();
|
||||
QMessageBox::warning(nullptr, tr("Loggin"), tr("Due to incorret password logging will be disabled"));
|
||||
Settings::getInstance().setEncryptLogs(false);
|
||||
Settings::getInstance().setEnableLogging(false);
|
||||
}
|
||||
error = true;
|
||||
clearPassword(ptHistory);
|
||||
} else {
|
||||
error = false;
|
||||
clearPassword(ptHistory);
|
||||
QMessageBox::warning(nullptr, tr("Loggin"), tr("Due to incorret password logging will be disabled"));
|
||||
Settings::getInstance().setEncryptLogs(false);
|
||||
Settings::getInstance().setEnableLogging(false);
|
||||
}
|
||||
} while (error);
|
||||
}
|
||||
} else {
|
||||
error = false;
|
||||
}
|
||||
} while (error);
|
||||
}
|
||||
|
||||
configurationFile.close();
|
||||
|
@ -1273,13 +1266,14 @@ void Core::saveConfiguration(const QString& path)
|
|||
|
||||
if (Settings::getInstance().getEncryptTox())
|
||||
{
|
||||
if (!isPasswordSet())
|
||||
if (!isPasswordSet(ptMain))
|
||||
{
|
||||
// probably zero chance event
|
||||
QMessageBox::warning(nullptr, tr("NO Password"), tr("Will be saved without encryption!"));
|
||||
tox_save(tox, data);
|
||||
} else {
|
||||
int ret = tox_encrypted_save(tox, data, reinterpret_cast<uint8_t *>(barePassword.data()), barePassword.size());
|
||||
int ret = tox_encrypted_save(tox, data, reinterpret_cast<uint8_t *>(barePassword[ptMain].data()),
|
||||
barePassword[ptMain].size());
|
||||
if (ret == -1)
|
||||
{
|
||||
qCritical() << "Core::saveConfiguration: encryption of save file failed!!!";
|
||||
|
@ -1307,7 +1301,8 @@ void Core::switchConfiguration(const QString& profile)
|
|||
qDebug() << "Core: switching from" << Settings::getInstance().getCurrentProfile() << "to" << profile;
|
||||
|
||||
saveConfiguration();
|
||||
clearPassword();
|
||||
clearPassword(ptMain);
|
||||
clearPassword(ptHistory);
|
||||
toxTimer->stop();
|
||||
|
||||
if (tox) {
|
||||
|
@ -1322,7 +1317,6 @@ void Core::switchConfiguration(const QString& profile)
|
|||
loadPath = QDir(Settings::getSettingsDirPath()).filePath(profile + TOX_EXT);
|
||||
Settings::getInstance().setCurrentProfile(profile);
|
||||
HistoryKeeper::getInstance()->resetInstance();
|
||||
clearPassword();
|
||||
|
||||
start();
|
||||
}
|
||||
|
@ -1604,43 +1598,43 @@ QList<CString> Core::splitMessage(const QString &message)
|
|||
return splittedMsgs;
|
||||
}
|
||||
|
||||
void Core::setPassword(QString& password)
|
||||
void Core::setPassword(QString& password, PasswordType passtype)
|
||||
{
|
||||
if (password.isEmpty())
|
||||
{
|
||||
clearPassword();
|
||||
clearPassword(passtype);
|
||||
return;
|
||||
}
|
||||
if (!pwsaltedkey)
|
||||
pwsaltedkey = new uint8_t[tox_pass_key_length()];
|
||||
if (!pwsaltedkey[passtype])
|
||||
pwsaltedkey[passtype] = new uint8_t[tox_pass_key_length()];
|
||||
|
||||
CString str(password);
|
||||
tox_derive_key_from_pass(str.data(), str.size(), pwsaltedkey);
|
||||
tox_derive_key_from_pass(str.data(), str.size(), pwsaltedkey[passtype]);
|
||||
|
||||
barePassword.clear();
|
||||
barePassword.append(password);
|
||||
barePassword[passtype].clear();
|
||||
barePassword[passtype].append(password);
|
||||
|
||||
password.clear();
|
||||
}
|
||||
|
||||
void Core::clearPassword()
|
||||
void Core::clearPassword(PasswordType passtype)
|
||||
{
|
||||
if (pwsaltedkey)
|
||||
if (pwsaltedkey[passtype])
|
||||
{
|
||||
delete[] pwsaltedkey;
|
||||
pwsaltedkey = nullptr;
|
||||
barePassword.clear();
|
||||
delete[] pwsaltedkey[passtype];
|
||||
pwsaltedkey[passtype] = nullptr;
|
||||
barePassword[passtype].clear();
|
||||
}
|
||||
}
|
||||
|
||||
QByteArray Core::encryptData(const QByteArray& data)
|
||||
QByteArray Core::encryptData(const QByteArray& data, PasswordType passtype)
|
||||
{
|
||||
if (!pwsaltedkey)
|
||||
if (!pwsaltedkey[passtype])
|
||||
return QByteArray();
|
||||
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, encrypted) == -1)
|
||||
// if (tox_pass_key_encrypt(reinterpret_cast<const uint8_t*>(data.data()), data.size(), pwsaltedkey[passtype], encrypted) == -1)
|
||||
if (tox_pass_encrypt(reinterpret_cast<const uint8_t*>(data.data()), data.size(),
|
||||
reinterpret_cast<uint8_t*>(barePassword.data()), barePassword.size(), encrypted) == -1)
|
||||
reinterpret_cast<uint8_t*>(barePassword[passtype].data()), barePassword[passtype].size(), encrypted) == -1)
|
||||
{
|
||||
qWarning() << "Core::encryptData: encryption failed";
|
||||
return QByteArray();
|
||||
|
@ -1648,15 +1642,15 @@ QByteArray Core::encryptData(const QByteArray& data)
|
|||
return QByteArray(reinterpret_cast<char*>(encrypted), data.size() + tox_pass_encryption_extra_length());
|
||||
}
|
||||
|
||||
QByteArray Core::decryptData(const QByteArray& data)
|
||||
QByteArray Core::decryptData(const QByteArray& data, PasswordType passtype)
|
||||
{
|
||||
if (!pwsaltedkey)
|
||||
if (!pwsaltedkey[passtype])
|
||||
return QByteArray();
|
||||
int sz = data.size() - tox_pass_encryption_extra_length();
|
||||
uint8_t decrypted[sz];
|
||||
// if (tox_pass_key_decrypt(reinterpret_cast<const uint8_t*>(data.data()), data.size(), pwsaltedkey, decrypted) != sz)
|
||||
// if (tox_pass_key_decrypt(reinterpret_cast<const uint8_t*>(data.data()), data.size(), pwsaltedkey[passtype], decrypted) != sz)
|
||||
if (tox_pass_decrypt(reinterpret_cast<const uint8_t*>(data.data()), data.size(),
|
||||
reinterpret_cast<uint8_t*>(barePassword.data()), barePassword.size(), decrypted) != sz)
|
||||
reinterpret_cast<uint8_t*>(barePassword[passtype].data()), barePassword[passtype].size(), decrypted) != sz)
|
||||
{
|
||||
qWarning() << "Core::decryptData: decryption failed";
|
||||
return QByteArray();
|
||||
|
@ -1664,9 +1658,9 @@ QByteArray Core::decryptData(const QByteArray& data)
|
|||
return QByteArray(reinterpret_cast<char*>(decrypted), sz);
|
||||
}
|
||||
|
||||
bool Core::isPasswordSet()
|
||||
bool Core::isPasswordSet(PasswordType passtype)
|
||||
{
|
||||
if (pwsaltedkey)
|
||||
if (pwsaltedkey[passtype])
|
||||
return true;
|
||||
|
||||
return false;
|
||||
|
|
19
src/core.h
19
src/core.h
|
@ -34,6 +34,8 @@ class Core : public QObject
|
|||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum PasswordType {ptMain = 0, ptHistory, ptCounter};
|
||||
|
||||
explicit Core(Camera* cam, QThread* coreThread, QString initialLoadPath);
|
||||
static Core* getInstance(); ///< Returns the global widget's Core instance
|
||||
~Core();
|
||||
|
@ -64,7 +66,7 @@ public:
|
|||
void decreaseVideoBusyness();
|
||||
|
||||
bool anyActiveCalls();
|
||||
bool isPasswordSet();
|
||||
bool isPasswordSet(PasswordType passtype);
|
||||
|
||||
public slots:
|
||||
void start();
|
||||
|
@ -105,16 +107,16 @@ public slots:
|
|||
|
||||
void micMuteToggle(int callId);
|
||||
|
||||
void setPassword(QString& password);
|
||||
void clearPassword();
|
||||
QByteArray encryptData(const QByteArray& data);
|
||||
QByteArray decryptData(const QByteArray& data);
|
||||
void setPassword(QString& password, PasswordType passtype);
|
||||
void clearPassword(PasswordType passtype);
|
||||
QByteArray encryptData(const QByteArray& data, PasswordType passtype);
|
||||
QByteArray decryptData(const QByteArray& data, PasswordType passtype);
|
||||
|
||||
signals:
|
||||
void connected();
|
||||
void disconnected();
|
||||
void blockingClearContacts();
|
||||
void blockingGetPassword(QString info);
|
||||
void blockingGetPassword(QString info, int passtype);
|
||||
|
||||
void friendRequestReceived(const QString& userId, const QString& message);
|
||||
void friendMessageReceived(int friendId, const QString& message, bool isAction);
|
||||
|
@ -251,8 +253,9 @@ private:
|
|||
int dhtServerId;
|
||||
static QList<ToxFile> fileSendQueue, fileRecvQueue;
|
||||
static ToxCall calls[];
|
||||
uint8_t* pwsaltedkey = nullptr; // use the pw's hash as the "pw"
|
||||
QByteArray barePassword; // to be deleted after tox_pass_key_decrypt/tox_pass_key_encrypt fix
|
||||
|
||||
uint8_t* pwsaltedkey[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 uint8_t* videobuf;
|
||||
|
|
|
@ -39,8 +39,9 @@ public:
|
|||
|
||||
static HistoryKeeper* getInstance();
|
||||
static void resetInstance();
|
||||
static bool checkPassword();
|
||||
|
||||
static QString getHistoryPath();
|
||||
static bool checkPassword();
|
||||
static void renameHistory(QString from, QString to);
|
||||
|
||||
void addChatEntry(const QString& chat, const QString& message, const QString& sender, const QDateTime &dt);
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#include <QDebug>
|
||||
#include <QSqlError>
|
||||
|
||||
qint64 EncryptedDb::plainChunkSize = 1024;
|
||||
qint64 EncryptedDb::plainChunkSize = 4096;
|
||||
qint64 EncryptedDb::encryptedChunkSize = EncryptedDb::plainChunkSize + tox_pass_encryption_extra_length();
|
||||
|
||||
EncryptedDb::EncryptedDb(const QString &fname, QList<QString> initList) :
|
||||
|
@ -50,7 +50,8 @@ EncryptedDb::EncryptedDb(const QString &fname, QList<QString> initList) :
|
|||
|
||||
EncryptedDb::~EncryptedDb()
|
||||
{
|
||||
encrFile.close(); // what if program is killed without being able to clean up?
|
||||
encrFile.close(); // Q: what if program is killed without being able to clean up?
|
||||
// A: cleanup isn't necessary, everything handled int appendToEncrypted(..) function
|
||||
}
|
||||
|
||||
QSqlQuery EncryptedDb::exec(const QString &query)
|
||||
|
@ -70,7 +71,7 @@ bool EncryptedDb::pullFileContent()
|
|||
while (!encrFile.atEnd())
|
||||
{
|
||||
QByteArray encrChunk = encrFile.read(encryptedChunkSize);
|
||||
buffer = Core::getInstance()->decryptData(encrChunk);
|
||||
buffer = Core::getInstance()->decryptData(encrChunk, Core::ptHistory);
|
||||
if (buffer.size() > 0)
|
||||
{
|
||||
fileContent += buffer;
|
||||
|
@ -129,7 +130,7 @@ void EncryptedDb::appendToEncrypted(const QString &sql)
|
|||
{
|
||||
QByteArray filledChunk = buffer.left(plainChunkSize);
|
||||
encrFile.seek(chunkPosition * encryptedChunkSize);
|
||||
QByteArray encr = Core::getInstance()->encryptData(filledChunk);
|
||||
QByteArray encr = Core::getInstance()->encryptData(filledChunk, Core::ptHistory);
|
||||
if (encr.size() > 0)
|
||||
{
|
||||
encrFile.write(encr);
|
||||
|
@ -140,7 +141,7 @@ void EncryptedDb::appendToEncrypted(const QString &sql)
|
|||
}
|
||||
encrFile.seek(chunkPosition * encryptedChunkSize);
|
||||
|
||||
QByteArray encr = Core::getInstance()->encryptData(buffer);
|
||||
QByteArray encr = Core::getInstance()->encryptData(buffer, Core::ptHistory);
|
||||
if (encr.size() > 0)
|
||||
{
|
||||
encrFile.write(encr);
|
||||
|
@ -157,7 +158,7 @@ bool EncryptedDb::check(const QString &fname)
|
|||
if (file.size() > 0)
|
||||
{
|
||||
QByteArray encrChunk = file.read(encryptedChunkSize);
|
||||
QByteArray buf = Core::getInstance()->decryptData(encrChunk);
|
||||
QByteArray buf = Core::getInstance()->decryptData(encrChunk, Core::ptHistory);
|
||||
if (buf.size() == 0)
|
||||
{
|
||||
state = false;
|
||||
|
|
|
@ -65,7 +65,7 @@ void PrivacyForm::onEncryptLogsUpdated()
|
|||
|
||||
if (encrytionState)
|
||||
{
|
||||
if (!Core::getInstance()->isPasswordSet())
|
||||
if (!Core::getInstance()->isPasswordSet(Core::ptHistory))
|
||||
{
|
||||
SetPasswordDialog dialog;
|
||||
if (dialog.exec())
|
||||
|
@ -74,10 +74,10 @@ void PrivacyForm::onEncryptLogsUpdated()
|
|||
if (pswd.size() == 0)
|
||||
encrytionState = false;
|
||||
|
||||
Core::getInstance()->setPassword(pswd);
|
||||
Core::getInstance()->setPassword(pswd, Core::ptHistory);
|
||||
} else {
|
||||
encrytionState = false;
|
||||
Core::getInstance()->clearPassword();
|
||||
Core::getInstance()->clearPassword(Core::ptHistory);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -100,8 +100,8 @@ void PrivacyForm::onEncryptLogsUpdated()
|
|||
if (encrytionState)
|
||||
HistoryKeeper::resetInstance();
|
||||
|
||||
if (!Settings::getInstance().getEncryptLogs() && !Settings::getInstance().getEncryptTox())
|
||||
Core::getInstance()->clearPassword();
|
||||
if (!Settings::getInstance().getEncryptLogs())
|
||||
Core::getInstance()->clearPassword(Core::ptHistory);
|
||||
}
|
||||
|
||||
void PrivacyForm::onEncryptToxUpdated()
|
||||
|
@ -110,7 +110,7 @@ void PrivacyForm::onEncryptToxUpdated()
|
|||
|
||||
if (encrytionState)
|
||||
{
|
||||
if (!Core::getInstance()->isPasswordSet())
|
||||
if (!Core::getInstance()->isPasswordSet(Core::ptMain))
|
||||
{
|
||||
SetPasswordDialog dialog;
|
||||
if (dialog.exec())
|
||||
|
@ -119,10 +119,10 @@ void PrivacyForm::onEncryptToxUpdated()
|
|||
if (pswd.size() == 0)
|
||||
encrytionState = false;
|
||||
|
||||
Core::getInstance()->setPassword(pswd);
|
||||
Core::getInstance()->setPassword(pswd, Core::ptMain);
|
||||
} else {
|
||||
encrytionState = false;
|
||||
Core::getInstance()->clearPassword();
|
||||
Core::getInstance()->clearPassword(Core::ptMain);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -130,6 +130,6 @@ void PrivacyForm::onEncryptToxUpdated()
|
|||
bodyUI->cbEncryptTox->setChecked(encrytionState);
|
||||
Settings::getInstance().setEncryptTox(encrytionState);
|
||||
|
||||
if (!Settings::getInstance().getEncryptLogs() && !Settings::getInstance().getEncryptTox())
|
||||
Core::getInstance()->clearPassword();
|
||||
if (!Settings::getInstance().getEncryptTox())
|
||||
Core::getInstance()->clearPassword(Core::ptMain);
|
||||
}
|
||||
|
|
|
@ -134,6 +134,7 @@ Widget::Widget(QWidget *parent)
|
|||
qRegisterMetaType<QPixmap>("QPixmap");
|
||||
qRegisterMetaType<ToxFile>("ToxFile");
|
||||
qRegisterMetaType<ToxFile::FileDirection>("ToxFile::FileDirection");
|
||||
qRegisterMetaType<Core::PasswordType>("Core::PasswordType");
|
||||
|
||||
QString profilePath = detectProfile();
|
||||
coreThread = new QThread(this);
|
||||
|
@ -911,15 +912,16 @@ void Widget::onGroupSendResult(int groupId, const QString& message, int result)
|
|||
g->chatForm->addSystemInfoMessage("Message failed to send", "red", QDateTime::currentDateTime());
|
||||
}
|
||||
|
||||
void Widget::getPassword(QString info)
|
||||
void Widget::getPassword(QString info, int passtype)
|
||||
{
|
||||
Core::PasswordType pt = static_cast<Core::PasswordType>(passtype);
|
||||
InputPasswordDialog dialog(info);
|
||||
if (dialog.exec())
|
||||
{
|
||||
QString pswd = dialog.getPassword();
|
||||
if (pswd.isEmpty())
|
||||
core->clearPassword();
|
||||
core->clearPassword(pt);
|
||||
else
|
||||
core->setPassword(pswd);
|
||||
core->setPassword(pswd, pt);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -112,7 +112,7 @@ private slots:
|
|||
void playRingtone();
|
||||
void onIconClick();
|
||||
void onUserAway();
|
||||
void getPassword(QString info);
|
||||
void getPassword(QString info, int passtype);
|
||||
|
||||
private:
|
||||
void hideMainForms();
|
||||
|
|
Loading…
Reference in New Issue
Block a user