diff --git a/CMakeLists.txt b/CMakeLists.txt index 34ac87f04..e6d4270ca 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -261,8 +261,8 @@ endif() set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS_NONE QT_NO_DEBUG) find_package(LibGPGError REQUIRED) - find_package(Gcrypt 1.7.0 REQUIRED) +find_package(Argon2 REQUIRED) find_package(ZLIB REQUIRED) diff --git a/INSTALL.md b/INSTALL.md index 0bfa86b2c..2690e6091 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -26,6 +26,7 @@ The following libraries are required: * libmicrohttpd * libxi, libxtst, qtx11extras (optional for auto-type on X11) * libsodium (>= 1.0.12, optional for keepassxc-browser support) +* libargon2 Prepare the Building Environment diff --git a/cmake/FindArgon2.cmake b/cmake/FindArgon2.cmake new file mode 100644 index 000000000..8378ebd54 --- /dev/null +++ b/cmake/FindArgon2.cmake @@ -0,0 +1,21 @@ +# Copyright (C) 2017 KeePassXC Team +# +# This program is free 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 2 or (at your option) +# version 3 of the License. +# +# This program 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 this program. If not, see . + +find_path(ARGON2_INCLUDE_DIR argon2.h) +find_library(ARGON2_LIBRARIES argon2) +mark_as_advanced(ARGON2_LIBRARIES ARGON2_INCLUDE_DIR) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(Argon2 DEFAULT_MSG ARGON2_LIBRARIES ARGON2_INCLUDE_DIR) \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c04d7110f..1e927ee38 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -78,6 +78,7 @@ set(keepassx_SOURCES crypto/kdf/Kdf.cpp crypto/kdf/Kdf_p.h crypto/kdf/AesKdf.cpp + crypto/kdf/Argon2Kdf.cpp format/CsvExporter.cpp format/KeePass1.h format/KeePass1Reader.cpp @@ -252,6 +253,7 @@ target_link_libraries(keepassx_core Qt5::Network Qt5::Concurrent Qt5::Widgets + ${ARGON2_LIBRARIES} ${GCRYPT_LIBRARIES} ${GPGERROR_LIBRARIES} ${ZLIB_LIBRARIES}) diff --git a/src/cli/CMakeLists.txt b/src/cli/CMakeLists.txt index 4c8620d55..225ce47dc 100644 --- a/src/cli/CMakeLists.txt +++ b/src/cli/CMakeLists.txt @@ -46,6 +46,7 @@ target_link_libraries(keepassxc-cli keepassx_core Qt5::Core ${GCRYPT_LIBRARIES} + ${ARGON2_LIBRARIES} ${GPGERROR_LIBRARIES} ${ZLIB_LIBRARIES} ${ZXCVBN_LIBRARIES}) diff --git a/src/core/Database.cpp b/src/core/Database.cpp index 2f2f2967d..ae1664118 100644 --- a/src/core/Database.cpp +++ b/src/core/Database.cpp @@ -45,7 +45,7 @@ Database::Database() m_data.cipher = KeePass2::CIPHER_AES; m_data.compressionAlgo = CompressionGZip; m_data.kdf = QSharedPointer::create(); - m_data.kdf->randomizeTransformSalt(); + m_data.kdf->randomizeSeed(); m_data.hasKey = false; setRootGroup(new Group()); @@ -258,7 +258,7 @@ void Database::setCompressionAlgo(Database::CompressionAlgorithm algo) bool Database::setKey(const CompositeKey& key, bool updateChangedTime, bool updateTransformSalt) { if (updateTransformSalt) { - m_data.kdf->randomizeTransformSalt(); + m_data.kdf->randomizeSeed(); } QByteArray transformedMasterKey; @@ -490,7 +490,7 @@ void Database::setKdf(QSharedPointer kdf) bool Database::changeKdf(QSharedPointer kdf) { - kdf->randomizeTransformSalt(); + kdf->randomizeSeed(); QByteArray transformedMasterKey; if (!m_data.key.transform(*kdf, transformedMasterKey)) { return false; diff --git a/src/crypto/kdf/AesKdf.cpp b/src/crypto/kdf/AesKdf.cpp index 7056698d7..3177506fc 100644 --- a/src/crypto/kdf/AesKdf.cpp +++ b/src/crypto/kdf/AesKdf.cpp @@ -15,12 +15,17 @@ * along with this program. If not, see . */ +#include "AesKdf.h" + #include #include "format/KeePass2.h" #include "crypto/CryptoHash.h" -#include "crypto/Random.h" -#include "AesKdf.h" + +AesKdf::AesKdf() + : Kdf::Kdf(KeePass2::KDF_AES) +{ +} bool AesKdf::transform(const QByteArray& raw, QByteArray& result) const { @@ -44,7 +49,7 @@ bool AesKdf::transform(const QByteArray& raw, QByteArray& result) const return true; } -bool AesKdf::transformKeyRaw(const QByteArray& key, const QByteArray& seed, quint64 rounds, QByteArray* result) +bool AesKdf::transformKeyRaw(const QByteArray& key, const QByteArray& seed, int rounds, QByteArray* result) { QByteArray iv(16, 0); SymmetricCipher cipher(SymmetricCipher::Aes256, SymmetricCipher::Ecb, @@ -65,44 +70,6 @@ bool AesKdf::transformKeyRaw(const QByteArray& key, const QByteArray& seed, quin return true; } -AesKdf::AesKdf() - : Kdf::Kdf(KeePass2::KDF_AES) - , m_rounds(100000ull) - , m_seed(QByteArray(32, 0)) -{ -} - -quint64 AesKdf::rounds() const -{ - return m_rounds; -} - -QByteArray AesKdf::seed() const -{ - return m_seed; -} - -bool AesKdf::setRounds(quint64 rounds) -{ - m_rounds = rounds; - return true; -} - -bool AesKdf::setSeed(const QByteArray& seed) -{ - if (seed.size() != 32) { - return false; - } - - m_seed = seed; - return true; -} - -void AesKdf::randomizeTransformSalt() -{ - setSeed(randomGen()->randomArray(32)); -} - QSharedPointer AesKdf::clone() const { return QSharedPointer::create(*this); @@ -117,17 +84,13 @@ int AesKdf::benchmarkImpl(int msec) const SymmetricCipher cipher(SymmetricCipher::Aes256, SymmetricCipher::Ecb, SymmetricCipher::Encrypt); cipher.init(seed, iv); - int rounds = 0; + quint64 rounds = 1000000; QElapsedTimer timer; timer.start(); - do { - if (!cipher.processInPlace(key, 10000)) { - rounds = -1; - break; - } - rounds += 10000; - } - while (!timer.hasExpired(msec)); - return rounds; + if (!cipher.processInPlace(key, rounds)) { + return -1; + } + + return static_cast(rounds * (static_cast(msec) / timer.elapsed())); } diff --git a/src/crypto/kdf/AesKdf.h b/src/crypto/kdf/AesKdf.h index 28206a8d6..3e2c8ada6 100644 --- a/src/crypto/kdf/AesKdf.h +++ b/src/crypto/kdf/AesKdf.h @@ -26,25 +26,15 @@ public: AesKdf(); bool transform(const QByteArray& raw, QByteArray& result) const override; - void randomizeTransformSalt() override; QSharedPointer clone() const override; - quint64 rounds() const override; - QByteArray seed() const override; - - bool setRounds(quint64 rounds) override; - bool setSeed(const QByteArray& seed) override; - protected: int benchmarkImpl(int msec) const override; private: - quint64 m_rounds; - QByteArray m_seed; - static bool transformKeyRaw(const QByteArray& key, const QByteArray& seed, - quint64 rounds, + int rounds, QByteArray* result) Q_REQUIRED_RESULT; }; diff --git a/src/crypto/kdf/Argon2Kdf.cpp b/src/crypto/kdf/Argon2Kdf.cpp new file mode 100644 index 000000000..fa410dc93 --- /dev/null +++ b/src/crypto/kdf/Argon2Kdf.cpp @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2017 KeePassXC Team + * + * This program is free 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 2 or (at your option) + * version 3 of the License. + * + * This program 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 this program. If not, see . + */ + +#include "Argon2Kdf.h" + +#include +#include + +#include "format/KeePass2.h" +#include "crypto/CryptoHash.h" + +/** + * KeePass' Argon2 implementation supports all parameters that are defined in the official specification, + * but only the number of iterations, the memory size and the degree of parallelism can be configured by + * the user in the database settings dialog. For the other parameters, KeePass chooses reasonable defaults: + * a 256-bit salt is generated each time the database is saved, the tag length is 256 bits, no secret key + * or associated data. KeePass uses the latest version of Argon2, v1.3. + */ +Argon2Kdf::Argon2Kdf() + : Kdf::Kdf(KeePass2::KDF_ARGON2) + , m_memory(1<<16) + , m_parallelism(2) +{ + m_rounds = 1; +} + +quint32 Argon2Kdf::memory() const +{ + // Convert to Megabytes + return m_memory / (1<<10); +} + +bool Argon2Kdf::setMemory(quint32 memoryMegabytes) +{ + // TODO: add bounds check + // Convert to Kibibytes + m_memory = (1<<10) * memoryMegabytes; + return true; +} + +quint32 Argon2Kdf::parallelism() const +{ + return m_parallelism; +} + +bool Argon2Kdf::setParallelism(quint32 threads) +{ + // TODO: add bounds check + m_parallelism = threads; + return true; +} + +bool Argon2Kdf::transform(const QByteArray& raw, QByteArray& result) const +{ + result.clear(); + result.resize(32); + + if (!transformKeyRaw(raw, seed(), rounds(), memory(), parallelism(), result)) { + return false; + } + + result = CryptoHash::hash(result, CryptoHash::Sha256); + return true; +} + +bool Argon2Kdf::transformKeyRaw(const QByteArray& key, const QByteArray& seed, int rounds, + quint32 memory, quint32 parallelism, QByteArray& result) +{ + // Time Cost, Mem Cost, Threads/Lanes, Password, length, Salt, length, out, length + int rc = argon2d_hash_raw(rounds, memory, parallelism, key.data(), key.size(), + seed.data(), seed.size(), result.data(), result.size()); + if (rc != ARGON2_OK) { + qWarning("Argon2 error: %s", argon2_error_message(rc)); + return false; + } + + return true; +} + +QSharedPointer Argon2Kdf::clone() const +{ + return QSharedPointer::create(*this); +} + +int Argon2Kdf::benchmarkImpl(int msec) const +{ + QByteArray key = QByteArray(16, '\x7E'); + QByteArray seed = QByteArray(32, '\x4B'); + + QElapsedTimer timer; + timer.start(); + + int rounds = 4; + + int rc = argon2d_hash_raw(rounds, m_memory, m_parallelism, key.data(), key.size(), seed.data(), seed.size(), key.data(), key.size()); + if (rc != ARGON2_OK) { + qWarning("Argon2 error: %s", argon2_error_message(rc)); + return -1; + } + + return static_cast(rounds * (static_cast(msec) / timer.elapsed())); +} \ No newline at end of file diff --git a/src/crypto/kdf/Argon2Kdf.h b/src/crypto/kdf/Argon2Kdf.h new file mode 100644 index 000000000..c01698120 --- /dev/null +++ b/src/crypto/kdf/Argon2Kdf.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2017 KeePassXC Team + * + * This program is free 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 2 or (at your option) + * version 3 of the License. + * + * This program 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 this program. If not, see . + */ + +#ifndef KEEPASSX_ARGON2KDF_H +#define KEEPASSX_ARGON2KDF_H + +#include "Kdf.h" + +class Argon2Kdf : public Kdf { +public: + Argon2Kdf(); + + bool transform(const QByteArray& raw, QByteArray& result) const override; + QSharedPointer clone() const override; + + quint32 memory() const; + bool setMemory(quint32 memory_kb); + quint32 parallelism() const; + bool setParallelism(quint32 threads); + +protected: + int benchmarkImpl(int msec) const override; + + quint32 m_memory; + quint32 m_parallelism; + +private: + static bool transformKeyRaw(const QByteArray& key, + const QByteArray& seed, + int rounds, + quint32 memory, + quint32 parallelism, + QByteArray& result) Q_REQUIRED_RESULT; +}; + +#endif // KEEPASSX_ARGON2KDF_H diff --git a/src/crypto/kdf/Kdf.cpp b/src/crypto/kdf/Kdf.cpp index cfc3025c1..5134adc5f 100644 --- a/src/crypto/kdf/Kdf.cpp +++ b/src/crypto/kdf/Kdf.cpp @@ -20,8 +20,12 @@ #include +#include "crypto/Random.h" + Kdf::Kdf(Uuid uuid) - : m_uuid(uuid) + : m_rounds(KDF_DEFAULT_ROUNDS) + , m_seed(QByteArray(KDF_DEFAULT_SEED_SIZE, 0)) + , m_uuid(uuid) { } @@ -30,6 +34,37 @@ Uuid Kdf::uuid() const return m_uuid; } +int Kdf::rounds() const +{ + return m_rounds; +} + +QByteArray Kdf::seed() const +{ + return m_seed; +} + +bool Kdf::setRounds(int rounds) +{ + m_rounds = rounds; + return true; +} + +bool Kdf::setSeed(const QByteArray& seed) +{ + if (seed.size() != m_seed.size()) { + return false; + } + + m_seed = seed; + return true; +} + +void Kdf::randomizeSeed() +{ + setSeed(randomGen()->randomArray(m_seed.size())); +} + int Kdf::benchmark(int msec) const { BenchmarkThread thread1(msec, this); @@ -41,7 +76,7 @@ int Kdf::benchmark(int msec) const thread1.wait(); thread2.wait(); - return qMin(thread1.rounds(), thread2.rounds()); + return qMax(1, qMin(thread1.rounds(), thread2.rounds())); } Kdf::BenchmarkThread::BenchmarkThread(int msec, const Kdf* kdf) diff --git a/src/crypto/kdf/Kdf.h b/src/crypto/kdf/Kdf.h index 5330e71d0..cb0bcc364 100644 --- a/src/crypto/kdf/Kdf.h +++ b/src/crypto/kdf/Kdf.h @@ -22,6 +22,9 @@ #include "core/Uuid.h" +#define KDF_DEFAULT_SEED_SIZE 32 +#define KDF_DEFAULT_ROUNDS 100000ull + class Kdf { public: @@ -30,12 +33,13 @@ public: Uuid uuid() const; - virtual quint64 rounds() const = 0; - virtual bool setRounds(quint64 rounds) = 0; - virtual QByteArray seed() const = 0; - virtual bool setSeed(const QByteArray& seed) = 0; + int rounds() const; + virtual bool setRounds(int rounds); + QByteArray seed() const; + virtual bool setSeed(const QByteArray& seed); + virtual void randomizeSeed(); + virtual bool transform(const QByteArray& raw, QByteArray& result) const = 0; - virtual void randomizeTransformSalt() = 0; virtual QSharedPointer clone() const = 0; int benchmark(int msec) const; @@ -43,6 +47,9 @@ public: protected: virtual int benchmarkImpl(int msec) const = 0; + int m_rounds; + QByteArray m_seed; + private: class BenchmarkThread; const Uuid m_uuid; diff --git a/src/format/KeePass2.cpp b/src/format/KeePass2.cpp index 61bd383df..fd57148d0 100644 --- a/src/format/KeePass2.cpp +++ b/src/format/KeePass2.cpp @@ -16,15 +16,16 @@ */ #include "KeePass2.h" -#include "crypto/kdf/AesKdf.h" #include - +#include "crypto/kdf/AesKdf.h" +#include "crypto/kdf/Argon2Kdf.h" const Uuid KeePass2::CIPHER_AES = Uuid(QByteArray::fromHex("31c1f2e6bf714350be5805216afc5aff")); const Uuid KeePass2::CIPHER_TWOFISH = Uuid(QByteArray::fromHex("ad68f29f576f4bb9a36ad47af965346c")); const Uuid KeePass2::CIPHER_CHACHA20 = Uuid(QByteArray::fromHex("D6038A2B8B6F4CB5A524339A31DBB59A")); const Uuid KeePass2::KDF_AES = Uuid(QByteArray::fromHex("C9D9F39A628A4460BF740D08C18A4FEA")); +const Uuid KeePass2::KDF_ARGON2 = Uuid(QByteArray::fromHex("EF636DDF8C29444B91F7A9A403E30A0C")); const QByteArray KeePass2::INNER_STREAM_SALSA20_IV("\xE8\x30\x09\x4B\x97\x20\x5D\x2A"); @@ -35,12 +36,15 @@ const QList> KeePass2::CIPHERS { }; const QList> KeePass2::KDFS { qMakePair(KeePass2::KDF_AES, QObject::tr("AES-KDF")), + qMakePair(KeePass2::KDF_ARGON2, QObject::tr("Argon2")), }; QSharedPointer KeePass2::uuidToKdf(const Uuid& uuid) { if (uuid == KDF_AES) { return QSharedPointer::create(); + } else if (uuid == KDF_ARGON2) { + return QSharedPointer::create(); } Q_ASSERT_X(false, "uuidToKdf", "Invalid UUID"); diff --git a/src/format/KeePass2.h b/src/format/KeePass2.h index c7945e907..99bc5a0b0 100644 --- a/src/format/KeePass2.h +++ b/src/format/KeePass2.h @@ -40,6 +40,7 @@ namespace KeePass2 extern const Uuid CIPHER_CHACHA20; extern const Uuid KDF_AES; + extern const Uuid KDF_ARGON2; extern const QByteArray INNER_STREAM_SALSA20_IV; diff --git a/src/gui/DatabaseSettingsWidget.cpp b/src/gui/DatabaseSettingsWidget.cpp index 51c0f4183..2f4fe177d 100644 --- a/src/gui/DatabaseSettingsWidget.cpp +++ b/src/gui/DatabaseSettingsWidget.cpp @@ -26,6 +26,7 @@ #include "core/Group.h" #include "core/Metadata.h" #include "crypto/SymmetricCipher.h" +#include "crypto/kdf/Argon2Kdf.h" #include "MessageBox.h" DatabaseSettingsWidget::DatabaseSettingsWidget(QWidget* parent) @@ -42,6 +43,7 @@ DatabaseSettingsWidget::DatabaseSettingsWidget(QWidget* parent) connect(m_ui->historyMaxSizeCheckBox, SIGNAL(toggled(bool)), m_ui->historyMaxSizeSpinBox, SLOT(setEnabled(bool))); connect(m_ui->transformBenchmarkButton, SIGNAL(clicked()), SLOT(transformRoundsBenchmark())); + connect(m_ui->kdfComboBox, SIGNAL(currentIndexChanged(int)), SLOT(kdfChanged(int))); } DatabaseSettingsWidget::~DatabaseSettingsWidget() @@ -83,19 +85,29 @@ void DatabaseSettingsWidget::load(Database* db) m_ui->algorithmComboBox->setCurrentIndex(cipherIndex); } - bool blockSignals = m_ui->kdfComboBox->signalsBlocked(); + // Setup kdf combo box m_ui->kdfComboBox->blockSignals(true); - m_ui->kdfComboBox->clear(); for (auto& kdf: asConst(KeePass2::KDFS)) { m_ui->kdfComboBox->addItem(kdf.second, kdf.first.toByteArray()); } - int kdfIndex = m_ui->kdfComboBox->findData(m_db->kdf()->uuid().toByteArray()); + m_ui->kdfComboBox->blockSignals(false); + + auto kdfUuid = m_db->kdf()->uuid(); + int kdfIndex = m_ui->kdfComboBox->findData(kdfUuid.toByteArray()); if (kdfIndex > -1) { m_ui->kdfComboBox->setCurrentIndex(kdfIndex); + kdfChanged(kdfIndex); + } + + // Setup kdf parameters + auto kdf = m_db->kdf(); + m_ui->transformRoundsSpinBox->setValue(kdf->rounds()); + if (kdfUuid == KeePass2::KDF_ARGON2) { + auto argon2Kdf = kdf.staticCast(); + m_ui->memorySpinBox->setValue(argon2Kdf->memory()); + m_ui->parallelismSpinBox->setValue(argon2Kdf->parallelism()); } - m_ui->kdfComboBox->blockSignals(blockSignals); - m_ui->transformRoundsSpinBox->setValue(static_cast(m_db->kdf()->rounds())); m_ui->dbNameEdit->setFocus(); } @@ -139,8 +151,14 @@ void DatabaseSettingsWidget::save() m_db->setCipher(Uuid(m_ui->algorithmComboBox->currentData().toByteArray())); + // Save kdf parameters auto kdf = KeePass2::uuidToKdf(Uuid(m_ui->kdfComboBox->currentData().toByteArray())); - kdf->setRounds(static_cast(qMax(0, m_ui->transformRoundsSpinBox->value()))); + kdf->setRounds(m_ui->transformRoundsSpinBox->value()); + if (kdf->uuid() == KeePass2::KDF_ARGON2) { + auto argon2Kdf = kdf.staticCast(); + argon2Kdf->setMemory(m_ui->memorySpinBox->value()); + argon2Kdf->setParallelism(m_ui->parallelismSpinBox->value()); + } QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); // TODO: we should probably use AsyncTask::runAndWaitForFuture() here, @@ -164,11 +182,26 @@ void DatabaseSettingsWidget::reject() void DatabaseSettingsWidget::transformRoundsBenchmark() { QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); - m_ui->transformRoundsSpinBox->setValue(AsyncTask::runAndWaitForFuture([this]() { - int rounds = m_db->kdf()->benchmark(1000); - QApplication::restoreOverrideCursor(); - return rounds; - })); + m_ui->transformBenchmarkButton->setEnabled(false); + + // Create a new kdf with the current parameters + auto kdf = KeePass2::uuidToKdf(Uuid(m_ui->kdfComboBox->currentData().toByteArray())); + kdf->setRounds(m_ui->transformRoundsSpinBox->value()); + if (kdf->uuid() == KeePass2::KDF_ARGON2) { + auto argon2Kdf = kdf.staticCast(); + argon2Kdf->setMemory(m_ui->memorySpinBox->value()); + argon2Kdf->setParallelism(m_ui->parallelismSpinBox->value()); + } + + // Determine the number of rounds required to meet 1 second delay + int rounds = AsyncTask::runAndWaitForFuture([this, kdf]() { + return kdf->benchmark(1000); + }); + + m_ui->transformRoundsSpinBox->setValue(rounds); + + QApplication::restoreOverrideCursor(); + m_ui->transformBenchmarkButton->setEnabled(true); } void DatabaseSettingsWidget::truncateHistories() @@ -178,3 +211,15 @@ void DatabaseSettingsWidget::truncateHistories() entry->truncateHistory(); } } + +void DatabaseSettingsWidget::kdfChanged(int index) +{ + Uuid id(m_ui->kdfComboBox->itemData(index).toByteArray()); + if (id == KeePass2::KDF_ARGON2) { + m_ui->memorySpinBox->setEnabled(true); + m_ui->parallelismSpinBox->setEnabled(true); + } else { + m_ui->memorySpinBox->setEnabled(false); + m_ui->parallelismSpinBox->setEnabled(false); + } +} diff --git a/src/gui/DatabaseSettingsWidget.h b/src/gui/DatabaseSettingsWidget.h index ec3d6415a..83a5eb098 100644 --- a/src/gui/DatabaseSettingsWidget.h +++ b/src/gui/DatabaseSettingsWidget.h @@ -51,6 +51,7 @@ private slots: void save(); void reject(); void transformRoundsBenchmark(); + void kdfChanged(int index); private: void truncateHistories(); diff --git a/src/gui/DatabaseSettingsWidget.ui b/src/gui/DatabaseSettingsWidget.ui index 8aaab19e7..5a6778678 100644 --- a/src/gui/DatabaseSettingsWidget.ui +++ b/src/gui/DatabaseSettingsWidget.ui @@ -2,6 +2,14 @@ DatabaseSettingsWidget + + + 0 + 0 + 1082 + 506 + + @@ -35,39 +43,36 @@ - 800 + 400 16777215 - + + + + Max. history size: + + + + + + + - - - - 0 - 0 - + + + MB 1 - 1000000000 + 1048576 - - - - - - - 0 - 0 - - - - Benchmark + + 64 @@ -80,31 +85,55 @@ - - - - Max. history size: - - - - - - - Transform rounds: - - - - + Max. history items: - - + + + + Key Derivation Function + + - + + + + + AES: 256 Bit (default) + + + + + Twofish: 256 Bit + + + + + + + + Encryption Algorithm: + + + + + + + Database description: + + + + + + + + + + @@ -121,17 +150,7 @@ - - - - Default username: - - - - - - - + @@ -155,54 +174,101 @@ - - - Use recycle bin + + + + 0 + 0 + + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + 1 + + + 1000000000 + + + + 0 + 0 + + + + Benchmark 1-second delay + + + + true - - + + - Database description: + Default username: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - AES: 256 Bit (default) - - - - - Twofish: 256 Bit - - - - - - + + - Encryption Algorithm: + Transform rounds: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - + + - Key Derivation Function + Memory Usage: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Parallelism: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + thread + + + 1 + + + 128 + + + + + + + Use recycle bin @@ -249,10 +315,6 @@ dbNameEdit dbDescriptionEdit - transformRoundsSpinBox - transformBenchmarkButton - defaultUsernameEdit - recycleBinEnabledCheckBox historyMaxItemsCheckBox historyMaxItemsSpinBox historyMaxSizeCheckBox diff --git a/src/main.cpp b/src/main.cpp index deabeabb7..da71739c4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -27,7 +27,6 @@ #include "crypto/Crypto.h" #include "gui/Application.h" #include "gui/MainWindow.h" -#include "gui/csvImport/CsvImportWizard.h" #include "gui/MessageBox.h" #if defined(WITH_ASAN) && defined(WITH_LSAN)