mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2025-03-02 03:09:51 -05:00
Add Argon2Kdf and enable parameters in db settings
Note: This implementation is not yet connected to the database itself and will corrupt existing kdbx3 db's. * Implemented memory and parallelism parameters for Argon2Kdf * Using libargon2; libsodium does not support Argon2d algorithm * Moved basic rounds parameter into Kdf class * Reimplemented benchmark algorithm; previous was utterly broken
This commit is contained in:
parent
9140893cd3
commit
542ee42313
@ -261,8 +261,8 @@ endif()
|
|||||||
set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS_NONE QT_NO_DEBUG)
|
set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS_NONE QT_NO_DEBUG)
|
||||||
|
|
||||||
find_package(LibGPGError REQUIRED)
|
find_package(LibGPGError REQUIRED)
|
||||||
|
|
||||||
find_package(Gcrypt 1.7.0 REQUIRED)
|
find_package(Gcrypt 1.7.0 REQUIRED)
|
||||||
|
find_package(Argon2 REQUIRED)
|
||||||
|
|
||||||
find_package(ZLIB REQUIRED)
|
find_package(ZLIB REQUIRED)
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@ The following libraries are required:
|
|||||||
* libmicrohttpd
|
* libmicrohttpd
|
||||||
* libxi, libxtst, qtx11extras (optional for auto-type on X11)
|
* libxi, libxtst, qtx11extras (optional for auto-type on X11)
|
||||||
* libsodium (>= 1.0.12, optional for keepassxc-browser support)
|
* libsodium (>= 1.0.12, optional for keepassxc-browser support)
|
||||||
|
* libargon2
|
||||||
|
|
||||||
|
|
||||||
Prepare the Building Environment
|
Prepare the Building Environment
|
||||||
|
21
cmake/FindArgon2.cmake
Normal file
21
cmake/FindArgon2.cmake
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
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)
|
@ -78,6 +78,7 @@ set(keepassx_SOURCES
|
|||||||
crypto/kdf/Kdf.cpp
|
crypto/kdf/Kdf.cpp
|
||||||
crypto/kdf/Kdf_p.h
|
crypto/kdf/Kdf_p.h
|
||||||
crypto/kdf/AesKdf.cpp
|
crypto/kdf/AesKdf.cpp
|
||||||
|
crypto/kdf/Argon2Kdf.cpp
|
||||||
format/CsvExporter.cpp
|
format/CsvExporter.cpp
|
||||||
format/KeePass1.h
|
format/KeePass1.h
|
||||||
format/KeePass1Reader.cpp
|
format/KeePass1Reader.cpp
|
||||||
@ -252,6 +253,7 @@ target_link_libraries(keepassx_core
|
|||||||
Qt5::Network
|
Qt5::Network
|
||||||
Qt5::Concurrent
|
Qt5::Concurrent
|
||||||
Qt5::Widgets
|
Qt5::Widgets
|
||||||
|
${ARGON2_LIBRARIES}
|
||||||
${GCRYPT_LIBRARIES}
|
${GCRYPT_LIBRARIES}
|
||||||
${GPGERROR_LIBRARIES}
|
${GPGERROR_LIBRARIES}
|
||||||
${ZLIB_LIBRARIES})
|
${ZLIB_LIBRARIES})
|
||||||
|
@ -46,6 +46,7 @@ target_link_libraries(keepassxc-cli
|
|||||||
keepassx_core
|
keepassx_core
|
||||||
Qt5::Core
|
Qt5::Core
|
||||||
${GCRYPT_LIBRARIES}
|
${GCRYPT_LIBRARIES}
|
||||||
|
${ARGON2_LIBRARIES}
|
||||||
${GPGERROR_LIBRARIES}
|
${GPGERROR_LIBRARIES}
|
||||||
${ZLIB_LIBRARIES}
|
${ZLIB_LIBRARIES}
|
||||||
${ZXCVBN_LIBRARIES})
|
${ZXCVBN_LIBRARIES})
|
||||||
|
@ -45,7 +45,7 @@ Database::Database()
|
|||||||
m_data.cipher = KeePass2::CIPHER_AES;
|
m_data.cipher = KeePass2::CIPHER_AES;
|
||||||
m_data.compressionAlgo = CompressionGZip;
|
m_data.compressionAlgo = CompressionGZip;
|
||||||
m_data.kdf = QSharedPointer<AesKdf>::create();
|
m_data.kdf = QSharedPointer<AesKdf>::create();
|
||||||
m_data.kdf->randomizeTransformSalt();
|
m_data.kdf->randomizeSeed();
|
||||||
m_data.hasKey = false;
|
m_data.hasKey = false;
|
||||||
|
|
||||||
setRootGroup(new Group());
|
setRootGroup(new Group());
|
||||||
@ -258,7 +258,7 @@ void Database::setCompressionAlgo(Database::CompressionAlgorithm algo)
|
|||||||
bool Database::setKey(const CompositeKey& key, bool updateChangedTime, bool updateTransformSalt)
|
bool Database::setKey(const CompositeKey& key, bool updateChangedTime, bool updateTransformSalt)
|
||||||
{
|
{
|
||||||
if (updateTransformSalt) {
|
if (updateTransformSalt) {
|
||||||
m_data.kdf->randomizeTransformSalt();
|
m_data.kdf->randomizeSeed();
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray transformedMasterKey;
|
QByteArray transformedMasterKey;
|
||||||
@ -490,7 +490,7 @@ void Database::setKdf(QSharedPointer<Kdf> kdf)
|
|||||||
|
|
||||||
bool Database::changeKdf(QSharedPointer<Kdf> kdf)
|
bool Database::changeKdf(QSharedPointer<Kdf> kdf)
|
||||||
{
|
{
|
||||||
kdf->randomizeTransformSalt();
|
kdf->randomizeSeed();
|
||||||
QByteArray transformedMasterKey;
|
QByteArray transformedMasterKey;
|
||||||
if (!m_data.key.transform(*kdf, transformedMasterKey)) {
|
if (!m_data.key.transform(*kdf, transformedMasterKey)) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -15,12 +15,17 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "AesKdf.h"
|
||||||
|
|
||||||
#include <QtConcurrent>
|
#include <QtConcurrent>
|
||||||
|
|
||||||
#include "format/KeePass2.h"
|
#include "format/KeePass2.h"
|
||||||
#include "crypto/CryptoHash.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
|
bool AesKdf::transform(const QByteArray& raw, QByteArray& result) const
|
||||||
{
|
{
|
||||||
@ -44,7 +49,7 @@ bool AesKdf::transform(const QByteArray& raw, QByteArray& result) const
|
|||||||
return true;
|
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);
|
QByteArray iv(16, 0);
|
||||||
SymmetricCipher cipher(SymmetricCipher::Aes256, SymmetricCipher::Ecb,
|
SymmetricCipher cipher(SymmetricCipher::Aes256, SymmetricCipher::Ecb,
|
||||||
@ -65,44 +70,6 @@ bool AesKdf::transformKeyRaw(const QByteArray& key, const QByteArray& seed, quin
|
|||||||
return true;
|
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<Kdf> AesKdf::clone() const
|
QSharedPointer<Kdf> AesKdf::clone() const
|
||||||
{
|
{
|
||||||
return QSharedPointer<AesKdf>::create(*this);
|
return QSharedPointer<AesKdf>::create(*this);
|
||||||
@ -117,17 +84,13 @@ int AesKdf::benchmarkImpl(int msec) const
|
|||||||
SymmetricCipher cipher(SymmetricCipher::Aes256, SymmetricCipher::Ecb, SymmetricCipher::Encrypt);
|
SymmetricCipher cipher(SymmetricCipher::Aes256, SymmetricCipher::Ecb, SymmetricCipher::Encrypt);
|
||||||
cipher.init(seed, iv);
|
cipher.init(seed, iv);
|
||||||
|
|
||||||
int rounds = 0;
|
quint64 rounds = 1000000;
|
||||||
QElapsedTimer timer;
|
QElapsedTimer timer;
|
||||||
timer.start();
|
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<int>(rounds * (static_cast<float>(msec) / timer.elapsed()));
|
||||||
}
|
}
|
||||||
|
@ -26,25 +26,15 @@ public:
|
|||||||
AesKdf();
|
AesKdf();
|
||||||
|
|
||||||
bool transform(const QByteArray& raw, QByteArray& result) const override;
|
bool transform(const QByteArray& raw, QByteArray& result) const override;
|
||||||
void randomizeTransformSalt() override;
|
|
||||||
QSharedPointer<Kdf> clone() const override;
|
QSharedPointer<Kdf> clone() const override;
|
||||||
|
|
||||||
quint64 rounds() const override;
|
|
||||||
QByteArray seed() const override;
|
|
||||||
|
|
||||||
bool setRounds(quint64 rounds) override;
|
|
||||||
bool setSeed(const QByteArray& seed) override;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int benchmarkImpl(int msec) const override;
|
int benchmarkImpl(int msec) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
quint64 m_rounds;
|
|
||||||
QByteArray m_seed;
|
|
||||||
|
|
||||||
static bool transformKeyRaw(const QByteArray& key,
|
static bool transformKeyRaw(const QByteArray& key,
|
||||||
const QByteArray& seed,
|
const QByteArray& seed,
|
||||||
quint64 rounds,
|
int rounds,
|
||||||
QByteArray* result) Q_REQUIRED_RESULT;
|
QByteArray* result) Q_REQUIRED_RESULT;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
116
src/crypto/kdf/Argon2Kdf.cpp
Normal file
116
src/crypto/kdf/Argon2Kdf.cpp
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Argon2Kdf.h"
|
||||||
|
|
||||||
|
#include <QtConcurrent>
|
||||||
|
#include <argon2.h>
|
||||||
|
|
||||||
|
#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<Kdf> Argon2Kdf::clone() const
|
||||||
|
{
|
||||||
|
return QSharedPointer<Argon2Kdf>::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<int>(rounds * (static_cast<float>(msec) / timer.elapsed()));
|
||||||
|
}
|
50
src/crypto/kdf/Argon2Kdf.h
Normal file
50
src/crypto/kdf/Argon2Kdf.h
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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<Kdf> 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
|
@ -20,8 +20,12 @@
|
|||||||
|
|
||||||
#include <QtConcurrent>
|
#include <QtConcurrent>
|
||||||
|
|
||||||
|
#include "crypto/Random.h"
|
||||||
|
|
||||||
Kdf::Kdf(Uuid uuid)
|
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;
|
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
|
int Kdf::benchmark(int msec) const
|
||||||
{
|
{
|
||||||
BenchmarkThread thread1(msec, this);
|
BenchmarkThread thread1(msec, this);
|
||||||
@ -41,7 +76,7 @@ int Kdf::benchmark(int msec) const
|
|||||||
thread1.wait();
|
thread1.wait();
|
||||||
thread2.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)
|
Kdf::BenchmarkThread::BenchmarkThread(int msec, const Kdf* kdf)
|
||||||
|
@ -22,6 +22,9 @@
|
|||||||
|
|
||||||
#include "core/Uuid.h"
|
#include "core/Uuid.h"
|
||||||
|
|
||||||
|
#define KDF_DEFAULT_SEED_SIZE 32
|
||||||
|
#define KDF_DEFAULT_ROUNDS 100000ull
|
||||||
|
|
||||||
class Kdf
|
class Kdf
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -30,12 +33,13 @@ public:
|
|||||||
|
|
||||||
Uuid uuid() const;
|
Uuid uuid() const;
|
||||||
|
|
||||||
virtual quint64 rounds() const = 0;
|
int rounds() const;
|
||||||
virtual bool setRounds(quint64 rounds) = 0;
|
virtual bool setRounds(int rounds);
|
||||||
virtual QByteArray seed() const = 0;
|
QByteArray seed() const;
|
||||||
virtual bool setSeed(const QByteArray& seed) = 0;
|
virtual bool setSeed(const QByteArray& seed);
|
||||||
|
virtual void randomizeSeed();
|
||||||
|
|
||||||
virtual bool transform(const QByteArray& raw, QByteArray& result) const = 0;
|
virtual bool transform(const QByteArray& raw, QByteArray& result) const = 0;
|
||||||
virtual void randomizeTransformSalt() = 0;
|
|
||||||
virtual QSharedPointer<Kdf> clone() const = 0;
|
virtual QSharedPointer<Kdf> clone() const = 0;
|
||||||
|
|
||||||
int benchmark(int msec) const;
|
int benchmark(int msec) const;
|
||||||
@ -43,6 +47,9 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
virtual int benchmarkImpl(int msec) const = 0;
|
virtual int benchmarkImpl(int msec) const = 0;
|
||||||
|
|
||||||
|
int m_rounds;
|
||||||
|
QByteArray m_seed;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class BenchmarkThread;
|
class BenchmarkThread;
|
||||||
const Uuid m_uuid;
|
const Uuid m_uuid;
|
||||||
|
@ -16,15 +16,16 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "KeePass2.h"
|
#include "KeePass2.h"
|
||||||
#include "crypto/kdf/AesKdf.h"
|
|
||||||
#include <QSharedPointer>
|
#include <QSharedPointer>
|
||||||
|
#include "crypto/kdf/AesKdf.h"
|
||||||
|
#include "crypto/kdf/Argon2Kdf.h"
|
||||||
|
|
||||||
const Uuid KeePass2::CIPHER_AES = Uuid(QByteArray::fromHex("31c1f2e6bf714350be5805216afc5aff"));
|
const Uuid KeePass2::CIPHER_AES = Uuid(QByteArray::fromHex("31c1f2e6bf714350be5805216afc5aff"));
|
||||||
const Uuid KeePass2::CIPHER_TWOFISH = Uuid(QByteArray::fromHex("ad68f29f576f4bb9a36ad47af965346c"));
|
const Uuid KeePass2::CIPHER_TWOFISH = Uuid(QByteArray::fromHex("ad68f29f576f4bb9a36ad47af965346c"));
|
||||||
const Uuid KeePass2::CIPHER_CHACHA20 = Uuid(QByteArray::fromHex("D6038A2B8B6F4CB5A524339A31DBB59A"));
|
const Uuid KeePass2::CIPHER_CHACHA20 = Uuid(QByteArray::fromHex("D6038A2B8B6F4CB5A524339A31DBB59A"));
|
||||||
|
|
||||||
const Uuid KeePass2::KDF_AES = Uuid(QByteArray::fromHex("C9D9F39A628A4460BF740D08C18A4FEA"));
|
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");
|
const QByteArray KeePass2::INNER_STREAM_SALSA20_IV("\xE8\x30\x09\x4B\x97\x20\x5D\x2A");
|
||||||
|
|
||||||
@ -35,12 +36,15 @@ const QList<QPair<Uuid, QString>> KeePass2::CIPHERS {
|
|||||||
};
|
};
|
||||||
const QList<QPair<Uuid, QString>> KeePass2::KDFS {
|
const QList<QPair<Uuid, QString>> KeePass2::KDFS {
|
||||||
qMakePair(KeePass2::KDF_AES, QObject::tr("AES-KDF")),
|
qMakePair(KeePass2::KDF_AES, QObject::tr("AES-KDF")),
|
||||||
|
qMakePair(KeePass2::KDF_ARGON2, QObject::tr("Argon2")),
|
||||||
};
|
};
|
||||||
|
|
||||||
QSharedPointer<Kdf> KeePass2::uuidToKdf(const Uuid& uuid)
|
QSharedPointer<Kdf> KeePass2::uuidToKdf(const Uuid& uuid)
|
||||||
{
|
{
|
||||||
if (uuid == KDF_AES) {
|
if (uuid == KDF_AES) {
|
||||||
return QSharedPointer<AesKdf>::create();
|
return QSharedPointer<AesKdf>::create();
|
||||||
|
} else if (uuid == KDF_ARGON2) {
|
||||||
|
return QSharedPointer<Argon2Kdf>::create();
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_ASSERT_X(false, "uuidToKdf", "Invalid UUID");
|
Q_ASSERT_X(false, "uuidToKdf", "Invalid UUID");
|
||||||
|
@ -40,6 +40,7 @@ namespace KeePass2
|
|||||||
extern const Uuid CIPHER_CHACHA20;
|
extern const Uuid CIPHER_CHACHA20;
|
||||||
|
|
||||||
extern const Uuid KDF_AES;
|
extern const Uuid KDF_AES;
|
||||||
|
extern const Uuid KDF_ARGON2;
|
||||||
|
|
||||||
extern const QByteArray INNER_STREAM_SALSA20_IV;
|
extern const QByteArray INNER_STREAM_SALSA20_IV;
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include "core/Group.h"
|
#include "core/Group.h"
|
||||||
#include "core/Metadata.h"
|
#include "core/Metadata.h"
|
||||||
#include "crypto/SymmetricCipher.h"
|
#include "crypto/SymmetricCipher.h"
|
||||||
|
#include "crypto/kdf/Argon2Kdf.h"
|
||||||
#include "MessageBox.h"
|
#include "MessageBox.h"
|
||||||
|
|
||||||
DatabaseSettingsWidget::DatabaseSettingsWidget(QWidget* parent)
|
DatabaseSettingsWidget::DatabaseSettingsWidget(QWidget* parent)
|
||||||
@ -42,6 +43,7 @@ DatabaseSettingsWidget::DatabaseSettingsWidget(QWidget* parent)
|
|||||||
connect(m_ui->historyMaxSizeCheckBox, SIGNAL(toggled(bool)),
|
connect(m_ui->historyMaxSizeCheckBox, SIGNAL(toggled(bool)),
|
||||||
m_ui->historyMaxSizeSpinBox, SLOT(setEnabled(bool)));
|
m_ui->historyMaxSizeSpinBox, SLOT(setEnabled(bool)));
|
||||||
connect(m_ui->transformBenchmarkButton, SIGNAL(clicked()), SLOT(transformRoundsBenchmark()));
|
connect(m_ui->transformBenchmarkButton, SIGNAL(clicked()), SLOT(transformRoundsBenchmark()));
|
||||||
|
connect(m_ui->kdfComboBox, SIGNAL(currentIndexChanged(int)), SLOT(kdfChanged(int)));
|
||||||
}
|
}
|
||||||
|
|
||||||
DatabaseSettingsWidget::~DatabaseSettingsWidget()
|
DatabaseSettingsWidget::~DatabaseSettingsWidget()
|
||||||
@ -83,19 +85,29 @@ void DatabaseSettingsWidget::load(Database* db)
|
|||||||
m_ui->algorithmComboBox->setCurrentIndex(cipherIndex);
|
m_ui->algorithmComboBox->setCurrentIndex(cipherIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool blockSignals = m_ui->kdfComboBox->signalsBlocked();
|
// Setup kdf combo box
|
||||||
m_ui->kdfComboBox->blockSignals(true);
|
m_ui->kdfComboBox->blockSignals(true);
|
||||||
|
|
||||||
m_ui->kdfComboBox->clear();
|
m_ui->kdfComboBox->clear();
|
||||||
for (auto& kdf: asConst(KeePass2::KDFS)) {
|
for (auto& kdf: asConst(KeePass2::KDFS)) {
|
||||||
m_ui->kdfComboBox->addItem(kdf.second, kdf.first.toByteArray());
|
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) {
|
if (kdfIndex > -1) {
|
||||||
m_ui->kdfComboBox->setCurrentIndex(kdfIndex);
|
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<Argon2Kdf>();
|
||||||
|
m_ui->memorySpinBox->setValue(argon2Kdf->memory());
|
||||||
|
m_ui->parallelismSpinBox->setValue(argon2Kdf->parallelism());
|
||||||
}
|
}
|
||||||
m_ui->kdfComboBox->blockSignals(blockSignals);
|
|
||||||
m_ui->transformRoundsSpinBox->setValue(static_cast<unsigned>(m_db->kdf()->rounds()));
|
|
||||||
|
|
||||||
m_ui->dbNameEdit->setFocus();
|
m_ui->dbNameEdit->setFocus();
|
||||||
}
|
}
|
||||||
@ -139,8 +151,14 @@ void DatabaseSettingsWidget::save()
|
|||||||
|
|
||||||
m_db->setCipher(Uuid(m_ui->algorithmComboBox->currentData().toByteArray()));
|
m_db->setCipher(Uuid(m_ui->algorithmComboBox->currentData().toByteArray()));
|
||||||
|
|
||||||
|
// Save kdf parameters
|
||||||
auto kdf = KeePass2::uuidToKdf(Uuid(m_ui->kdfComboBox->currentData().toByteArray()));
|
auto kdf = KeePass2::uuidToKdf(Uuid(m_ui->kdfComboBox->currentData().toByteArray()));
|
||||||
kdf->setRounds(static_cast<quint64>(qMax(0, m_ui->transformRoundsSpinBox->value())));
|
kdf->setRounds(m_ui->transformRoundsSpinBox->value());
|
||||||
|
if (kdf->uuid() == KeePass2::KDF_ARGON2) {
|
||||||
|
auto argon2Kdf = kdf.staticCast<Argon2Kdf>();
|
||||||
|
argon2Kdf->setMemory(m_ui->memorySpinBox->value());
|
||||||
|
argon2Kdf->setParallelism(m_ui->parallelismSpinBox->value());
|
||||||
|
}
|
||||||
|
|
||||||
QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
|
QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
|
||||||
// TODO: we should probably use AsyncTask::runAndWaitForFuture() here,
|
// TODO: we should probably use AsyncTask::runAndWaitForFuture() here,
|
||||||
@ -164,11 +182,26 @@ void DatabaseSettingsWidget::reject()
|
|||||||
void DatabaseSettingsWidget::transformRoundsBenchmark()
|
void DatabaseSettingsWidget::transformRoundsBenchmark()
|
||||||
{
|
{
|
||||||
QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
|
QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
|
||||||
m_ui->transformRoundsSpinBox->setValue(AsyncTask::runAndWaitForFuture([this]() {
|
m_ui->transformBenchmarkButton->setEnabled(false);
|
||||||
int rounds = m_db->kdf()->benchmark(1000);
|
|
||||||
QApplication::restoreOverrideCursor();
|
// Create a new kdf with the current parameters
|
||||||
return rounds;
|
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>();
|
||||||
|
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()
|
void DatabaseSettingsWidget::truncateHistories()
|
||||||
@ -178,3 +211,15 @@ void DatabaseSettingsWidget::truncateHistories()
|
|||||||
entry->truncateHistory();
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -51,6 +51,7 @@ private slots:
|
|||||||
void save();
|
void save();
|
||||||
void reject();
|
void reject();
|
||||||
void transformRoundsBenchmark();
|
void transformRoundsBenchmark();
|
||||||
|
void kdfChanged(int index);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void truncateHistories();
|
void truncateHistories();
|
||||||
|
@ -2,6 +2,14 @@
|
|||||||
<ui version="4.0">
|
<ui version="4.0">
|
||||||
<class>DatabaseSettingsWidget</class>
|
<class>DatabaseSettingsWidget</class>
|
||||||
<widget class="QWidget" name="DatabaseSettingsWidget">
|
<widget class="QWidget" name="DatabaseSettingsWidget">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>1082</width>
|
||||||
|
<height>506</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout" stretch="1,2,5,1">
|
<layout class="QVBoxLayout" name="verticalLayout" stretch="1,2,5,1">
|
||||||
<item>
|
<item>
|
||||||
<spacer name="verticalSpacer_2">
|
<spacer name="verticalSpacer_2">
|
||||||
@ -35,39 +43,36 @@
|
|||||||
<widget class="QWidget" name="widget" native="true">
|
<widget class="QWidget" name="widget" native="true">
|
||||||
<property name="maximumSize">
|
<property name="maximumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>800</width>
|
<width>400</width>
|
||||||
<height>16777215</height>
|
<height>16777215</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout">
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
<item row="4" column="2">
|
<item row="11" column="1">
|
||||||
|
<widget class="QCheckBox" name="historyMaxSizeCheckBox">
|
||||||
|
<property name="text">
|
||||||
|
<string>Max. history size:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="2">
|
||||||
|
<widget class="QLineEdit" name="dbNameEdit"/>
|
||||||
|
</item>
|
||||||
|
<item row="7" column="2">
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QSpinBox" name="transformRoundsSpinBox">
|
<widget class="QSpinBox" name="memorySpinBox">
|
||||||
<property name="sizePolicy">
|
<property name="suffix">
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
<string> MB</string>
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
</property>
|
||||||
<property name="minimum">
|
<property name="minimum">
|
||||||
<number>1</number>
|
<number>1</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="maximum">
|
<property name="maximum">
|
||||||
<number>1000000000</number>
|
<number>1048576</number>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
<property name="value">
|
||||||
</item>
|
<number>64</number>
|
||||||
<item>
|
|
||||||
<widget class="QToolButton" name="transformBenchmarkButton">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Fixed" vsizetype="MinimumExpanding">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Benchmark</string>
|
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -80,31 +85,55 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="8" column="1">
|
<item row="10" column="1">
|
||||||
<widget class="QCheckBox" name="historyMaxSizeCheckBox">
|
|
||||||
<property name="text">
|
|
||||||
<string>Max. history size:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="1" alignment="Qt::AlignRight">
|
|
||||||
<widget class="QLabel" name="transformRoundsLabel">
|
|
||||||
<property name="text">
|
|
||||||
<string>Transform rounds:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="7" column="1">
|
|
||||||
<widget class="QCheckBox" name="historyMaxItemsCheckBox">
|
<widget class="QCheckBox" name="historyMaxItemsCheckBox">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Max. history items:</string>
|
<string>Max. history items:</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="2">
|
<item row="4" column="1">
|
||||||
<widget class="QLineEdit" name="dbNameEdit"/>
|
<widget class="QLabel" name="kdfLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Key Derivation Function</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="7" column="2">
|
<item row="3" column="2">
|
||||||
|
<widget class="QComboBox" name="algorithmComboBox">
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>AES: 256 Bit (default)</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Twofish: 256 Bit</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="1" alignment="Qt::AlignRight">
|
||||||
|
<widget class="QLabel" name="algorithmLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Encryption Algorithm:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1" alignment="Qt::AlignRight">
|
||||||
|
<widget class="QLabel" name="dbDescriptionLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Database description:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="2">
|
||||||
|
<widget class="QLineEdit" name="dbDescriptionEdit"/>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="2">
|
||||||
|
<widget class="QComboBox" name="kdfComboBox"/>
|
||||||
|
</item>
|
||||||
|
<item row="10" column="2">
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QSpinBox" name="historyMaxItemsSpinBox">
|
<widget class="QSpinBox" name="historyMaxItemsSpinBox">
|
||||||
@ -121,17 +150,7 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item row="5" column="1" alignment="Qt::AlignRight">
|
<item row="11" column="2">
|
||||||
<widget class="QLabel" name="defaultUsernameLabel">
|
|
||||||
<property name="text">
|
|
||||||
<string>Default username:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="2">
|
|
||||||
<widget class="QLineEdit" name="dbDescriptionEdit"/>
|
|
||||||
</item>
|
|
||||||
<item row="8" column="2">
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QSpinBox" name="historyMaxSizeSpinBox">
|
<widget class="QSpinBox" name="historyMaxSizeSpinBox">
|
||||||
@ -155,54 +174,101 @@
|
|||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item row="6" column="2">
|
<item row="6" column="2">
|
||||||
<widget class="QCheckBox" name="recycleBinEnabledCheckBox">
|
<widget class="QSpinBox" name="transformRoundsSpinBox">
|
||||||
<property name="text">
|
<property name="sizePolicy">
|
||||||
<string>Use recycle bin</string>
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<number>1</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>1000000000</number>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="5" column="2">
|
<item row="5" column="2">
|
||||||
|
<widget class="QToolButton" name="transformBenchmarkButton">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Benchmark 1-second delay</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="2">
|
||||||
<widget class="QLineEdit" name="defaultUsernameEdit">
|
<widget class="QLineEdit" name="defaultUsernameEdit">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="1" alignment="Qt::AlignRight">
|
<item row="2" column="1">
|
||||||
<widget class="QLabel" name="dbDescriptionLabel">
|
<widget class="QLabel" name="defaultUsernameLabel">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Database description:</string>
|
<string>Default username:</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="2">
|
<item row="6" column="1">
|
||||||
<widget class="QComboBox" name="algorithmComboBox">
|
<widget class="QLabel" name="transformRoundsLabel">
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>AES: 256 Bit (default)</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>Twofish: 256 Bit</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="1" alignment="Qt::AlignRight">
|
|
||||||
<widget class="QLabel" name="algorithmLabel">
|
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Encryption Algorithm:</string>
|
<string>Transform rounds:</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="2">
|
<item row="7" column="1">
|
||||||
<widget class="QComboBox" name="kdfComboBox"/>
|
<widget class="QLabel" name="memoryUsageLabel">
|
||||||
</item>
|
|
||||||
<item row="3" column="1">
|
|
||||||
<widget class="QLabel" name="kdfLabel">
|
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Key Derivation Function</string>
|
<string>Memory Usage:</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="8" column="1">
|
||||||
|
<widget class="QLabel" name="parallelismLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Parallelism:</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="8" column="2">
|
||||||
|
<widget class="QSpinBox" name="parallelismSpinBox">
|
||||||
|
<property name="suffix">
|
||||||
|
<string> thread</string>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<number>1</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>128</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="9" column="1">
|
||||||
|
<widget class="QCheckBox" name="recycleBinEnabledCheckBox">
|
||||||
|
<property name="text">
|
||||||
|
<string>Use recycle bin</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -249,10 +315,6 @@
|
|||||||
<tabstops>
|
<tabstops>
|
||||||
<tabstop>dbNameEdit</tabstop>
|
<tabstop>dbNameEdit</tabstop>
|
||||||
<tabstop>dbDescriptionEdit</tabstop>
|
<tabstop>dbDescriptionEdit</tabstop>
|
||||||
<tabstop>transformRoundsSpinBox</tabstop>
|
|
||||||
<tabstop>transformBenchmarkButton</tabstop>
|
|
||||||
<tabstop>defaultUsernameEdit</tabstop>
|
|
||||||
<tabstop>recycleBinEnabledCheckBox</tabstop>
|
|
||||||
<tabstop>historyMaxItemsCheckBox</tabstop>
|
<tabstop>historyMaxItemsCheckBox</tabstop>
|
||||||
<tabstop>historyMaxItemsSpinBox</tabstop>
|
<tabstop>historyMaxItemsSpinBox</tabstop>
|
||||||
<tabstop>historyMaxSizeCheckBox</tabstop>
|
<tabstop>historyMaxSizeCheckBox</tabstop>
|
||||||
|
@ -27,7 +27,6 @@
|
|||||||
#include "crypto/Crypto.h"
|
#include "crypto/Crypto.h"
|
||||||
#include "gui/Application.h"
|
#include "gui/Application.h"
|
||||||
#include "gui/MainWindow.h"
|
#include "gui/MainWindow.h"
|
||||||
#include "gui/csvImport/CsvImportWizard.h"
|
|
||||||
#include "gui/MessageBox.h"
|
#include "gui/MessageBox.h"
|
||||||
|
|
||||||
#if defined(WITH_ASAN) && defined(WITH_LSAN)
|
#if defined(WITH_ASAN) && defined(WITH_LSAN)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user