mirror of
https://github.com/qTox/qTox.git
synced 2024-03-22 14:00:36 +08:00
fix(db): Add half-upgraded cipher params
Our previous SQLCiper upgrade code attempted to set SQLCipher 4.0 default params. If SQLCipher 3.x was used at that time, it would result in only half upgrading the params, since SQLCipher 3.x doesn't support PRAGMA cipher_hmac_algorithm or PRAGMA cipher_kdf_algorithm. This means that our databases could be saved with any of three sets of SQLCipher params.
This commit is contained in:
parent
40989e54d8
commit
deb7fbb67c
|
@ -192,7 +192,7 @@ bool RawDatabase::openEncryptedDatabaseAtLatestVersion(const QString& hexKey)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (setCipherParameters(4)) {
|
||||
if (setCipherParameters(SqlCipherParams::p4_0)) {
|
||||
if (testUsable()) {
|
||||
qInfo() << "Opened database with SQLCipher 4.x parameters";
|
||||
return true;
|
||||
|
@ -201,7 +201,7 @@ bool RawDatabase::openEncryptedDatabaseAtLatestVersion(const QString& hexKey)
|
|||
}
|
||||
} else {
|
||||
// setKey again to clear old bad cipher settings
|
||||
if (setKey(hexKey) && setCipherParameters(3) && testUsable()) {
|
||||
if (setKey(hexKey) && setCipherParameters(SqlCipherParams::p3_0) && testUsable()) {
|
||||
qInfo() << "Opened database with SQLCipher 3.x parameters";
|
||||
return true;
|
||||
} else {
|
||||
|
@ -223,7 +223,7 @@ bool RawDatabase::testUsable()
|
|||
bool RawDatabase::updateSavedCipherParameters(const QString& hexKey)
|
||||
{
|
||||
setKey(hexKey); // setKey again because a SELECT has already been run, causing crypto settings to take effect
|
||||
if (!setCipherParameters(3)) {
|
||||
if (!setCipherParameters(SqlCipherParams::p3_0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -234,7 +234,7 @@ bool RawDatabase::updateSavedCipherParameters(const QString& hexKey)
|
|||
if (!execNow("ATTACH DATABASE '" + path + ".tmp' AS sqlcipher4 KEY \"x'" + hexKey + "'\";")) {
|
||||
return false;
|
||||
}
|
||||
if (!setCipherParameters(4, "sqlcipher4")) {
|
||||
if (!setCipherParameters(SqlCipherParams::p4_0, "sqlcipher4")) {
|
||||
return false;
|
||||
}
|
||||
if (!execNow("SELECT sqlcipher_export('sqlcipher4');")) {
|
||||
|
@ -253,36 +253,44 @@ bool RawDatabase::updateSavedCipherParameters(const QString& hexKey)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool RawDatabase::setCipherParameters(int majorVersion, const QString& database)
|
||||
bool RawDatabase::setCipherParameters(SqlCipherParams params, const QString& database)
|
||||
{
|
||||
QString prefix;
|
||||
if (!database.isNull()) {
|
||||
prefix = database + ".";
|
||||
}
|
||||
// from https://www.zetetic.net/blog/2018/11/30/sqlcipher-400-release/
|
||||
const QString default3_xParams{"PRAGMA database.cipher_page_size = 1024; PRAGMA database.kdf_iter = 64000;"
|
||||
const QString default3_xParams{"PRAGMA database.cipher_page_size = 1024;"
|
||||
"PRAGMA database.kdf_iter = 64000;"
|
||||
"PRAGMA database.cipher_hmac_algorithm = HMAC_SHA1;"
|
||||
"PRAGMA database.cipher_kdf_algorithm = PBKDF2_HMAC_SHA1;"};
|
||||
const QString default4_xParams{"PRAGMA database.cipher_page_size = 4096; PRAGMA database.kdf_iter = 256000;"
|
||||
// cipher_hmac_algorithm and cipher_kdf_algorithm weren't supported in sqlcipher 3.x, so our upgrade to 4 only
|
||||
// applied some of the new params if sqlcipher 3.x was used at the time
|
||||
const QString halfUpgradedTo4Params{"PRAGMA database.cipher_page_size = 4096;"
|
||||
"PRAGMA database.kdf_iter = 256000;"
|
||||
"PRAGMA database.cipher_hmac_algorithm = HMAC_SHA1;"
|
||||
"PRAGMA database.cipher_kdf_algorithm = PBKDF2_HMAC_SHA1;"};
|
||||
const QString default4_xParams{"PRAGMA database.cipher_page_size = 4096;"
|
||||
"PRAGMA database.kdf_iter = 256000;"
|
||||
"PRAGMA database.cipher_hmac_algorithm = HMAC_SHA512;"
|
||||
"PRAGMA database.cipher_kdf_algorithm = PBKDF2_HMAC_SHA512;"};
|
||||
|
||||
QString defaultParams;
|
||||
switch(majorVersion) {
|
||||
case 3: {
|
||||
switch(params) {
|
||||
case SqlCipherParams::p3_0: {
|
||||
defaultParams = default3_xParams;
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
case SqlCipherParams::halfUpgradedTo4: {
|
||||
defaultParams = halfUpgradedTo4Params;
|
||||
break;
|
||||
}
|
||||
case SqlCipherParams::p4_0: {
|
||||
defaultParams = default4_xParams;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
qCritical() << __FUNCTION__ << "called with unsupported SQLCipher major version" << majorVersion;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
qDebug().nospace() << "Setting SQLCipher " << majorVersion << ".x parameters";
|
||||
qDebug() << "Setting SQLCipher" << static_cast<int>(params) << "parameters";
|
||||
return execNow(defaultParams.replace("database.", prefix));
|
||||
}
|
||||
|
||||
|
@ -494,7 +502,7 @@ bool RawDatabase::encryptDatabase(const QString& newHexKey)
|
|||
qWarning() << "Failed to export encrypted database";
|
||||
return false;
|
||||
}
|
||||
if (!setCipherParameters(4, "encrypted")) {
|
||||
if (!setCipherParameters(SqlCipherParams::p4_0, "encrypted")) {
|
||||
return false;
|
||||
}
|
||||
if (!execNow("SELECT sqlcipher_export('encrypted');")) {
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
#ifndef RAWDATABASE_H
|
||||
#define RAWDATABASE_H
|
||||
|
||||
#include "src/util/strongtype.h"
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QMutex>
|
||||
#include <QPair>
|
||||
|
@ -29,10 +31,11 @@
|
|||
#include <QVariant>
|
||||
#include <QVector>
|
||||
#include <QRegularExpression>
|
||||
|
||||
#include <atomic>
|
||||
#include <cassert>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include "src/util/strongtype.h"
|
||||
|
||||
/// The two following defines are required to use SQLCipher
|
||||
/// They are used by the sqlite3.h header
|
||||
|
@ -82,6 +85,16 @@ public:
|
|||
};
|
||||
|
||||
public:
|
||||
enum class SqlCipherParams {
|
||||
// keep these sorted in upgrade order
|
||||
p3_0, // SQLCipher 3.0 default encryption params
|
||||
// SQLCipher 4.0 default params where SQLCipher 3.0 supports them, but 3.0 params where not possible.
|
||||
// We accidentally got to this state when attemption to update all databases to 4.0 defaults even when using
|
||||
// SQLCipher 3.x, but might as well keep using these for people with SQLCipher 3.x.
|
||||
halfUpgradedTo4,
|
||||
p4_0 // SQLCipher 4.0 default encryption params
|
||||
};
|
||||
|
||||
RawDatabase(const QString& path, const QString& password, const QByteArray& salt);
|
||||
~RawDatabase();
|
||||
bool isOpen();
|
||||
|
@ -96,6 +109,21 @@ public:
|
|||
|
||||
void sync();
|
||||
|
||||
static QString toString(SqlCipherParams params)
|
||||
{
|
||||
switch (params)
|
||||
{
|
||||
case SqlCipherParams::p3_0:
|
||||
return "3.0 default";
|
||||
case SqlCipherParams::halfUpgradedTo4:
|
||||
return "3.x max compatible";
|
||||
case SqlCipherParams::p4_0:
|
||||
return "4.0 default";
|
||||
}
|
||||
assert(false);
|
||||
return {};
|
||||
}
|
||||
|
||||
public slots:
|
||||
bool setPassword(const QString& password);
|
||||
bool rename(const QString& newPath);
|
||||
|
@ -110,7 +138,7 @@ private:
|
|||
QString anonymizeQuery(const QByteArray& query);
|
||||
bool openEncryptedDatabaseAtLatestVersion(const QString& hexKey);
|
||||
bool updateSavedCipherParameters(const QString& hexKey);
|
||||
bool setCipherParameters(int majorVersion, const QString& database = {});
|
||||
bool setCipherParameters(SqlCipherParams params, const QString& database = {});
|
||||
bool setKey(const QString& hexKey);
|
||||
int getUserVersion();
|
||||
bool encryptDatabase(const QString& newHexKey);
|
||||
|
|
Loading…
Reference in New Issue
Block a user