Revert back to Argon2 reference library
* Fix #7487 - Botan does not use threads when calculating Argon2 KDF leading to very poor performance for a parallelism value > 1. * Include port file for vcpkg backed builds
This commit is contained in:
@@ -336,6 +336,7 @@ target_link_libraries(keepassx_core
|
||||
${PCSC_LIBRARIES}
|
||||
${ZXCVBN_LIBRARIES}
|
||||
${ZLIB_LIBRARIES}
|
||||
${ARGON2_LIBRARIES}
|
||||
${thirdparty_LIBRARIES}
|
||||
)
|
||||
|
||||
|
||||
@@ -17,8 +17,10 @@
|
||||
|
||||
#include "Argon2Kdf.h"
|
||||
|
||||
#include <QElapsedTimer>
|
||||
#include <QThread>
|
||||
#include <botan/pwdhash.h>
|
||||
|
||||
#include <argon2.h>
|
||||
|
||||
#include "format/KeePass2.h"
|
||||
|
||||
@@ -163,20 +165,27 @@ bool Argon2Kdf::transform(const QByteArray& raw, QByteArray& result) const
|
||||
{
|
||||
result.clear();
|
||||
result.resize(32);
|
||||
try {
|
||||
auto algo = type() == Type::Argon2d ? "Argon2d" : "Argon2id";
|
||||
auto pwhash = Botan::PasswordHashFamily::create_or_throw(algo)->from_params(memory(), rounds(), parallelism());
|
||||
pwhash->derive_key(reinterpret_cast<uint8_t*>(result.data()),
|
||||
result.size(),
|
||||
raw.constData(),
|
||||
raw.size(),
|
||||
reinterpret_cast<const uint8_t*>(seed().constData()),
|
||||
seed().size());
|
||||
return true;
|
||||
} catch (std::exception& e) {
|
||||
qWarning("Argon2 error: %s", e.what());
|
||||
// Time Cost, Mem Cost, Threads/Lanes, Password, length, Salt, length, out, length
|
||||
|
||||
int rc = argon2_hash(rounds(),
|
||||
memory(),
|
||||
parallelism(),
|
||||
raw.data(),
|
||||
raw.size(),
|
||||
seed().data(),
|
||||
seed().size(),
|
||||
result.data(),
|
||||
result.size(),
|
||||
nullptr,
|
||||
0,
|
||||
type() == Type::Argon2d ? Argon2_d : Argon2_id,
|
||||
version());
|
||||
if (rc != ARGON2_OK) {
|
||||
qWarning("Argon2 error: %s", argon2_error_message(rc));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QSharedPointer<Kdf> Argon2Kdf::clone() const
|
||||
@@ -186,14 +195,16 @@ QSharedPointer<Kdf> Argon2Kdf::clone() const
|
||||
|
||||
int Argon2Kdf::benchmark(int msec) const
|
||||
{
|
||||
try {
|
||||
auto algo = type() == Type::Argon2d ? "Argon2d" : "Argon2id";
|
||||
auto pwhash = Botan::PasswordHashFamily::create_or_throw(algo)->tune(
|
||||
32, std::chrono::milliseconds(msec), memory() / 1024);
|
||||
return qMax(static_cast<size_t>(1), pwhash->iterations());
|
||||
} catch (std::exception& e) {
|
||||
return 1;
|
||||
QByteArray key = QByteArray(16, '\x7E');
|
||||
|
||||
QElapsedTimer timer;
|
||||
timer.start();
|
||||
|
||||
if (transform(key, key)) {
|
||||
return static_cast<int>(rounds() * (static_cast<float>(msec) / timer.elapsed()));
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
QString Argon2Kdf::toString() const
|
||||
|
||||
@@ -325,6 +325,8 @@ void DatabaseSettingsWidgetEncryption::benchmarkTransformRounds(int millisecs)
|
||||
kdf->setRounds(m_ui->transformRoundsSpinBox->value());
|
||||
if (IS_ARGON2(kdf->uuid())) {
|
||||
auto argon2Kdf = kdf.staticCast<Argon2Kdf>();
|
||||
// Set a small static number of rounds for the benchmark
|
||||
argon2Kdf->setRounds(4);
|
||||
if (!argon2Kdf->setMemory(static_cast<quint64>(m_ui->memorySpinBox->value()) * (1 << 10))) {
|
||||
m_ui->memorySpinBox->setValue(static_cast<int>(argon2Kdf->memory() / (1 << 10)));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user