1
0
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:
apprb 2014-10-22 22:36:36 +09:00
parent dfd5b6411a
commit 5c0370eaed
No known key found for this signature in database
GPG Key ID: B001911B5B22FB9B
7 changed files with 99 additions and 98 deletions

View File

@ -53,6 +53,9 @@ Core::Core(Camera* cam, QThread *coreThread, QString loadPath) :
videobuf = new uint8_t[videobufsize]; videobuf = new uint8_t[videobufsize];
videoBusyness=0; videoBusyness=0;
for (int i = 0; i < ptCounter; i++)
pwsaltedkey[i] = nullptr;
toxTimer = new QTimer(this); toxTimer = new QTimer(this);
toxTimer->setSingleShot(true); toxTimer->setSingleShot(true);
connect(toxTimer, &QTimer::timeout, this, &Core::process); connect(toxTimer, &QTimer::timeout, this, &Core::process);
@ -116,7 +119,8 @@ Core::~Core()
if (alInDev) if (alInDev)
alcCaptureCloseDevice(alInDev); alcCaptureCloseDevice(alInDev);
clearPassword(); clearPassword(Core::ptMain);
clearPassword(Core::ptHistory);
} }
Core* Core::getInstance() Core* Core::getInstance()
@ -1096,10 +1100,10 @@ bool Core::loadConfiguration(QString path)
if (Settings::getInstance().getEncryptTox()) if (Settings::getInstance().getEncryptTox())
{ {
while (!isPasswordSet()) while (!isPasswordSet(ptMain))
{ {
emit blockingGetPassword(tr("Tox datafile decryption password")); emit blockingGetPassword(tr("Tox datafile decryption password"), ptMain);
if (!isPasswordSet()) if (!isPasswordSet(ptMain))
QMessageBox::warning(nullptr, tr("Password error"), tr("Failed to setup password.\nEmpty password.")); QMessageBox::warning(nullptr, tr("Password error"), tr("Failed to setup password.\nEmpty password."));
} }
} }
@ -1116,15 +1120,15 @@ bool Core::loadConfiguration(QString path)
{ {
do do
{ {
while (!isPasswordSet()) while (!isPasswordSet(ptMain))
{ {
emit blockingGetPassword(tr("Tox datafile decryption password")); emit blockingGetPassword(tr("Tox datafile decryption password"), ptMain);
if (!isPasswordSet()) if (!isPasswordSet(ptMain))
QMessageBox::warning(nullptr, tr("Password error"), tr("Failed to setup password.\nEmpty password.")); 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(), 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) if (error != 0)
{ {
QMessageBox msgb; QMessageBox msgb;
@ -1140,14 +1144,14 @@ bool Core::loadConfiguration(QString path)
if (msgb.clickedButton() == tryAgain) if (msgb.clickedButton() == tryAgain)
{ {
clearPassword(); 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(); clearPassword(ptMain);
Settings::getInstance().setEncryptTox(false); Settings::getInstance().setEncryptTox(false);
error = 0; error = 0;
} }
@ -1161,46 +1165,35 @@ bool Core::loadConfiguration(QString path)
// tox core is already decrypted // tox core is already decrypted
if (Settings::getInstance().getEnableLogging() && Settings::getInstance().getEncryptLogs()) 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()) if (!HistoryKeeper::checkPassword())
{ {
QMessageBox::warning(nullptr, tr("Different passwords!"), if (QMessageBox::Ok == QMessageBox::warning(nullptr, tr("Encrypted log"),
tr("Tox datafile and history log encrypted with different passwords.")); tr("Your history encrypted with different password\nDo you want to try another password?"),
Settings::getInstance().setEncryptLogs(false); QMessageBox::Ok | QMessageBox::Cancel))
Settings::getInstance().setEnableLogging(false);
}
} else {
bool error = true;
do
{
while (!isPasswordSet())
{ {
emit blockingGetPassword(tr("History Log decpytion password")); error = true;
if (!isPasswordSet()) clearPassword(ptHistory);
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);
}
} else { } else {
error = false; 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(); configurationFile.close();
@ -1273,13 +1266,14 @@ void Core::saveConfiguration(const QString& path)
if (Settings::getInstance().getEncryptTox()) if (Settings::getInstance().getEncryptTox())
{ {
if (!isPasswordSet()) if (!isPasswordSet(ptMain))
{ {
// probably zero chance event // probably zero chance event
QMessageBox::warning(nullptr, tr("NO Password"), tr("Will be saved without encryption!")); QMessageBox::warning(nullptr, tr("NO Password"), tr("Will be saved without encryption!"));
tox_save(tox, data); tox_save(tox, data);
} else { } 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) if (ret == -1)
{ {
qCritical() << "Core::saveConfiguration: encryption of save file failed!!!"; 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; qDebug() << "Core: switching from" << Settings::getInstance().getCurrentProfile() << "to" << profile;
saveConfiguration(); saveConfiguration();
clearPassword(); clearPassword(ptMain);
clearPassword(ptHistory);
toxTimer->stop(); toxTimer->stop();
if (tox) { if (tox) {
@ -1322,7 +1317,6 @@ void Core::switchConfiguration(const QString& profile)
loadPath = QDir(Settings::getSettingsDirPath()).filePath(profile + TOX_EXT); loadPath = QDir(Settings::getSettingsDirPath()).filePath(profile + TOX_EXT);
Settings::getInstance().setCurrentProfile(profile); Settings::getInstance().setCurrentProfile(profile);
HistoryKeeper::getInstance()->resetInstance(); HistoryKeeper::getInstance()->resetInstance();
clearPassword();
start(); start();
} }
@ -1604,43 +1598,43 @@ QList<CString> Core::splitMessage(const QString &message)
return splittedMsgs; return splittedMsgs;
} }
void Core::setPassword(QString& password) void Core::setPassword(QString& password, PasswordType passtype)
{ {
if (password.isEmpty()) if (password.isEmpty())
{ {
clearPassword(); clearPassword(passtype);
return; return;
} }
if (!pwsaltedkey) if (!pwsaltedkey[passtype])
pwsaltedkey = new uint8_t[tox_pass_key_length()]; pwsaltedkey[passtype] = new uint8_t[tox_pass_key_length()];
CString str(password); 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[passtype].clear();
barePassword.append(password); barePassword[passtype].append(password);
password.clear(); password.clear();
} }
void Core::clearPassword() void Core::clearPassword(PasswordType passtype)
{ {
if (pwsaltedkey) if (pwsaltedkey[passtype])
{ {
delete[] pwsaltedkey; delete[] pwsaltedkey[passtype];
pwsaltedkey = nullptr; pwsaltedkey[passtype] = nullptr;
barePassword.clear(); barePassword[passtype].clear();
} }
} }
QByteArray Core::encryptData(const QByteArray& data) QByteArray Core::encryptData(const QByteArray& data, PasswordType passtype)
{ {
if (!pwsaltedkey) if (!pwsaltedkey[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, 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(), 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"; qWarning() << "Core::encryptData: encryption failed";
return QByteArray(); 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()); 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(); 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, 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(), 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"; qWarning() << "Core::decryptData: decryption failed";
return QByteArray(); return QByteArray();
@ -1664,9 +1658,9 @@ QByteArray Core::decryptData(const QByteArray& data)
return QByteArray(reinterpret_cast<char*>(decrypted), sz); return QByteArray(reinterpret_cast<char*>(decrypted), sz);
} }
bool Core::isPasswordSet() bool Core::isPasswordSet(PasswordType passtype)
{ {
if (pwsaltedkey) if (pwsaltedkey[passtype])
return true; return true;
return false; return false;

View File

@ -34,6 +34,8 @@ class Core : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
enum PasswordType {ptMain = 0, ptHistory, ptCounter};
explicit Core(Camera* cam, QThread* coreThread, QString initialLoadPath); explicit Core(Camera* cam, QThread* coreThread, QString initialLoadPath);
static Core* getInstance(); ///< Returns the global widget's Core instance static Core* getInstance(); ///< Returns the global widget's Core instance
~Core(); ~Core();
@ -64,7 +66,7 @@ public:
void decreaseVideoBusyness(); void decreaseVideoBusyness();
bool anyActiveCalls(); bool anyActiveCalls();
bool isPasswordSet(); bool isPasswordSet(PasswordType passtype);
public slots: public slots:
void start(); void start();
@ -105,16 +107,16 @@ public slots:
void micMuteToggle(int callId); void micMuteToggle(int callId);
void setPassword(QString& password); void setPassword(QString& password, PasswordType passtype);
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();
void disconnected(); void disconnected();
void blockingClearContacts(); void blockingClearContacts();
void blockingGetPassword(QString info); void blockingGetPassword(QString info, int passtype);
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);
@ -251,8 +253,9 @@ private:
int dhtServerId; int dhtServerId;
static QList<ToxFile> fileSendQueue, fileRecvQueue; static QList<ToxFile> fileSendQueue, fileRecvQueue;
static ToxCall calls[]; 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 const int videobufsize;
static uint8_t* videobuf; static uint8_t* videobuf;

View File

@ -39,8 +39,9 @@ public:
static HistoryKeeper* getInstance(); static HistoryKeeper* getInstance();
static void resetInstance(); static void resetInstance();
static bool checkPassword();
static QString getHistoryPath(); static QString getHistoryPath();
static bool checkPassword();
static void renameHistory(QString from, QString to); static void renameHistory(QString from, QString to);
void addChatEntry(const QString& chat, const QString& message, const QString& sender, const QDateTime &dt); void addChatEntry(const QString& chat, const QString& message, const QString& sender, const QDateTime &dt);

View File

@ -24,7 +24,7 @@
#include <QDebug> #include <QDebug>
#include <QSqlError> #include <QSqlError>
qint64 EncryptedDb::plainChunkSize = 1024; qint64 EncryptedDb::plainChunkSize = 4096;
qint64 EncryptedDb::encryptedChunkSize = EncryptedDb::plainChunkSize + tox_pass_encryption_extra_length(); qint64 EncryptedDb::encryptedChunkSize = EncryptedDb::plainChunkSize + tox_pass_encryption_extra_length();
EncryptedDb::EncryptedDb(const QString &fname, QList<QString> initList) : EncryptedDb::EncryptedDb(const QString &fname, QList<QString> initList) :
@ -50,7 +50,8 @@ EncryptedDb::EncryptedDb(const QString &fname, QList<QString> initList) :
EncryptedDb::~EncryptedDb() 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) QSqlQuery EncryptedDb::exec(const QString &query)
@ -70,7 +71,7 @@ bool EncryptedDb::pullFileContent()
while (!encrFile.atEnd()) while (!encrFile.atEnd())
{ {
QByteArray encrChunk = encrFile.read(encryptedChunkSize); QByteArray encrChunk = encrFile.read(encryptedChunkSize);
buffer = Core::getInstance()->decryptData(encrChunk); buffer = Core::getInstance()->decryptData(encrChunk, Core::ptHistory);
if (buffer.size() > 0) if (buffer.size() > 0)
{ {
fileContent += buffer; fileContent += buffer;
@ -129,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); QByteArray encr = Core::getInstance()->encryptData(filledChunk, Core::ptHistory);
if (encr.size() > 0) if (encr.size() > 0)
{ {
encrFile.write(encr); encrFile.write(encr);
@ -140,7 +141,7 @@ void EncryptedDb::appendToEncrypted(const QString &sql)
} }
encrFile.seek(chunkPosition * encryptedChunkSize); encrFile.seek(chunkPosition * encryptedChunkSize);
QByteArray encr = Core::getInstance()->encryptData(buffer); QByteArray encr = Core::getInstance()->encryptData(buffer, Core::ptHistory);
if (encr.size() > 0) if (encr.size() > 0)
{ {
encrFile.write(encr); encrFile.write(encr);
@ -157,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); QByteArray buf = Core::getInstance()->decryptData(encrChunk, Core::ptHistory);
if (buf.size() == 0) if (buf.size() == 0)
{ {
state = false; state = false;

View File

@ -65,7 +65,7 @@ void PrivacyForm::onEncryptLogsUpdated()
if (encrytionState) if (encrytionState)
{ {
if (!Core::getInstance()->isPasswordSet()) if (!Core::getInstance()->isPasswordSet(Core::ptHistory))
{ {
SetPasswordDialog dialog; SetPasswordDialog dialog;
if (dialog.exec()) if (dialog.exec())
@ -74,10 +74,10 @@ void PrivacyForm::onEncryptLogsUpdated()
if (pswd.size() == 0) if (pswd.size() == 0)
encrytionState = false; encrytionState = false;
Core::getInstance()->setPassword(pswd); Core::getInstance()->setPassword(pswd, Core::ptHistory);
} else { } else {
encrytionState = false; encrytionState = false;
Core::getInstance()->clearPassword(); Core::getInstance()->clearPassword(Core::ptHistory);
} }
} }
} }
@ -100,8 +100,8 @@ void PrivacyForm::onEncryptLogsUpdated()
if (encrytionState) if (encrytionState)
HistoryKeeper::resetInstance(); HistoryKeeper::resetInstance();
if (!Settings::getInstance().getEncryptLogs() && !Settings::getInstance().getEncryptTox()) if (!Settings::getInstance().getEncryptLogs())
Core::getInstance()->clearPassword(); Core::getInstance()->clearPassword(Core::ptHistory);
} }
void PrivacyForm::onEncryptToxUpdated() void PrivacyForm::onEncryptToxUpdated()
@ -110,7 +110,7 @@ void PrivacyForm::onEncryptToxUpdated()
if (encrytionState) if (encrytionState)
{ {
if (!Core::getInstance()->isPasswordSet()) if (!Core::getInstance()->isPasswordSet(Core::ptMain))
{ {
SetPasswordDialog dialog; SetPasswordDialog dialog;
if (dialog.exec()) if (dialog.exec())
@ -119,10 +119,10 @@ void PrivacyForm::onEncryptToxUpdated()
if (pswd.size() == 0) if (pswd.size() == 0)
encrytionState = false; encrytionState = false;
Core::getInstance()->setPassword(pswd); Core::getInstance()->setPassword(pswd, Core::ptMain);
} else { } else {
encrytionState = false; encrytionState = false;
Core::getInstance()->clearPassword(); Core::getInstance()->clearPassword(Core::ptMain);
} }
} }
} }
@ -130,6 +130,6 @@ void PrivacyForm::onEncryptToxUpdated()
bodyUI->cbEncryptTox->setChecked(encrytionState); bodyUI->cbEncryptTox->setChecked(encrytionState);
Settings::getInstance().setEncryptTox(encrytionState); Settings::getInstance().setEncryptTox(encrytionState);
if (!Settings::getInstance().getEncryptLogs() && !Settings::getInstance().getEncryptTox()) if (!Settings::getInstance().getEncryptTox())
Core::getInstance()->clearPassword(); Core::getInstance()->clearPassword(Core::ptMain);
} }

View File

@ -134,6 +134,7 @@ Widget::Widget(QWidget *parent)
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");
QString profilePath = detectProfile(); QString profilePath = detectProfile();
coreThread = new QThread(this); 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()); 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); InputPasswordDialog dialog(info);
if (dialog.exec()) if (dialog.exec())
{ {
QString pswd = dialog.getPassword(); QString pswd = dialog.getPassword();
if (pswd.isEmpty()) if (pswd.isEmpty())
core->clearPassword(); core->clearPassword(pt);
else else
core->setPassword(pswd); core->setPassword(pswd, pt);
} }
} }

View File

@ -112,7 +112,7 @@ private slots:
void playRingtone(); void playRingtone();
void onIconClick(); void onIconClick();
void onUserAway(); void onUserAway();
void getPassword(QString info); void getPassword(QString info, int passtype);
private: private:
void hideMainForms(); void hideMainForms();