Browse Source

refactor(core): use factory methods for ToxEncrypt

pull/4060/head
sudden6 9 years ago
parent
commit
5c5dce4d33
No known key found for this signature in database
GPG Key ID: 279509B499E032B9
  1. 158
      src/core/toxencrypt.cpp
  2. 10
      src/core/toxencrypt.h

158
src/core/toxencrypt.cpp

@ -20,6 +20,7 @@
#include "toxencrypt.h" #include "toxencrypt.h"
#include <tox/toxencryptsave.h> #include <tox/toxencryptsave.h>
#include <memory>
#include <QByteArray> #include <QByteArray>
#include <QDebug> #include <QDebug>
#include <QString> #include <QString>
@ -33,9 +34,9 @@ static QString getSaltError(TOX_ERR_GET_SALT error);
/** /**
* @class ToxEncrypt * @class ToxEncrypt
* @brief Encapsulates the toxencrypsave API. * @brief Encapsulates the toxencrypsave API.
* Since key derivation is work intensive, use a ToxEncrypt object and * Since key derivation is work intensive and to avoid storing plaintext
* encrypt() or decrypt() when you have to encrypt or decrypt more than once * passwords in memory, use a ToxEncrypt object and encrypt() or decrypt()
* with the same password. * when you have to encrypt or decrypt more than once with the same password.
*/ */
/** /**
@ -47,62 +48,12 @@ ToxEncrypt::~ToxEncrypt()
} }
/** /**
* @brief Creates a new ToxEncrypt object, with a random salt. * @brief Constructs a ToxEncrypt object from a Tox_Pass_Key.
* @param password Password to use for encryption. * @param key Derived key to use for encryption and decryption.
*/ */
ToxEncrypt::ToxEncrypt(const QString& password) ToxEncrypt::ToxEncrypt(Tox_Pass_Key* key) :
{ passKey{key}
passKey = tox_pass_key_new(); {}
QByteArray pass = password.toUtf8();
TOX_ERR_KEY_DERIVATION error;
tox_pass_key_derive(passKey, reinterpret_cast<const uint8_t*>(pass.constData()),
static_cast<size_t>(pass.length()), &error);
if(error != TOX_ERR_KEY_DERIVATION_OK)
{
qWarning() << getKeyDerivationError(error);
tox_pass_key_free(passKey);
passKey = nullptr;
}
}
/**
* @brief Creates a new ToxEncrypt object, with the salt read from the toxSave data.
* @param password The Password for the encrypted data.
* @param toxSave The data to read the salt from.
*/
ToxEncrypt::ToxEncrypt(const QString& password, const QByteArray& toxSave)
{
if(!isEncrypted(toxSave))
{
qWarning() << "The data was not encrypted using this module or it's corrupted.";
return;
}
TOX_ERR_GET_SALT saltError;
uint8_t salt[TOX_PASS_SALT_LENGTH];
tox_get_salt(reinterpret_cast<const uint8_t*>(toxSave.constData()), salt, &saltError);
if(saltError != TOX_ERR_GET_SALT_OK)
{
qWarning() << getSaltError(saltError);
return;
}
passKey = tox_pass_key_new();
QByteArray pass = password.toUtf8();
TOX_ERR_KEY_DERIVATION keyError;
tox_pass_key_derive_with_salt(passKey, reinterpret_cast<const uint8_t*>(pass.constData()),
static_cast<size_t>(pass.length()), salt, &keyError);
if(keyError != TOX_ERR_KEY_DERIVATION_OK)
{
qWarning() << getKeyDerivationError(keyError);
tox_pass_key_free(passKey);
passKey = nullptr;
}
}
/** /**
* @brief Checks if the data was encrypted by this module. * @brief Checks if the data was encrypted by this module.
@ -111,7 +62,7 @@ ToxEncrypt::ToxEncrypt(const QString& password, const QByteArray& toxSave)
*/ */
bool ToxEncrypt::isEncrypted(const QByteArray& ciphertext) bool ToxEncrypt::isEncrypted(const QByteArray& ciphertext)
{ {
if(ciphertext.length() < TOX_PASS_ENCRYPTION_EXTRA_LENGTH) if (ciphertext.length() < TOX_PASS_ENCRYPTION_EXTRA_LENGTH)
{ {
return false; return false;
} }
@ -128,7 +79,7 @@ bool ToxEncrypt::isEncrypted(const QByteArray& ciphertext)
*/ */
QByteArray ToxEncrypt::encryptPass(const QString& password, const QByteArray& plaintext) QByteArray ToxEncrypt::encryptPass(const QString& password, const QByteArray& plaintext)
{ {
if(password.length() == 0) if (password.length() == 0)
{ {
qWarning() << "Empty password supplied, probably not what you intended."; qWarning() << "Empty password supplied, probably not what you intended.";
} }
@ -142,9 +93,9 @@ QByteArray ToxEncrypt::encryptPass(const QString& password, const QByteArray& pl
static_cast<size_t>(pass.size()), static_cast<size_t>(pass.size()),
reinterpret_cast<uint8_t*>(ciphertext.data()), &error); reinterpret_cast<uint8_t*>(ciphertext.data()), &error);
if(error != TOX_ERR_ENCRYPTION_OK) if (error != TOX_ERR_ENCRYPTION_OK)
{ {
qWarning() << getEncryptionError(error); qCritical() << getEncryptionError(error);
return QByteArray{}; return QByteArray{};
} }
@ -160,13 +111,13 @@ QByteArray ToxEncrypt::encryptPass(const QString& password, const QByteArray& pl
*/ */
QByteArray ToxEncrypt::decryptPass(const QString& password, const QByteArray& ciphertext) QByteArray ToxEncrypt::decryptPass(const QString& password, const QByteArray& ciphertext)
{ {
if(!isEncrypted(ciphertext)) if (!isEncrypted(ciphertext))
{ {
qWarning() << "The data was not encrypted using this module or it's corrupted."; qWarning() << "The data was not encrypted using this module or it's corrupted.";
return QByteArray{}; return QByteArray{};
} }
if(password.length() == 0) if (password.length() == 0)
{ {
qDebug() << "Empty password supplied, probably not what you intended."; qDebug() << "Empty password supplied, probably not what you intended.";
} }
@ -180,7 +131,7 @@ QByteArray ToxEncrypt::decryptPass(const QString& password, const QByteArray& ci
static_cast<size_t>(pass.size()), static_cast<size_t>(pass.size()),
reinterpret_cast<uint8_t*>(plaintext.data()), &error); reinterpret_cast<uint8_t*>(plaintext.data()), &error);
if(error != TOX_ERR_DECRYPTION_OK) if (error != TOX_ERR_DECRYPTION_OK)
{ {
qWarning() << getDecryptionError(error); qWarning() << getDecryptionError(error);
return QByteArray{}; return QByteArray{};
@ -190,12 +141,68 @@ QByteArray ToxEncrypt::decryptPass(const QString& password, const QByteArray& ci
} }
/** /**
* @brief Checks if the object can be used for encryption and decryption. * @brief Factory method for the ToxEncrypt object.
* @return True if encryption and decryption is possible, false otherwise. * @param password Password to use for encryption.
* @return A std::unique_ptr containing a ToxEncrypt object on success, or an
* or an empty std::unique_ptr on failure.
*/ */
bool ToxEncrypt::isValid() const std::unique_ptr<ToxEncrypt> ToxEncrypt::makeToxEncrypt(const QString& password)
{ {
return passKey != nullptr; Tox_Pass_Key* passKey = tox_pass_key_new();
QByteArray pass = password.toUtf8();
TOX_ERR_KEY_DERIVATION error;
tox_pass_key_derive(passKey, reinterpret_cast<const uint8_t*>(pass.constData()),
static_cast<size_t>(pass.length()), &error);
if (error != TOX_ERR_KEY_DERIVATION_OK)
{
tox_pass_key_free(passKey);
qCritical() << getKeyDerivationError(error);
return std::unique_ptr<ToxEncrypt>{};
}
return std::unique_ptr<ToxEncrypt>(new ToxEncrypt(passKey));
}
/**
* @brief Factory method for the ToxEncrypt object.
* @param password Password to use for encryption.
* @param toxSave The data to read the salt for decryption from.
* @return A std::unique_ptr containing a ToxEncrypt object on success, or an
* or an empty std::unique_ptr on failure.
*/
std::unique_ptr<ToxEncrypt> ToxEncrypt::makeToxEncrypt(const QString& password, const QByteArray& toxSave)
{
if (!isEncrypted(toxSave))
{
qWarning() << "The data was not encrypted using this module or it's corrupted.";
return std::unique_ptr<ToxEncrypt>{};
}
TOX_ERR_GET_SALT saltError;
uint8_t salt[TOX_PASS_SALT_LENGTH];
tox_get_salt(reinterpret_cast<const uint8_t*>(toxSave.constData()), salt, &saltError);
if (saltError != TOX_ERR_GET_SALT_OK)
{
qWarning() << getSaltError(saltError);
return std::unique_ptr<ToxEncrypt>{};
}
Tox_Pass_Key* passKey = tox_pass_key_new();
QByteArray pass = password.toUtf8();
TOX_ERR_KEY_DERIVATION keyError;
tox_pass_key_derive_with_salt(passKey, reinterpret_cast<const uint8_t*>(pass.constData()),
static_cast<size_t>(pass.length()), salt, &keyError);
if (keyError != TOX_ERR_KEY_DERIVATION_OK)
{
tox_pass_key_free(passKey);
qWarning() << getKeyDerivationError(keyError);
return std::unique_ptr<ToxEncrypt>{};
}
return std::unique_ptr<ToxEncrypt>(new ToxEncrypt(passKey));
} }
/** /**
@ -205,9 +212,9 @@ bool ToxEncrypt::isValid() const
*/ */
QByteArray ToxEncrypt::encrypt(const QByteArray& plaintext) const QByteArray ToxEncrypt::encrypt(const QByteArray& plaintext) const
{ {
if(!passKey) if (!passKey)
{ {
qWarning() << "The passKey is invalid."; qCritical() << "The passKey is invalid.";
return QByteArray{}; return QByteArray{};
} }
@ -218,9 +225,9 @@ QByteArray ToxEncrypt::encrypt(const QByteArray& plaintext) const
static_cast<size_t>(plaintext.size()), static_cast<size_t>(plaintext.size()),
reinterpret_cast<uint8_t*>(ciphertext.data()), &error); reinterpret_cast<uint8_t*>(ciphertext.data()), &error);
if(error != TOX_ERR_ENCRYPTION_OK) if (error != TOX_ERR_ENCRYPTION_OK)
{ {
qWarning() << getEncryptionError(error); qCritical() << getEncryptionError(error);
return QByteArray{}; return QByteArray{};
} }
@ -235,7 +242,7 @@ QByteArray ToxEncrypt::encrypt(const QByteArray& plaintext) const
*/ */
QByteArray ToxEncrypt::decrypt(const QByteArray& ciphertext) const QByteArray ToxEncrypt::decrypt(const QByteArray& ciphertext) const
{ {
if(!isEncrypted(ciphertext)) if (!isEncrypted(ciphertext))
{ {
qWarning() << "The data was not encrypted using this module or it's corrupted."; qWarning() << "The data was not encrypted using this module or it's corrupted.";
return QByteArray{}; return QByteArray{};
@ -248,7 +255,7 @@ QByteArray ToxEncrypt::decrypt(const QByteArray& ciphertext) const
static_cast<size_t>(ciphertext.size()), static_cast<size_t>(ciphertext.size()),
reinterpret_cast<uint8_t*>(plaintext.data()), &error); reinterpret_cast<uint8_t*>(plaintext.data()), &error);
if(error != TOX_ERR_DECRYPTION_OK) if (error != TOX_ERR_DECRYPTION_OK)
{ {
qWarning() << getDecryptionError(error); qWarning() << getDecryptionError(error);
return QByteArray{}; return QByteArray{};
@ -256,6 +263,7 @@ QByteArray ToxEncrypt::decrypt(const QByteArray& ciphertext) const
return ciphertext; return ciphertext;
} }
/** /**
* @brief Gets the error string for TOX_ERR_KEY_DERIVATION errors. * @brief Gets the error string for TOX_ERR_KEY_DERIVATION errors.
* @param error The error number. * @param error The error number.

10
src/core/toxencrypt.h

@ -23,6 +23,8 @@
#ifndef TOXENCRYPT_H #ifndef TOXENCRYPT_H
#define TOXENCRYPT_H #define TOXENCRYPT_H
#include <memory>
struct Tox_Pass_Key; struct Tox_Pass_Key;
class ToxEncrypt class ToxEncrypt
@ -33,15 +35,17 @@ public:
ToxEncrypt(const ToxEncrypt& other) = delete; ToxEncrypt(const ToxEncrypt& other) = delete;
ToxEncrypt& operator=(const ToxEncrypt& other) = delete; ToxEncrypt& operator=(const ToxEncrypt& other) = delete;
ToxEncrypt(const QString& password);
ToxEncrypt(const QString& password, const QByteArray& toxSave);
static bool isEncrypted(const QByteArray& ciphertext); static bool isEncrypted(const QByteArray& ciphertext);
static QByteArray encryptPass(const QString& password, const QByteArray& plaintext); static QByteArray encryptPass(const QString& password, const QByteArray& plaintext);
static QByteArray decryptPass(const QString& password, const QByteArray& ciphertext); static QByteArray decryptPass(const QString& password, const QByteArray& ciphertext);
bool isValid() const; static std::unique_ptr<ToxEncrypt> makeToxEncrypt(const QString& password);
static std::unique_ptr<ToxEncrypt> makeToxEncrypt(const QString& password, const QByteArray& toxSave);
QByteArray encrypt(const QByteArray& plaintext) const; QByteArray encrypt(const QByteArray& plaintext) const;
QByteArray decrypt(const QByteArray& ciphertext) const; QByteArray decrypt(const QByteArray& ciphertext) const;
private:
ToxEncrypt(Tox_Pass_Key* key);
private: private:
Tox_Pass_Key* passKey = nullptr; Tox_Pass_Key* passKey = nullptr;
}; };

Loading…
Cancel
Save