Browse Source

Encrypt avatar for encryped profiles

Fixes #2583

Fixes #2546
pull/2628/head
tux3 10 years ago
parent
commit
2396109a7e
No known key found for this signature in database
GPG Key ID: 7E086DD661263264
  1. 42
      src/persistence/profile.cpp
  2. 4
      src/persistence/profile.h

42
src/persistence/profile.cpp

@ -33,6 +33,7 @@ @@ -33,6 +33,7 @@
#include <QThread>
#include <QObject>
#include <QDebug>
#include <sodium.h>
QVector<QString> Profile::profiles;
@ -325,9 +326,18 @@ void Profile::saveToxSave(QByteArray data) @@ -325,9 +326,18 @@ void Profile::saveToxSave(QByteArray data)
newProfile = false;
}
QString Profile::avatarPath(const QString &ownerId)
QString Profile::avatarPath(const QString &ownerId, bool forceUnencrypted)
{
return Settings::getInstance().getSettingsDirPath() + "avatars/" + ownerId + ".png";
if (password.isEmpty() || forceUnencrypted)
return Settings::getInstance().getSettingsDirPath() + "avatars/" + ownerId + ".png";
QByteArray idData = ownerId.toUtf8();
constexpr int hashSize = TOX_PUBLIC_KEY_SIZE; // As long as an unencrypted hash
static_assert(hashSize >= crypto_generichash_BYTES_MIN
&& hashSize <= crypto_generichash_BYTES_MAX, "Hash size not supported by libsodium");
QByteArray hash(hashSize, 0);
crypto_generichash((uint8_t*)hash.data(), hashSize, (uint8_t*)idData.data(), idData.size(), nullptr, 0);
return Settings::getInstance().getSettingsDirPath() + "avatars/" + hash.toHex().toUpper() + ".png";
}
QPixmap Profile::loadAvatar()
@ -344,16 +354,38 @@ QPixmap Profile::loadAvatar(const QString &ownerId) @@ -344,16 +354,38 @@ QPixmap Profile::loadAvatar(const QString &ownerId)
QByteArray Profile::loadAvatarData(const QString &ownerId)
{
QFile file(avatarPath(ownerId));
QString path = avatarPath(ownerId);
bool encrypted = !password.isEmpty();
// If the encrypted avatar isn't found, try loading the unencrypted one for the same ID
if (!password.isEmpty() && !QFile::exists(path))
{
encrypted = false;
path = avatarPath(ownerId, true);
}
QFile file(path);
if (!file.open(QIODevice::ReadOnly))
return {};
return file.readAll();
QByteArray pic = file.readAll();
if (encrypted)
{
uint8_t salt[TOX_PASS_SALT_LENGTH];
tox_get_salt(reinterpret_cast<uint8_t *>(pic.data()), salt);
auto passkey = core->createPasskey(password, salt);
pic = core->decryptData(pic, *passkey);
}
return pic;
}
void Profile::saveAvatar(QByteArray pic, const QString &ownerId)
{
if (!password.isEmpty())
pic = core->encryptData(pic, passkey);
QString path = avatarPath(ownerId);
QSaveFile file(avatarPath(ownerId));
QSaveFile file(path);
if (!file.open(QIODevice::WriteOnly))
{
qWarning() << "Tox avatar " << path << " couldn't be saved";

4
src/persistence/profile.h

@ -91,7 +91,9 @@ private: @@ -91,7 +91,9 @@ private:
/// Creates a .ini file for the given .tox profile
/// Only pass the basename, without extension
static void importProfile(QString name);
QString avatarPath(const QString& ownerId);
/// Gets the path of the avatar file cached by this profile and corresponding to this owner ID
/// If forceUnencrypted, we return the path to the plaintext file even if we're an encrypted profile
QString avatarPath(const QString& ownerId, bool forceUnencrypted = false);
private:
Core* core;

Loading…
Cancel
Save