mirror of
https://github.com/qTox/qTox.git
synced 2024-03-22 14:00:36 +08:00
refactor(encryption): move everything to ToxEncrypt
This commit removes coreencryption.cpp and replaces it with ToxEncrypt.
This commit is contained in:
parent
f6b1cf9311
commit
7cd800374a
|
@ -192,7 +192,6 @@ set(${PROJECT_NAME}_SOURCES
|
|||
src/core/coreav.h
|
||||
src/core/core.cpp
|
||||
src/core/coredefines.h
|
||||
src/core/coreencryption.cpp
|
||||
src/core/corefile.cpp
|
||||
src/core/corefile.h
|
||||
src/core/core.h
|
||||
|
|
1
qtox.pro
1
qtox.pro
|
@ -556,7 +556,6 @@ SOURCES += \
|
|||
src/chatlog/pixmapcache.cpp \
|
||||
src/core/core.cpp \
|
||||
src/core/coreav.cpp \
|
||||
src/core/coreencryption.cpp \
|
||||
src/core/corefile.cpp \
|
||||
src/core/corestructs.cpp \
|
||||
src/core/cstring.cpp \
|
||||
|
|
|
@ -79,12 +79,6 @@ public:
|
|||
ToxId getSelfId() const;
|
||||
QPair<QByteArray, QByteArray> getKeypair() const;
|
||||
|
||||
static std::shared_ptr<Tox_Pass_Key> createPasskey(const QString &password, uint8_t* salt = nullptr);
|
||||
static QByteArray encryptData(const QByteArray& data, const Tox_Pass_Key& encryptionKey);
|
||||
static QByteArray encryptData(const QByteArray& data);
|
||||
static QByteArray decryptData(const QByteArray& data, const Tox_Pass_Key &encryptionKey);
|
||||
static QByteArray decryptData(const QByteArray& data);
|
||||
|
||||
bool isReady() const;
|
||||
|
||||
void sendFile(uint32_t friendId, QString filename, QString filePath, long long filesize);
|
||||
|
|
|
@ -1,125 +0,0 @@
|
|||
/*
|
||||
Copyright © 2014-2015 by The qTox Project Contributors
|
||||
|
||||
This file is part of qTox, a Qt-based graphical interface for Tox.
|
||||
|
||||
qTox is libre software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qTox is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qTox. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* This file is part of the Core class, but was separated for my sanity */
|
||||
/* The load function delegates to loadEncrypted here, and the save function */
|
||||
/* was permanently moved here to handle encryption */
|
||||
|
||||
#include "core.h"
|
||||
#include "src/widget/gui.h"
|
||||
#include "src/persistence/settings.h"
|
||||
#include "src/core/cstring.h"
|
||||
#include "src/nexus.h"
|
||||
#include "src/persistence/profile.h"
|
||||
#include <tox/tox.h>
|
||||
#include <tox/toxencryptsave.h>
|
||||
#include <QApplication>
|
||||
#include <QDebug>
|
||||
#include <QSaveFile>
|
||||
#include <QFile>
|
||||
#include <QThread>
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
|
||||
std::shared_ptr<Tox_Pass_Key> Core::createPasskey(const QString& password, uint8_t* salt)
|
||||
{
|
||||
std::shared_ptr<Tox_Pass_Key> encryptionKey(tox_pass_key_new(), tox_pass_key_free);
|
||||
|
||||
CString str(password);
|
||||
if (salt)
|
||||
tox_pass_key_derive_with_salt(encryptionKey.get(), str.data(), str.size(), salt, nullptr);
|
||||
else
|
||||
tox_pass_key_derive(encryptionKey.get(), str.data(), str.size(), nullptr);
|
||||
|
||||
return encryptionKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Encrypts data.
|
||||
* @note Uses the default profile's key.
|
||||
* @param data Data to encrypt.
|
||||
* @return Encrypted data.
|
||||
*/
|
||||
QByteArray Core::encryptData(const QByteArray &data)
|
||||
{
|
||||
return encryptData(data, Nexus::getProfile()->getPasskey());
|
||||
}
|
||||
|
||||
QByteArray Core::encryptData(const QByteArray& data, const Tox_Pass_Key& encryptionKey)
|
||||
{
|
||||
QByteArray encrypted(data.size() + TOX_PASS_ENCRYPTION_EXTRA_LENGTH, 0x00);
|
||||
if (!tox_pass_key_encrypt(&encryptionKey, reinterpret_cast<const uint8_t*>(data.data()), data.size(),
|
||||
(uint8_t*) encrypted.data(), nullptr))
|
||||
{
|
||||
qWarning() << "Encryption failed";
|
||||
return QByteArray();
|
||||
}
|
||||
return encrypted;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Decrypts data.
|
||||
* @note Uses the default profile's key.
|
||||
* @param data Data to decrypt.
|
||||
* @return Decrypted data.
|
||||
*/
|
||||
QByteArray Core::decryptData(const QByteArray &data)
|
||||
{
|
||||
return decryptData(data, Nexus::getProfile()->getPasskey());
|
||||
}
|
||||
|
||||
QByteArray Core::decryptData(const QByteArray& data, const Tox_Pass_Key& encryptionKey)
|
||||
{
|
||||
if (data.size() < TOX_PASS_ENCRYPTION_EXTRA_LENGTH)
|
||||
{
|
||||
qWarning() << "Not enough data:" << data.size();
|
||||
return QByteArray();
|
||||
}
|
||||
int decryptedSize = data.size() - TOX_PASS_ENCRYPTION_EXTRA_LENGTH;
|
||||
QByteArray decrypted(decryptedSize, 0x00);
|
||||
if (!tox_pass_key_decrypt(&encryptionKey, reinterpret_cast<const uint8_t*>(data.data()), data.size(),
|
||||
(uint8_t*) decrypted.data(), nullptr))
|
||||
{
|
||||
qWarning() << "Decryption failed";
|
||||
return QByteArray();
|
||||
}
|
||||
return decrypted;
|
||||
}
|
||||
|
||||
QByteArray Core::getSaltFromFile(QString filename)
|
||||
{
|
||||
QFile file(filename);
|
||||
if (!file.open(QIODevice::ReadOnly))
|
||||
{
|
||||
qWarning() << "file" << filename << "doesn't exist";
|
||||
return QByteArray();
|
||||
}
|
||||
QByteArray data = file.read(TOX_PASS_ENCRYPTION_EXTRA_LENGTH);
|
||||
file.close();
|
||||
|
||||
uint8_t salt[TOX_PASS_SALT_LENGTH];
|
||||
if (!tox_get_salt(reinterpret_cast<uint8_t *>(data.data()), salt, nullptr))
|
||||
{
|
||||
qWarning() << "can't get salt from" << filename << "header";
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
QByteArray res(reinterpret_cast<const char*>(salt), TOX_PASS_SALT_LENGTH);
|
||||
return res;
|
||||
}
|
|
@ -53,11 +53,6 @@ Profile::Profile(QString name, const QString& password, bool isNewProfile)
|
|||
: name{name}, password{password}
|
||||
, newProfile{isNewProfile}, isRemoved{false}
|
||||
{
|
||||
if (!password.isEmpty())
|
||||
{
|
||||
passkey = core->createPasskey(password);
|
||||
}
|
||||
|
||||
Settings& s = Settings::getInstance();
|
||||
s.setCurrentProfile(name);
|
||||
s.saveGlobal();
|
||||
|
@ -92,6 +87,8 @@ Profile* Profile::loadProfile(QString name, const QString& password)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<ToxEncrypt> tmpKey;
|
||||
|
||||
// Check password
|
||||
{
|
||||
QString path = Settings::getInstance().getSettingsDirPath() + name + ".tox";
|
||||
|
@ -121,7 +118,7 @@ Profile* Profile::loadProfile(QString name, const QString& password)
|
|||
}
|
||||
|
||||
QByteArray data = saveFile.readAll();
|
||||
if (tox_is_data_encrypted((uint8_t*)data.data()))
|
||||
if (ToxEncrypt::isEncrypted(data))
|
||||
{
|
||||
if (password.isEmpty())
|
||||
{
|
||||
|
@ -130,11 +127,15 @@ Profile* Profile::loadProfile(QString name, const QString& password)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
uint8_t salt[TOX_PASS_SALT_LENGTH];
|
||||
tox_get_salt(reinterpret_cast<uint8_t*>(data.data()), salt, nullptr);
|
||||
auto tmpkey = Core::createPasskey(password, salt);
|
||||
tmpKey = ToxEncrypt::makeToxEncrypt(password, data);
|
||||
if (!tmpKey)
|
||||
{
|
||||
qCritical() << "Failed to derive key of the tox save file";
|
||||
ProfileLocker::unlock();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
data = Core::decryptData(data, *tmpkey);
|
||||
data = tmpKey->decrypt(data);
|
||||
if (data.isEmpty())
|
||||
{
|
||||
qCritical() << "Failed to decrypt the tox save file";
|
||||
|
@ -152,6 +153,8 @@ Profile* Profile::loadProfile(QString name, const QString& password)
|
|||
}
|
||||
|
||||
Profile* p = new Profile(name, password, false);
|
||||
p->passkey = std::move(tmpKey);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
|
@ -165,6 +168,17 @@ Profile* Profile::loadProfile(QString name, const QString& password)
|
|||
*/
|
||||
Profile* Profile::createProfile(QString name, QString password)
|
||||
{
|
||||
std::unique_ptr<ToxEncrypt> tmpKey;
|
||||
if(!password.isEmpty())
|
||||
{
|
||||
tmpKey = ToxEncrypt::makeToxEncrypt(password);
|
||||
if (!tmpKey)
|
||||
{
|
||||
qCritical() << "Failed to derive key for the tox save";
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (ProfileLocker::hasLock())
|
||||
{
|
||||
qCritical() << "Tried to create profile "<<name<<", but another profile is already locked!";
|
||||
|
@ -184,7 +198,10 @@ Profile* Profile::createProfile(QString name, QString password)
|
|||
}
|
||||
|
||||
Settings::getInstance().createPersonal(name);
|
||||
return new Profile(name, password, true);
|
||||
Profile* p = new Profile(name, password, true);
|
||||
p->passkey = std::move(tmpKey);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
Profile::~Profile()
|
||||
|
@ -308,7 +325,7 @@ QByteArray Profile::loadToxSave()
|
|||
}
|
||||
|
||||
data = saveFile.readAll();
|
||||
if (tox_is_data_encrypted((uint8_t*)data.data()))
|
||||
if (ToxEncrypt::isEncrypted(data))
|
||||
{
|
||||
if (password.isEmpty())
|
||||
{
|
||||
|
@ -317,14 +334,12 @@ QByteArray Profile::loadToxSave()
|
|||
goto fail;
|
||||
}
|
||||
|
||||
uint8_t salt[TOX_PASS_SALT_LENGTH];
|
||||
tox_get_salt(reinterpret_cast<uint8_t*>(data.data()), salt, nullptr);
|
||||
passkey = core->createPasskey(password, salt);
|
||||
|
||||
data = core->decryptData(data, *passkey);
|
||||
data = passkey->decrypt(data);
|
||||
if (data.isEmpty())
|
||||
{
|
||||
qCritical() << "Failed to decrypt the tox save file";
|
||||
data.clear();
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -374,8 +389,7 @@ void Profile::saveToxSave(QByteArray data)
|
|||
|
||||
if (!password.isEmpty())
|
||||
{
|
||||
passkey = core->createPasskey(password);
|
||||
data = core->encryptData(data, *passkey);
|
||||
data = passkey->encrypt(data);
|
||||
if (data.isEmpty())
|
||||
{
|
||||
qCritical() << "Failed to encrypt, can't save!";
|
||||
|
@ -480,10 +494,8 @@ QByteArray Profile::loadAvatarData(const QString& ownerId, const QString& passwo
|
|||
QByteArray pic = file.readAll();
|
||||
if (encrypted && !pic.isEmpty())
|
||||
{
|
||||
uint8_t salt[TOX_PASS_SALT_LENGTH];
|
||||
tox_get_salt(reinterpret_cast<uint8_t*>(pic.data()), salt, nullptr);
|
||||
auto passkey = core->createPasskey(password, salt);
|
||||
pic = core->decryptData(pic, *passkey);
|
||||
// TODO: check if we can use passkey-decrypt(pic) here
|
||||
pic = ToxEncrypt::decryptPass(password, pic);
|
||||
}
|
||||
|
||||
return pic;
|
||||
|
@ -526,7 +538,7 @@ void Profile::saveAvatar(QByteArray pic, const QString& ownerId)
|
|||
{
|
||||
if (!password.isEmpty() && !pic.isEmpty())
|
||||
{
|
||||
pic = core->encryptData(pic, *passkey);
|
||||
pic = passkey->encrypt(pic);
|
||||
}
|
||||
|
||||
QString path = avatarPath(ownerId);
|
||||
|
@ -745,7 +757,7 @@ QString Profile::getPassword() const
|
|||
return password;
|
||||
}
|
||||
|
||||
const Tox_Pass_Key& Profile::getPasskey() const
|
||||
const ToxEncrypt& Profile::getPasskey() const
|
||||
{
|
||||
return *passkey;
|
||||
}
|
||||
|
@ -772,10 +784,19 @@ void Profile::setPassword(const QString& newPassword)
|
|||
{
|
||||
QByteArray avatar = loadAvatarData(core->getSelfId().getPublicKey().toString());
|
||||
QString oldPassword = password;
|
||||
std::unique_ptr<ToxEncrypt> oldpasskey = std::move(passkey);
|
||||
password = newPassword;
|
||||
passkey = core->createPasskey(password);
|
||||
passkey = ToxEncrypt::makeToxEncrypt(password);
|
||||
if(!passkey)
|
||||
{
|
||||
qCritical() << "Failed to derive key from password, the profile won't use the new password";
|
||||
password = oldPassword;
|
||||
passkey = std::move(oldpasskey);
|
||||
return;
|
||||
}
|
||||
saveToxSave();
|
||||
|
||||
// TODO: ensure the database and the tox save file use the same password
|
||||
if (database)
|
||||
{
|
||||
database->setPassword(newPassword);
|
||||
|
|
|
@ -22,8 +22,7 @@
|
|||
#define PROFILE_H
|
||||
|
||||
#include "src/core/toxid.h"
|
||||
|
||||
#include <tox/toxencryptsave.h>
|
||||
#include "src/core/toxencrypt.h"
|
||||
|
||||
#include "src/persistence/history.h"
|
||||
|
||||
|
@ -56,7 +55,7 @@ public:
|
|||
bool checkPassword();
|
||||
QString getPassword() const;
|
||||
void setPassword(const QString& newPassword);
|
||||
const Tox_Pass_Key& getPasskey() const;
|
||||
const ToxEncrypt& getPasskey() const;
|
||||
|
||||
QByteArray loadToxSave();
|
||||
void saveToxSave();
|
||||
|
@ -96,7 +95,7 @@ private:
|
|||
Core* core;
|
||||
QThread* coreThread;
|
||||
QString name, password;
|
||||
std::shared_ptr<Tox_Pass_Key> passkey;
|
||||
std::unique_ptr<ToxEncrypt> passkey;
|
||||
std::shared_ptr<RawDatabase> database;
|
||||
std::unique_ptr<History> history;
|
||||
bool newProfile;
|
||||
|
|
|
@ -19,9 +19,10 @@
|
|||
|
||||
#include "settingsserializer.h"
|
||||
#include "serialize.h"
|
||||
#include "src/nexus.h"
|
||||
|
||||
#include "src/core/toxencrypt.h"
|
||||
#include "src/persistence/profile.h"
|
||||
#include "src/core/core.h"
|
||||
|
||||
#include <QSaveFile>
|
||||
#include <QFile>
|
||||
#include <QDebug>
|
||||
|
@ -328,9 +329,8 @@ void SettingsSerializer::save()
|
|||
// Encrypt
|
||||
if (!password.isEmpty())
|
||||
{
|
||||
Core* core = Nexus::getCore();
|
||||
auto passkey = core->createPasskey(password);
|
||||
data = core->encryptData(data, *passkey);
|
||||
// TODO: use passkey
|
||||
data = ToxEncrypt::encryptPass(password, data);
|
||||
}
|
||||
|
||||
f.write(data);
|
||||
|
@ -367,13 +367,7 @@ void SettingsSerializer::readSerialized()
|
|||
return;
|
||||
}
|
||||
|
||||
Core* core = Nexus::getCore();
|
||||
|
||||
uint8_t salt[TOX_PASS_SALT_LENGTH];
|
||||
tox_get_salt(reinterpret_cast<uint8_t *>(data.data()), salt, nullptr);
|
||||
auto passkey = core->createPasskey(password, salt);
|
||||
|
||||
data = core->decryptData(data, *passkey);
|
||||
data = ToxEncrypt::decryptPass(password, data);
|
||||
if (data.isEmpty())
|
||||
{
|
||||
qCritical() << "Failed to decrypt the settings file";
|
||||
|
|
Loading…
Reference in New Issue
Block a user