1
0
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:
dubslow 2014-10-24 06:25:40 -05:00
parent 3607240152
commit 7260fdd38d
4 changed files with 99 additions and 84 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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);
} }
} }

View File

@ -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();