1
0
mirror of https://github.com/qTox/qTox.git synced 2024-03-22 14:00:36 +08:00

Use profile password for all encryption

This commit is contained in:
tux3 2015-06-04 15:16:25 +02:00
parent 4e2983817f
commit 5f94f33117
15 changed files with 81 additions and 407 deletions

View File

@ -62,9 +62,7 @@ Core::Core(QThread *CoreThread, Profile& profile) :
Audio::getInstance(); Audio::getInstance();
videobuf = nullptr; videobuf = nullptr;
encryptionKey = nullptr;
for (int i = 0; i < ptCounter; i++)
pwsaltedkeys[i] = nullptr;
toxTimer = new QTimer(this); toxTimer = new QTimer(this);
toxTimer->setSingleShot(true); toxTimer->setSingleShot(true);
@ -109,7 +107,7 @@ Core::~Core()
if (QThread::currentThread() == coreThread) if (QThread::currentThread() == coreThread)
killTimers(); killTimers();
else else
QMetaObject::invokeMethod(this, "stopTimers", Qt::BlockingQueuedConnection); QMetaObject::invokeMethod(this, "killTimers", Qt::BlockingQueuedConnection);
} }
coreThread->exit(0); coreThread->exit(0);
while (coreThread->isRunning()) while (coreThread->isRunning())
@ -286,7 +284,7 @@ void Core::start()
emit idSet(id); emit idSet(id);
// tox core is already decrypted // tox core is already decrypted
if (Settings::getInstance().getEnableLogging() && Settings::getInstance().getEncryptLogs()) if (Settings::getInstance().getEnableLogging() && Nexus::getProfile()->isEncrypted())
checkEncryptedHistory(); checkEncryptedHistory();
loadFriends(); loadFriends();

View File

@ -44,8 +44,6 @@ class Core : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
enum PasswordType {ptMain = 0, ptHistory, ptCounter};
explicit Core(QThread* coreThread, Profile& profile); explicit Core(QThread* coreThread, Profile& profile);
static Core* getInstance(); ///< Returns the global widget's Core instance static Core* getInstance(); ///< Returns the global widget's Core instance
~Core(); ~Core();
@ -82,7 +80,7 @@ public:
VideoSource* getVideoSourceFromCall(int callNumber); ///< Get a call's video source VideoSource* getVideoSourceFromCall(int callNumber); ///< Get a call's video source
static bool anyActiveCalls(); ///< true is any calls are currently active (note: a call about to start is not yet active) static bool anyActiveCalls(); ///< true is any calls are currently active (note: a call about to start is not yet active)
bool isPasswordSet(PasswordType passtype); bool isPasswordSet();
bool isReady(); ///< Most of the API shouldn't be used until Core is ready, call start() first bool isReady(); ///< Most of the API shouldn't be used until Core is ready, call start() first
void resetCallSources(); ///< Forces to regenerate each call's audio sources void resetCallSources(); ///< Forces to regenerate each call's audio sources
@ -145,11 +143,10 @@ public slots:
static bool isGroupCallMicEnabled(int groupId); static bool isGroupCallMicEnabled(int groupId);
static bool isGroupCallVolEnabled(int groupId); static bool isGroupCallVolEnabled(int groupId);
void setPassword(const QString &password, PasswordType passtype, uint8_t* salt = nullptr); void setPassword(const QString &password, uint8_t* salt = nullptr);
void useOtherPassword(PasswordType type); void clearPassword();
void clearPassword(PasswordType passtype); QByteArray encryptData(const QByteArray& data);
QByteArray encryptData(const QByteArray& data, PasswordType passtype); QByteArray decryptData(const QByteArray& data);
QByteArray decryptData(const QByteArray& data, PasswordType passtype);
signals: signals:
void connected(); void connected();
@ -301,7 +298,7 @@ private:
QMutex messageSendMutex; QMutex messageSendMutex;
bool ready; bool ready;
TOX_PASS_KEY* pwsaltedkeys[PasswordType::ptCounter] = {nullptr}; // use the pw's hash as the "pw" TOX_PASS_KEY* encryptionKey = nullptr; // use the pw's hash as the "pw"
static const int videobufsize; static const int videobufsize;
static uint8_t* videobuf; static uint8_t* videobuf;

View File

@ -33,45 +33,38 @@
#include <algorithm> #include <algorithm>
#include <cassert> #include <cassert>
void Core::setPassword(const QString& password, PasswordType passtype, uint8_t* salt) void Core::setPassword(const QString& password, uint8_t* salt)
{ {
clearPassword(passtype); clearPassword();
if (password.isEmpty()) if (password.isEmpty())
return; return;
pwsaltedkeys[passtype] = new TOX_PASS_KEY; encryptionKey = new TOX_PASS_KEY;
CString str(password); CString str(password);
if (salt) if (salt)
tox_derive_key_with_salt(str.data(), str.size(), salt, pwsaltedkeys[passtype], nullptr); tox_derive_key_with_salt(str.data(), str.size(), salt, encryptionKey, nullptr);
else else
tox_derive_key_from_pass(str.data(), str.size(), pwsaltedkeys[passtype], nullptr); tox_derive_key_from_pass(str.data(), str.size(), encryptionKey, nullptr);
} }
void Core::useOtherPassword(PasswordType type) void Core::clearPassword()
{ {
clearPassword(type); delete encryptionKey;
pwsaltedkeys[type] = new TOX_PASS_KEY; encryptionKey = nullptr;
PasswordType other = (type == ptMain) ? ptHistory : ptMain;
std::copy(pwsaltedkeys[other], pwsaltedkeys[other]+1, pwsaltedkeys[type]);
} }
void Core::clearPassword(PasswordType passtype) QByteArray Core::encryptData(const QByteArray& data)
{ {
delete pwsaltedkeys[passtype]; if (!encryptionKey)
pwsaltedkeys[passtype] = nullptr; {
} qWarning() << "No encryption key set";
QByteArray Core::encryptData(const QByteArray& data, PasswordType 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(), if (!tox_pass_key_encrypt(reinterpret_cast<const uint8_t*>(data.data()), data.size(),
pwsaltedkeys[passtype], encrypted, nullptr)) encryptionKey, encrypted, nullptr))
{ {
qWarning() << "Encryption failed"; qWarning() << "Encryption failed";
return QByteArray(); return QByteArray();
@ -79,15 +72,18 @@ QByteArray Core::encryptData(const QByteArray& data, PasswordType passtype)
return QByteArray(reinterpret_cast<char*>(encrypted), data.size() + TOX_PASS_ENCRYPTION_EXTRA_LENGTH); return QByteArray(reinterpret_cast<char*>(encrypted), data.size() + TOX_PASS_ENCRYPTION_EXTRA_LENGTH);
} }
QByteArray Core::decryptData(const QByteArray& data, PasswordType passtype) QByteArray Core::decryptData(const QByteArray& data)
{ {
if (!pwsaltedkeys[passtype]) if (!encryptionKey)
{
qWarning() << "No encryption key set";
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(), if (!tox_pass_key_decrypt(reinterpret_cast<const uint8_t*>(data.data()), data.size(),
pwsaltedkeys[passtype], decrypted, nullptr)) encryptionKey, decrypted, nullptr))
{ {
qWarning() << "Decryption failed"; qWarning() << "Decryption failed";
return QByteArray(); return QByteArray();
@ -95,12 +91,9 @@ QByteArray Core::decryptData(const QByteArray& data, PasswordType passtype)
return QByteArray(reinterpret_cast<char*>(decrypted), sz); return QByteArray(reinterpret_cast<char*>(decrypted), sz);
} }
bool Core::isPasswordSet(PasswordType passtype) bool Core::isPasswordSet()
{ {
if (pwsaltedkeys[passtype]) return static_cast<bool>(encryptionKey);
return true;
return false;
} }
QByteArray Core::getSaltFromFile(QString filename) QByteArray Core::getSaltFromFile(QString filename)
@ -135,42 +128,24 @@ void Core::checkEncryptedHistory()
if (exists && salt.size() == 0) if (exists && salt.size() == 0)
{ // maybe we should handle this better { // maybe we should handle this better
GUI::showWarning(tr("Encrypted chat history"), tr("No encrypted chat history file found, or it was corrupted.\nHistory will be disabled!")); GUI::showWarning(tr("Encrypted chat history"), tr("No encrypted chat history file found, or it was corrupted.\nHistory will be disabled!"));
Settings::getInstance().setEncryptLogs(false);
Settings::getInstance().setEnableLogging(false);
HistoryKeeper::resetInstance(); HistoryKeeper::resetInstance();
return; return;
} }
setPassword(Nexus::getProfile()->getPassword(), reinterpret_cast<uint8_t*>(salt.data()));
QString a(tr("Please enter the password for the chat history for the profile \"%1\".", "used in load() when no hist pw set").arg(Nexus::getProfile()->getName())); QString a(tr("Please enter the password for the chat history for the profile \"%1\".", "used in load() when no hist pw set").arg(Nexus::getProfile()->getName()));
QString b(tr("The previous password is incorrect; please try again:", "used on retries in load()")); QString b(tr("The previous password is incorrect; please try again:", "used on retries in load()"));
QString c(tr("\nDisabling chat history now will leave the encrypted history intact (but not usable); if you later remember the password, you may re-enable encryption from the Privacy tab with the correct password to use the history.", "part of history password dialog")); QString c(tr("\nDisabling chat history now will leave the encrypted history intact (but not usable); if you later remember the password, you may re-enable encryption from the Privacy tab with the correct password to use the history.", "part of history password dialog"));
QString dialogtxt; QString dialogtxt;
if (pwsaltedkeys[ptHistory])
{
if (!exists || HistoryKeeper::checkPassword())
return;
dialogtxt = tr("The chat history password failed. Please try another?", "used only when pw set before load() doesn't work"); if (!exists || HistoryKeeper::checkPassword())
} return;
else
{
dialogtxt = a;
}
dialogtxt = tr("The chat history password failed. Please try another?", "used only when pw set before load() doesn't work");
dialogtxt += "\n" + c; dialogtxt += "\n" + c;
if (pwsaltedkeys[ptMain])
{
useOtherPassword(ptHistory);
if (!exists || HistoryKeeper::checkPassword())
{
qDebug() << "using main password for chat history";
return;
}
clearPassword(ptHistory);
}
bool error = true; bool error = true;
do do
{ {
@ -178,15 +153,14 @@ void Core::checkEncryptedHistory()
if (pw.isEmpty()) if (pw.isEmpty())
{ {
clearPassword(ptHistory); clearPassword();
Settings::getInstance().setEncryptLogs(false);
Settings::getInstance().setEnableLogging(false); Settings::getInstance().setEnableLogging(false);
HistoryKeeper::resetInstance(); HistoryKeeper::resetInstance();
return; return;
} }
else else
{ {
setPassword(pw, ptHistory, reinterpret_cast<uint8_t*>(salt.data())); setPassword(pw, reinterpret_cast<uint8_t*>(salt.data()));
} }
error = exists && !HistoryKeeper::checkPassword(); error = exists && !HistoryKeeper::checkPassword();

View File

@ -47,9 +47,7 @@ HistoryKeeper *HistoryKeeper::getInstance()
if (Settings::getInstance().getEnableLogging()) if (Settings::getInstance().getEnableLogging())
{ {
bool encrypted = Settings::getInstance().getEncryptLogs(); if (Nexus::getProfile()->isEncrypted())
if (encrypted)
{ {
path = getHistoryPath(); path = getHistoryPath();
dbIntf = new EncryptedDb(path, initLst); dbIntf = new EncryptedDb(path, initLst);
@ -75,7 +73,7 @@ bool HistoryKeeper::checkPassword(int encrypted)
if (!Settings::getInstance().getEnableLogging() && (encrypted == -1)) if (!Settings::getInstance().getEnableLogging() && (encrypted == -1))
return true; return true;
if ((encrypted == 1) || (encrypted == -1 && Settings::getInstance().getEncryptLogs())) if ((encrypted == 1) || (encrypted == -1 && Nexus::getProfile()->isEncrypted()))
return EncryptedDb::check(getHistoryPath(Nexus::getProfile()->getName(), encrypted)); return EncryptedDb::check(getHistoryPath(Nexus::getProfile()->getName(), encrypted));
return true; return true;
@ -365,7 +363,7 @@ QString HistoryKeeper::getHistoryPath(QString currentProfile, int encrypted)
if (currentProfile.isEmpty()) if (currentProfile.isEmpty())
currentProfile = Settings::getInstance().getCurrentProfile(); currentProfile = Settings::getInstance().getCurrentProfile();
if (encrypted == 1 || (encrypted == -1 && Settings::getInstance().getEncryptLogs())) if (encrypted == 1 || (encrypted == -1 && Nexus::getProfile()->isEncrypted()))
return baseDir.filePath(currentProfile + ".qtox_history.encrypted"); return baseDir.filePath(currentProfile + ".qtox_history.encrypted");
else else
return baseDir.filePath(currentProfile + ".qtox_history"); return baseDir.filePath(currentProfile + ".qtox_history");

View File

@ -118,7 +118,7 @@ int main(int argc, char *argv[])
if (QDir(Settings::getSettingsDirPath()).exists(profileName + ".tox")) if (QDir(Settings::getSettingsDirPath()).exists(profileName + ".tox"))
{ {
qDebug() << "Setting profile to" << profileName; qDebug() << "Setting profile to" << profileName;
if (Profile::isProfileEncrypted(profileName)) if (Profile::isEncrypted(profileName))
{ {
Settings::getInstance().setCurrentProfile(profileName); Settings::getInstance().setCurrentProfile(profileName);
} }

View File

@ -85,7 +85,7 @@ bool EncryptedDb::pullFileContent(const QString &fname, QByteArray &buf)
while (!dbFile.atEnd()) while (!dbFile.atEnd())
{ {
QByteArray encrChunk = dbFile.read(encryptedChunkSize); QByteArray encrChunk = dbFile.read(encryptedChunkSize);
buf = Core::getInstance()->decryptData(encrChunk, Core::ptHistory); buf = Core::getInstance()->decryptData(encrChunk);
if (buf.size() > 0) if (buf.size() > 0)
{ {
fileContent += buf; fileContent += buf;
@ -130,7 +130,7 @@ void EncryptedDb::appendToEncrypted(const QString &sql)
{ {
QByteArray filledChunk = buffer.left(plainChunkSize); QByteArray filledChunk = buffer.left(plainChunkSize);
encrFile.seek(chunkPosition * encryptedChunkSize); encrFile.seek(chunkPosition * encryptedChunkSize);
QByteArray encr = Core::getInstance()->encryptData(filledChunk, Core::ptHistory); QByteArray encr = Core::getInstance()->encryptData(filledChunk);
if (encr.size() > 0) if (encr.size() > 0)
{ {
encrFile.write(encr); encrFile.write(encr);
@ -142,7 +142,7 @@ void EncryptedDb::appendToEncrypted(const QString &sql)
} }
encrFile.seek(chunkPosition * encryptedChunkSize); encrFile.seek(chunkPosition * encryptedChunkSize);
QByteArray encr = Core::getInstance()->encryptData(buffer, Core::ptHistory); QByteArray encr = Core::getInstance()->encryptData(buffer);
if (encr.size() > 0) if (encr.size() > 0)
encrFile.write(encr); encrFile.write(encr);
@ -158,7 +158,7 @@ bool EncryptedDb::check(const QString &fname)
if (file.size() > 0) if (file.size() > 0)
{ {
QByteArray encrChunk = file.read(encryptedChunkSize); QByteArray encrChunk = file.read(encryptedChunkSize);
QByteArray buf = Core::getInstance()->decryptData(encrChunk, Core::ptHistory); QByteArray buf = Core::getInstance()->decryptData(encrChunk);
if (buf.size() == 0) if (buf.size() == 0)
state = false; state = false;
} }

View File

@ -249,8 +249,6 @@ void Settings::load()
ps.beginGroup("Privacy"); ps.beginGroup("Privacy");
typingNotification = ps.value("typingNotification", false).toBool(); typingNotification = ps.value("typingNotification", false).toBool();
enableLogging = ps.value("enableLogging", false).toBool(); enableLogging = ps.value("enableLogging", false).toBool();
encryptLogs = ps.value("encryptLogs", false).toBool();
encryptTox = ps.value("encryptTox", false).toBool();
ps.endGroup(); ps.endGroup();
} }
} }
@ -396,8 +394,6 @@ void Settings::savePersonal(QString path)
ps.beginGroup("Privacy"); ps.beginGroup("Privacy");
ps.setValue("typingNotification", typingNotification); ps.setValue("typingNotification", typingNotification);
ps.setValue("enableLogging", enableLogging); ps.setValue("enableLogging", enableLogging);
ps.setValue("encryptLogs", encryptLogs);
ps.setValue("encryptTox", encryptTox);
ps.endGroup(); ps.endGroup();
} }
@ -731,26 +727,6 @@ void Settings::setEnableLogging(bool newValue)
enableLogging = newValue; enableLogging = newValue;
} }
bool Settings::getEncryptLogs() const
{
return encryptLogs;
}
void Settings::setEncryptLogs(bool newValue)
{
encryptLogs = newValue;
}
bool Settings::getEncryptTox() const
{
return encryptTox;
}
void Settings::setEncryptTox(bool newValue)
{
encryptTox = newValue;
}
Db::syncType Settings::getDbSyncType() const Db::syncType Settings::getDbSyncType() const
{ {
return dbSyncType; return dbSyncType;

View File

@ -104,12 +104,6 @@ public:
bool getEnableLogging() const; bool getEnableLogging() const;
void setEnableLogging(bool newValue); void setEnableLogging(bool newValue);
bool getEncryptLogs() const;
void setEncryptLogs(bool newValue);
bool getEncryptTox() const;
void setEncryptTox(bool newValue);
Db::syncType getDbSyncType() const; Db::syncType getDbSyncType() const;
void setDbSyncType(int newValue); void setDbSyncType(int newValue);
@ -303,8 +297,6 @@ private:
uint32_t currentProfileId; uint32_t currentProfileId;
bool enableLogging; bool enableLogging;
bool encryptLogs;
bool encryptTox = false;
int autoAwayTime; int autoAwayTime;

View File

@ -59,7 +59,6 @@ void Nexus::start()
qRegisterMetaType<QPixmap>("QPixmap"); qRegisterMetaType<QPixmap>("QPixmap");
qRegisterMetaType<ToxFile>("ToxFile"); qRegisterMetaType<ToxFile>("ToxFile");
qRegisterMetaType<ToxFile::FileDirection>("ToxFile::FileDirection"); qRegisterMetaType<ToxFile::FileDirection>("ToxFile::FileDirection");
qRegisterMetaType<Core::PasswordType>("Core::PasswordType");
qRegisterMetaType<std::shared_ptr<VideoFrame>>("std::shared_ptr<VideoFrame>"); qRegisterMetaType<std::shared_ptr<VideoFrame>>("std::shared_ptr<VideoFrame>");
loginScreen = new LoginScreen(); loginScreen = new LoginScreen();

View File

@ -176,9 +176,9 @@ QByteArray Profile::loadToxSave()
uint8_t salt[TOX_PASS_SALT_LENGTH]; uint8_t salt[TOX_PASS_SALT_LENGTH];
tox_get_salt(reinterpret_cast<uint8_t *>(data.data()), salt); tox_get_salt(reinterpret_cast<uint8_t *>(data.data()), salt);
core->setPassword(password, Core::ptMain, salt); core->setPassword(password, salt);
data = core->decryptData(data, Core::ptMain); data = core->decryptData(data);
if (data.isEmpty()) if (data.isEmpty())
qCritical() << "Failed to decrypt the tox save file"; qCritical() << "Failed to decrypt the tox save file";
} }
@ -218,8 +218,8 @@ void Profile::saveToxSave(QByteArray data)
if (!password.isEmpty()) if (!password.isEmpty())
{ {
core->setPassword(password, Core::ptMain); core->setPassword(password);
data = core->encryptData(data, Core::ptMain); data = core->encryptData(data);
if (data.isEmpty()) if (data.isEmpty())
{ {
qCritical() << "Failed to encrypt, can't save!"; qCritical() << "Failed to encrypt, can't save!";
@ -239,7 +239,12 @@ bool Profile::profileExists(QString name)
return QFile::exists(path+".tox") && QFile::exists(path+".ini"); return QFile::exists(path+".tox") && QFile::exists(path+".ini");
} }
bool Profile::isProfileEncrypted(QString name) bool Profile::isEncrypted()
{
return !password.isEmpty();
}
bool Profile::isEncrypted(QString name)
{ {
uint8_t data[encryptHeaderSize] = {0}; uint8_t data[encryptHeaderSize] = {0};
QString path = Settings::getSettingsDirPath() + QDir::separator() + name + ".tox"; QString path = Settings::getSettingsDirPath() + QDir::separator() + name + ".tox";
@ -303,3 +308,8 @@ bool Profile::checkPassword()
return !loadToxSave().isEmpty(); return !loadToxSave().isEmpty();
} }
QString Profile::getPassword()
{
return password;
}

View File

@ -26,7 +26,10 @@ public:
void startCore(); ///< Starts the Core thread void startCore(); ///< Starts the Core thread
bool isNewProfile(); bool isNewProfile();
bool isEncrypted(); ///< Returns true if we have a password set (doesn't check the actual file on disk)
bool checkPassword(); ///< Checks whether the password is valid bool checkPassword(); ///< Checks whether the password is valid
QString getPassword();
QByteArray loadToxSave(); ///< Loads the profile's .tox save from file, unencrypted QByteArray loadToxSave(); ///< Loads the profile's .tox save from file, unencrypted
void saveToxSave(); ///< Saves the profile's .tox save, encrypted if needed. Invalid on deleted profiles. void saveToxSave(); ///< Saves the profile's .tox save, encrypted if needed. Invalid on deleted profiles.
void saveToxSave(QByteArray data); ///< Write the .tox save, encrypted if needed. Invalid on deleted profiles. void saveToxSave(QByteArray data); ///< Write the .tox save, encrypted if needed. Invalid on deleted profiles.
@ -45,7 +48,7 @@ public:
static QVector<QString> getProfiles(); static QVector<QString> getProfiles();
static bool profileExists(QString name); static bool profileExists(QString name);
static bool isProfileEncrypted(QString name); ///< Returns false on error. static bool isEncrypted(QString name); ///< Returns false on error. Checks the actual file on disk.
private: private:
Profile(QString name, QString password, bool newProfile); Profile(QString name, QString password, bool newProfile);

View File

@ -31,15 +31,8 @@ PrivacyForm::PrivacyForm() :
bodyUI = new Ui::PrivacySettings; bodyUI = new Ui::PrivacySettings;
bodyUI->setupUi(this); bodyUI->setupUi(this);
bodyUI->encryptToxHLayout->addStretch();
bodyUI->encryptLogsHLayout->addStretch();
connect(bodyUI->cbTypingNotification, SIGNAL(stateChanged(int)), this, SLOT(onTypingNotificationEnabledUpdated())); connect(bodyUI->cbTypingNotification, SIGNAL(stateChanged(int)), this, SLOT(onTypingNotificationEnabledUpdated()));
connect(bodyUI->cbKeepHistory, SIGNAL(stateChanged(int)), this, SLOT(onEnableLoggingUpdated())); connect(bodyUI->cbKeepHistory, SIGNAL(stateChanged(int)), this, SLOT(onEnableLoggingUpdated()));
connect(bodyUI->cbEncryptHistory, SIGNAL(clicked()), this, SLOT(onEncryptLogsUpdated()));
connect(bodyUI->changeLogsPwButton, &QPushButton::clicked, this, &PrivacyForm::setChatLogsPassword);
connect(bodyUI->cbEncryptTox, SIGNAL(clicked()), this, SLOT(onEncryptToxUpdated()));
connect(bodyUI->changeToxPwButton, &QPushButton::clicked, this, &PrivacyForm::setToxPassword);
connect(bodyUI->nospamLineEdit, SIGNAL(editingFinished()), this, SLOT(setNospam())); connect(bodyUI->nospamLineEdit, SIGNAL(editingFinished()), this, SLOT(setNospam()));
connect(bodyUI->randomNosapamButton, SIGNAL(clicked()), this, SLOT(generateRandomNospam())); connect(bodyUI->randomNosapamButton, SIGNAL(clicked()), this, SLOT(generateRandomNospam()));
connect(bodyUI->nospamLineEdit, SIGNAL(textChanged(QString)), this, SLOT(onNospamEdit())); connect(bodyUI->nospamLineEdit, SIGNAL(textChanged(QString)), this, SLOT(onNospamEdit()));
@ -53,7 +46,6 @@ PrivacyForm::~PrivacyForm()
void PrivacyForm::onEnableLoggingUpdated() void PrivacyForm::onEnableLoggingUpdated()
{ {
Settings::getInstance().setEnableLogging(bodyUI->cbKeepHistory->isChecked()); Settings::getInstance().setEnableLogging(bodyUI->cbKeepHistory->isChecked());
bodyUI->cbEncryptHistory->setEnabled(bodyUI->cbKeepHistory->isChecked());
HistoryKeeper::resetInstance(); HistoryKeeper::resetInstance();
Widget::getInstance()->clearAllReceipts(); Widget::getInstance()->clearAllReceipts();
} }
@ -63,205 +55,6 @@ void PrivacyForm::onTypingNotificationEnabledUpdated()
Settings::getInstance().setTypingNotification(bodyUI->cbTypingNotification->isChecked()); Settings::getInstance().setTypingNotification(bodyUI->cbTypingNotification->isChecked());
} }
bool PrivacyForm::setChatLogsPassword()
{
Core* core = Core::getInstance();
SetPasswordDialog* dialog;
// check if an encrypted history exists because it was disabled earlier, and use it if possible
QString path = HistoryKeeper::getHistoryPath(QString(), 1);
QByteArray salt = core->getSaltFromFile(path);
bool haveEncHist = salt.size() > 0;
QString body = tr("Please set your new chat history password.");
if (haveEncHist)
body += "\n\n" + tr("It appears you have an unused encrypted chat history; if the password matches, it will be added to your current history.");
if (core->isPasswordSet(Core::ptMain))
dialog = new SetPasswordDialog(body, tr("Use data file password", "pushbutton text"), 0);
else
dialog = new SetPasswordDialog(body, QString(), 0);
do {
int r = dialog->exec();
if (r == QDialog::Rejected)
break;
QList<HistoryKeeper::HistMessage> oldMessages = HistoryKeeper::exportMessagesDeleteFile();
QString newpw = dialog->getPassword();
if (r == SetPasswordDialog::Tertiary)
core->useOtherPassword(Core::ptHistory);
else if (haveEncHist)
core->setPassword(newpw, Core::ptHistory, reinterpret_cast<uint8_t*>(salt.data()));
else
core->setPassword(newpw, Core::ptHistory);
if (!haveEncHist || HistoryKeeper::checkPassword(1))
{
Settings::getInstance().setEncryptLogs(true);
HistoryKeeper::getInstance()->importMessages(oldMessages);
if (haveEncHist)
{
Widget::getInstance()->reloadHistory();
GUI::showWarning(tr("Successfully decrypted old chat history","popup title"), tr("You have succesfully decrypted the old chat history, and it has been added to your current history and re-encrypted.", "popup text"));
}
delete dialog;
return true;
}
else
{
if (GUI::askQuestion(tr("Old encrypted chat history", "popup title"), tr("There is currently an unused encrypted chat history, but the password you just entered doesn't match.\n\nIf you don't care about the old history, you may delete it and use the password you just entered.\nOtherwise, hit Cancel to try again.", "This happens when enabling encryption after previously \"Disabling History\""), tr("Delete"), tr("Cancel")))
{
if (GUI::askQuestion(tr("Old encrypted chat history", "popup title"), tr("Are you absolutely sure you want to lose the unused encrypted chat history?", "secondary popup"), tr("Delete"), tr("Cancel")))
haveEncHist = false; // logically this is really just a `break`, but conceptually this is more accurate
}
}
} while (haveEncHist);
delete dialog;
return false;
}
void PrivacyForm::onEncryptLogsUpdated()
{
Core* core = Core::getInstance();
if (bodyUI->cbEncryptHistory->isChecked())
{
if (!core->isPasswordSet(Core::ptHistory))
{
if (setChatLogsPassword())
{
bodyUI->cbEncryptHistory->setChecked(true);
bodyUI->changeLogsPwButton->setEnabled(true);
return;
}
}
}
else
{
QMessageBox box(QMessageBox::Warning,
tr("Old encrypted chat history", "title"),
tr("Would you like to decrypt your chat history?\nOtherwise it will be deleted."),
QMessageBox::NoButton, Widget::getInstance());
QPushButton* decryptBtn = box.addButton(tr("Decrypt"), QMessageBox::YesRole);
QPushButton* deleteBtn = box.addButton(tr("Delete"), QMessageBox::NoRole);
QPushButton* cancelBtn = box.addButton(tr("Cancel"), QMessageBox::RejectRole);
box.setDefaultButton(cancelBtn);
box.setEscapeButton(cancelBtn);
box.exec();
if (box.clickedButton() == decryptBtn)
{
QList<HistoryKeeper::HistMessage> oldMessages = HistoryKeeper::exportMessagesDeleteFile(true);
core->clearPassword(Core::ptHistory);
Settings::getInstance().setEncryptLogs(false);
HistoryKeeper::getInstance()->importMessages(oldMessages);
}
else if (box.clickedButton() == deleteBtn)
{
QMessageBox box2(QMessageBox::Critical,
tr("Old encrypted chat history", "title"),
tr("Are you sure you want to lose your entire chat history?"),
QMessageBox::NoButton, Widget::getInstance());
QPushButton* deleteBtn2 = box2.addButton(tr("Delete"), QMessageBox::AcceptRole);
QPushButton* cancelBtn2 = box2.addButton(tr("Cancel"), QMessageBox::RejectRole);
box2.setDefaultButton(cancelBtn2);
box2.setEscapeButton(cancelBtn2);
box2.exec();
if (box2.clickedButton() == deleteBtn2)
{
HistoryKeeper::removeHistory(true);
}
else
{
bodyUI->cbEncryptHistory->setChecked(true);
return;
}
}
else
{
bodyUI->cbEncryptHistory->setChecked(true);
return;
}
}
core->clearPassword(Core::ptHistory);
Settings::getInstance().setEncryptLogs(false);
bodyUI->cbEncryptHistory->setChecked(false);
bodyUI->changeLogsPwButton->setEnabled(false);
HistoryKeeper::resetInstance();
}
bool PrivacyForm::setToxPassword()
{
Core* core = Core::getInstance();
SetPasswordDialog* dialog;
QString body = tr("Please set your new data file password.");
if (core->isPasswordSet(Core::ptHistory))
dialog = new SetPasswordDialog(body, tr("Use chat history password", "pushbutton text"), 0);
else
dialog = new SetPasswordDialog(body, QString(), 0);
if (int r = dialog->exec())
{
QString newpw = dialog->getPassword();
delete dialog;
if (r == SetPasswordDialog::Tertiary)
core->useOtherPassword(Core::ptMain);
else
core->setPassword(newpw, Core::ptMain);
Settings::getInstance().setEncryptTox(true);
Settings::getInstance().save();
return true;
}
else
{
delete dialog;
return false;
}
}
void PrivacyForm::onEncryptToxUpdated()
{
Core* core = Core::getInstance();
if (bodyUI->cbEncryptTox->isChecked())
{
if (!core->isPasswordSet(Core::ptMain))
{
if (setToxPassword())
{
bodyUI->cbEncryptTox->setChecked(true);
bodyUI->changeToxPwButton->setEnabled(true);
return;
}
}
}
else
{
if (!GUI::askQuestion(tr("Decrypt your data file", "title"),
tr("Would you like to decrypt your data file?"),
tr("Decrypt"), tr("Cancel")))
{
bodyUI->cbEncryptTox->setChecked(true);
return;
}
// affirmative answer falls through to the catch all below
}
bodyUI->cbEncryptTox->setChecked(false);
Settings::getInstance().setEncryptTox(false);
bodyUI->changeToxPwButton->setEnabled(false);
core->clearPassword(Core::ptMain);
}
void PrivacyForm::setNospam() void PrivacyForm::setNospam()
{ {
QString newNospam = bodyUI->nospamLineEdit->text(); QString newNospam = bodyUI->nospamLineEdit->text();
@ -277,11 +70,6 @@ void PrivacyForm::present()
bodyUI->nospamLineEdit->setText(Core::getInstance()->getSelfId().noSpam); bodyUI->nospamLineEdit->setText(Core::getInstance()->getSelfId().noSpam);
bodyUI->cbTypingNotification->setChecked(Settings::getInstance().isTypingNotificationEnabled()); bodyUI->cbTypingNotification->setChecked(Settings::getInstance().isTypingNotificationEnabled());
bodyUI->cbKeepHistory->setChecked(Settings::getInstance().getEnableLogging()); bodyUI->cbKeepHistory->setChecked(Settings::getInstance().getEnableLogging());
bodyUI->cbEncryptHistory->setChecked(Settings::getInstance().getEncryptLogs());
bodyUI->changeLogsPwButton->setEnabled(Settings::getInstance().getEncryptLogs());
bodyUI->cbEncryptHistory->setEnabled(Settings::getInstance().getEnableLogging());
bodyUI->cbEncryptTox->setChecked(Settings::getInstance().getEncryptTox());
bodyUI->changeToxPwButton->setEnabled(Settings::getInstance().getEncryptTox());
} }
void PrivacyForm::generateRandomNospam() void PrivacyForm::generateRandomNospam()

View File

@ -36,10 +36,6 @@ private slots:
void setNospam(); void setNospam();
void generateRandomNospam(); void generateRandomNospam();
void onNospamEdit(); void onNospamEdit();
void onEncryptLogsUpdated();
bool setChatLogsPassword();
void onEncryptToxUpdated();
bool setToxPassword();
private: private:
Ui::PrivacySettings* bodyUI; Ui::PrivacySettings* bodyUI;

View File

@ -37,7 +37,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>380</width> <width>380</width>
<height>391</height> <height>280</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_3"> <layout class="QVBoxLayout" name="verticalLayout_3">
@ -47,7 +47,7 @@
<string comment="tooltip for typing notifications setting">Your friends will be able to see when you are typing.</string> <string comment="tooltip for typing notifications setting">Your friends will be able to see when you are typing.</string>
</property> </property>
<property name="text"> <property name="text">
<string>Send Typing Notifications</string> <string>Send typing notifications</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -58,77 +58,10 @@
Save format changes are possible, which may result in data loss.</string> Save format changes are possible, which may result in data loss.</string>
</property> </property>
<property name="text"> <property name="text">
<string>Keep chat history (mostly stable)</string> <string>Keep chat history</string>
</property> </property>
</widget> </widget>
</item> </item>
<item alignment="Qt::AlignTop">
<widget class="QGroupBox" name="encryptionGroup">
<property name="enabled">
<bool>true</bool>
</property>
<property name="title">
<string>Local file encryption</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="encryptStatement">
<property name="text">
<string>All Tox communications over the internet are encrypted, and this cannot be disabled. However, you may optionally password protect your local Tox files.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="encryptToxHLayout">
<item>
<widget class="QCheckBox" name="cbEncryptTox">
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string>Encrypt Tox data file</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="changeToxPwButton">
<property name="text">
<string>Change password</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="encryptLogsHLayout">
<item>
<widget class="QCheckBox" name="cbEncryptHistory">
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string>Encrypt chat history</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="changeLogsPwButton">
<property name="text">
<string>Change password</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item alignment="Qt::AlignTop"> <item alignment="Qt::AlignTop">
<widget class="QGroupBox" name="nospamGroup"> <widget class="QGroupBox" name="nospamGroup">
<property name="toolTip"> <property name="toolTip">
@ -138,9 +71,19 @@ When you change nospam, your current contacts still can communicate with you,
but new contacts need to know your new Tox ID to be able to add you.</string> but new contacts need to know your new Tox ID to be able to add you.</string>
</property> </property>
<property name="title"> <property name="title">
<string>Nospam</string> <string>NoSpam</string>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_4"> <layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>The NoSpam is part of your Tox ID, if you are getting spammed with friend requests, change the NoSpam.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout"> <layout class="QHBoxLayout" name="horizontalLayout">
<item> <item>
@ -153,7 +96,7 @@ but new contacts need to know your new Tox ID to be able to add you.</string>
<item> <item>
<widget class="QPushButton" name="randomNosapamButton"> <widget class="QPushButton" name="randomNosapamButton">
<property name="text"> <property name="text">
<string>Generate random nospam</string> <string>Generate random NoSpam</string>
</property> </property>
</widget> </widget>
</item> </item>

View File

@ -108,7 +108,7 @@ void LoginScreen::onLoginUsernameSelected(const QString &name)
return; return;
ui->loginPassword->clear(); ui->loginPassword->clear();
if (Profile::isProfileEncrypted(name)) if (Profile::isEncrypted(name))
{ {
ui->loginPasswordLabel->show(); ui->loginPasswordLabel->show();
ui->loginPassword->show(); ui->loginPassword->show();