mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2024-10-01 01:26:01 -04:00
Fix TestCli and TestGui entropy tests across platforms
* zxcvbn wordlists can vary between platforms depending on packager adjustments (ie, zxcvbn-c vs Ubuntu Focal)
This commit is contained in:
parent
3a86381df8
commit
caece405fb
@ -26,6 +26,7 @@
|
|||||||
#include "crypto/Crypto.h"
|
#include "crypto/Crypto.h"
|
||||||
#include "keys/FileKey.h"
|
#include "keys/FileKey.h"
|
||||||
#include "keys/drivers/YubiKey.h"
|
#include "keys/drivers/YubiKey.h"
|
||||||
|
#include "zxcvbn/zxcvbn.h"
|
||||||
|
|
||||||
#include "cli/Add.h"
|
#include "cli/Add.h"
|
||||||
#include "cli/AddGroup.h"
|
#include "cli/AddGroup.h"
|
||||||
@ -1186,90 +1187,72 @@ void TestCli::testEdit()
|
|||||||
|
|
||||||
void TestCli::testEstimate_data()
|
void TestCli::testEstimate_data()
|
||||||
{
|
{
|
||||||
|
// clang-format off
|
||||||
QTest::addColumn<QString>("input");
|
QTest::addColumn<QString>("input");
|
||||||
QTest::addColumn<QString>("length");
|
|
||||||
QTest::addColumn<QString>("entropy");
|
|
||||||
QTest::addColumn<QString>("log10");
|
|
||||||
QTest::addColumn<QStringList>("searchStrings");
|
QTest::addColumn<QStringList>("searchStrings");
|
||||||
|
|
||||||
QTest::newRow("Dictionary") << "password"
|
QTest::newRow("Dictionary")
|
||||||
<< "8"
|
<< "password"
|
||||||
<< "1.0"
|
<< QStringList{"Type: Dictionary", "\tpassword"};
|
||||||
<< "0.3" << QStringList{"Type: Dictionary", "\tpassword"};
|
|
||||||
|
|
||||||
QTest::newRow("Spatial") << "zxcv"
|
QTest::newRow("Spatial")
|
||||||
<< "4"
|
<< "sdfg"
|
||||||
<< "10.3"
|
<< QStringList{"Type: Spatial", "\tsdfg"};
|
||||||
<< "3.1" << QStringList{"Type: Spatial", "\tzxcv"};
|
|
||||||
|
|
||||||
QTest::newRow("Spatial(Rep)") << "sdfgsdfg"
|
QTest::newRow("Spatial(Rep)")
|
||||||
<< "8"
|
<< "sdfgsdfg"
|
||||||
<< "11.3"
|
<< QStringList{"Type: Spatial(Rep)", "\tsdfgsdfg"};
|
||||||
<< "3.4" << QStringList{"Type: Spatial(Rep)", "\tsdfgsdfg"};
|
|
||||||
|
|
||||||
QTest::newRow("Dictionary / Sequence")
|
QTest::newRow("Dictionary / Sequence")
|
||||||
<< "password123"
|
<< "password123"
|
||||||
<< "11"
|
<< QStringList{"Type: Dictionary", "Type: Sequence", "\tpassword", "\t123"};
|
||||||
<< "4.5"
|
|
||||||
<< "1.3" << QStringList{"Type: Dictionary", "Type: Sequence", "\tpassword", "\t123"};
|
|
||||||
|
|
||||||
QTest::newRow("Dict+Leet") << "p455w0rd"
|
QTest::newRow("Dict+Leet")
|
||||||
<< "8"
|
<< "p455w0rd"
|
||||||
<< "2.5"
|
<< QStringList{"Type: Dict+Leet", "\tp455w0rd"};
|
||||||
<< "0.7" << QStringList{"Type: Dict+Leet", "\tp455w0rd"};
|
|
||||||
|
|
||||||
QTest::newRow("Dictionary(Rep)") << "hellohello"
|
QTest::newRow("Dictionary(Rep)")
|
||||||
<< "10"
|
<< "hellohello"
|
||||||
<< "7.3"
|
<< QStringList{"Type: Dictionary(Rep)", "\thellohello"};
|
||||||
<< "2.2" << QStringList{"Type: Dictionary(Rep)", "\thellohello"};
|
|
||||||
|
|
||||||
QTest::newRow("Sequence(Rep) / Dictionary")
|
QTest::newRow("Sequence(Rep) / Dictionary")
|
||||||
<< "456456foobar"
|
<< "456456foobar"
|
||||||
<< "12"
|
<< QStringList{"Type: Sequence(Rep)", "Type: Dictionary", "\t456456", "\tfoobar"};
|
||||||
<< "16.7"
|
|
||||||
<< "5.0" << QStringList{"Type: Sequence(Rep)", "Type: Dictionary", "\t456456", "\tfoobar"};
|
|
||||||
|
|
||||||
QTest::newRow("Bruteforce(Rep) / Bruteforce")
|
QTest::newRow("Bruteforce(Rep) / Bruteforce")
|
||||||
<< "xzxzy"
|
<< "xzxzy"
|
||||||
<< "5"
|
<< QStringList{"Type: Bruteforce(Rep)", "Type: Bruteforce", "\txzxz", "\ty"};
|
||||||
<< "16.1"
|
|
||||||
<< "4.8" << QStringList{"Type: Bruteforce(Rep)", "Type: Bruteforce", "\txzxz", "\ty"};
|
|
||||||
|
|
||||||
QTest::newRow("Dictionary / Date(Rep)")
|
QTest::newRow("Dictionary / Date(Rep)")
|
||||||
<< "pass20182018"
|
<< "pass20182018"
|
||||||
<< "12"
|
<< QStringList{"Type: Dictionary", "Type: Date(Rep)", "\tpass", "\t20182018"};
|
||||||
<< "15.1"
|
|
||||||
<< "4.56" << QStringList{"Type: Dictionary", "Type: Date(Rep)", "\tpass", "\t20182018"};
|
|
||||||
|
|
||||||
QTest::newRow("Dictionary / Date / Bruteforce")
|
QTest::newRow("Dictionary / Date / Bruteforce")
|
||||||
<< "mypass2018-2"
|
<< "mypass2018-2"
|
||||||
<< "12"
|
<< QStringList{"Type: Dictionary", "Type: Date", "Type: Bruteforce", "\tmypass", "\t2018", "\t-2"};
|
||||||
<< "32.9"
|
|
||||||
<< "9.9" << QStringList{"Type: Dictionary", "Type: Date", "Type: Bruteforce", "\tmypass", "\t2018", "\t-2"};
|
|
||||||
|
|
||||||
QTest::newRow("Strong Password") << "E*!%.Qw{t.X,&bafw)\"Q!ah$%;U/"
|
QTest::newRow("Strong Password")
|
||||||
<< "28"
|
<< "E*!%.Qw{t.X,&bafw)\"Q!ah$%;U/"
|
||||||
<< "165.7"
|
<< QStringList{"Type: Bruteforce", "\tE*"};
|
||||||
<< "49.8" << QStringList{"Type: Bruteforce", "\tE*"};
|
|
||||||
|
|
||||||
// TODO: detect passphrases and adjust entropy calculation accordingly (issue #2347)
|
// TODO: detect passphrases and adjust entropy calculation accordingly (issue #2347)
|
||||||
QTest::newRow("Strong Passphrase")
|
QTest::newRow("Strong Passphrase")
|
||||||
<< "squint wooing resupply dangle isolation axis headsman"
|
<< "squint wooing resupply dangle isolation axis headsman"
|
||||||
<< "53"
|
<< QStringList{"Type: Dictionary", "Type: Bruteforce", "Multi-word extra bits 22.0", "\tsquint", "\t ", "\twooing"};
|
||||||
<< "151.2"
|
// clang-format on
|
||||||
<< "45.5"
|
|
||||||
<< QStringList{
|
|
||||||
"Type: Dictionary", "Type: Bruteforce", "Multi-word extra bits 22.0", "\tsquint", "\t ", "\twooing"};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestCli::testEstimate()
|
void TestCli::testEstimate()
|
||||||
{
|
{
|
||||||
QFETCH(QString, input);
|
QFETCH(QString, input);
|
||||||
QFETCH(QString, length);
|
|
||||||
QFETCH(QString, entropy);
|
|
||||||
QFETCH(QString, log10);
|
|
||||||
QFETCH(QStringList, searchStrings);
|
QFETCH(QStringList, searchStrings);
|
||||||
|
|
||||||
|
// Calculate expected values since zxcvbn output can vary by platform if different wordlists are used
|
||||||
|
const auto e = ZxcvbnMatch(input.toUtf8(), nullptr, nullptr);
|
||||||
|
auto length = QString::number(input.length());
|
||||||
|
auto entropy = QString("%1").arg(e, 0, 'f', 3);
|
||||||
|
auto log10 = QString("%1").arg(e * 0.301029996, 0, 'f', 3);
|
||||||
|
|
||||||
Estimate estimateCmd;
|
Estimate estimateCmd;
|
||||||
QVERIFY(!estimateCmd.name.isEmpty());
|
QVERIFY(!estimateCmd.name.isEmpty());
|
||||||
QVERIFY(estimateCmd.getDescriptionLine().contains(estimateCmd.name));
|
QVERIFY(estimateCmd.getDescriptionLine().contains(estimateCmd.name));
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
#include <QToolBar>
|
#include <QToolBar>
|
||||||
|
|
||||||
#include "config-keepassx-tests.h"
|
#include "config-keepassx-tests.h"
|
||||||
|
#include "core/PasswordHealth.h"
|
||||||
#include "core/Tools.h"
|
#include "core/Tools.h"
|
||||||
#include "crypto/Crypto.h"
|
#include "crypto/Crypto.h"
|
||||||
#include "gui/ApplicationSettingsWidget.h"
|
#include "gui/ApplicationSettingsWidget.h"
|
||||||
@ -682,43 +683,33 @@ void TestGui::testAddEntry()
|
|||||||
void TestGui::testPasswordEntryEntropy_data()
|
void TestGui::testPasswordEntryEntropy_data()
|
||||||
{
|
{
|
||||||
QTest::addColumn<QString>("password");
|
QTest::addColumn<QString>("password");
|
||||||
QTest::addColumn<QString>("expectedEntropyLabel");
|
|
||||||
QTest::addColumn<QString>("expectedStrengthLabel");
|
QTest::addColumn<QString>("expectedStrengthLabel");
|
||||||
|
|
||||||
QTest::newRow("Empty password") << ""
|
QTest::newRow("Empty password") << ""
|
||||||
<< "Entropy: 0.00 bit"
|
|
||||||
<< "Password Quality: Poor";
|
<< "Password Quality: Poor";
|
||||||
|
|
||||||
QTest::newRow("Well-known password") << "hello"
|
QTest::newRow("Well-known password") << "hello"
|
||||||
<< "Entropy: 6.38 bit"
|
|
||||||
<< "Password Quality: Poor";
|
<< "Password Quality: Poor";
|
||||||
|
|
||||||
QTest::newRow("Password composed of well-known words.") << "helloworld"
|
QTest::newRow("Password composed of well-known words.") << "helloworld"
|
||||||
<< "Entropy: 13.10 bit"
|
|
||||||
<< "Password Quality: Poor";
|
<< "Password Quality: Poor";
|
||||||
|
|
||||||
QTest::newRow("Password composed of well-known words with number.") << "password1"
|
QTest::newRow("Password composed of well-known words with number.") << "password1"
|
||||||
<< "Entropy: 4.00 bit"
|
|
||||||
<< "Password Quality: Poor";
|
<< "Password Quality: Poor";
|
||||||
|
|
||||||
QTest::newRow("Password out of small character space.") << "D0g.................."
|
QTest::newRow("Password out of small character space.") << "D0g.................."
|
||||||
<< "Entropy: 19.02 bit"
|
|
||||||
<< "Password Quality: Poor";
|
<< "Password Quality: Poor";
|
||||||
|
|
||||||
QTest::newRow("XKCD, easy substitutions.") << "Tr0ub4dour&3"
|
QTest::newRow("XKCD, easy substitutions.") << "Tr0ub4dour&3"
|
||||||
<< "Entropy: 30.87 bit"
|
|
||||||
<< "Password Quality: Poor";
|
<< "Password Quality: Poor";
|
||||||
|
|
||||||
QTest::newRow("XKCD, word generator.") << "correcthorsebatterystaple"
|
QTest::newRow("XKCD, word generator.") << "correcthorsebatterystaple"
|
||||||
<< "Entropy: 47.98 bit"
|
|
||||||
<< "Password Quality: Weak";
|
<< "Password Quality: Weak";
|
||||||
|
|
||||||
QTest::newRow("Random characters, medium length.") << "YQC3kbXbjC652dTDH"
|
QTest::newRow("Random characters, medium length.") << "YQC3kbXbjC652dTDH"
|
||||||
<< "Entropy: 95.83 bit"
|
|
||||||
<< "Password Quality: Good";
|
<< "Password Quality: Good";
|
||||||
|
|
||||||
QTest::newRow("Random characters, long.") << "Bs5ZFfthWzR8DGFEjaCM6bGqhmCT4km"
|
QTest::newRow("Random characters, long.") << "Bs5ZFfthWzR8DGFEjaCM6bGqhmCT4km"
|
||||||
<< "Entropy: 174.59 bit"
|
|
||||||
<< "Password Quality: Excellent";
|
<< "Password Quality: Excellent";
|
||||||
|
|
||||||
QTest::newRow("Long password using Zxcvbn chunk estimation")
|
QTest::newRow("Long password using Zxcvbn chunk estimation")
|
||||||
@ -726,7 +717,6 @@ void TestGui::testPasswordEntryEntropy_data()
|
|||||||
"ashamed-anatomy-daybed-jam-swear-strudel-neatness-stalemate-unbundle-flavored-relation-emergency-underrate-"
|
"ashamed-anatomy-daybed-jam-swear-strudel-neatness-stalemate-unbundle-flavored-relation-emergency-underrate-"
|
||||||
"registry-getting-award-unveiled-unshaken-stagnate-cartridge-magnitude-ointment-hardener-enforced-scrubbed-"
|
"registry-getting-award-unveiled-unshaken-stagnate-cartridge-magnitude-ointment-hardener-enforced-scrubbed-"
|
||||||
"radial-fiddling-envelope-unpaved-moisture-unused-crawlers-quartered-crushed-kangaroo-tiptop-doily"
|
"radial-fiddling-envelope-unpaved-moisture-unused-crawlers-quartered-crushed-kangaroo-tiptop-doily"
|
||||||
<< "Entropy: 1205.85 bit"
|
|
||||||
<< "Password Quality: Excellent";
|
<< "Password Quality: Excellent";
|
||||||
|
|
||||||
QTest::newRow("Longer password above Zxcvbn threshold")
|
QTest::newRow("Longer password above Zxcvbn threshold")
|
||||||
@ -744,7 +734,6 @@ void TestGui::testPasswordEntryEntropy_data()
|
|||||||
"disparate-decorated-washroom-threefold-muzzle-buckwheat-kerosene-swell-why-reprocess-correct-shady-"
|
"disparate-decorated-washroom-threefold-muzzle-buckwheat-kerosene-swell-why-reprocess-correct-shady-"
|
||||||
"impatient-slit-banshee-scrubbed-dreadful-unlocking-urologist-hurried-citable-fragment-septic-lapped-"
|
"impatient-slit-banshee-scrubbed-dreadful-unlocking-urologist-hurried-citable-fragment-septic-lapped-"
|
||||||
"prankish-phantom-unpaved-moisture-unused-crawlers-quartered-crushed-kangaroo-lapel-emporium-renounce"
|
"prankish-phantom-unpaved-moisture-unused-crawlers-quartered-crushed-kangaroo-lapel-emporium-renounce"
|
||||||
<< "Entropy: 4210.27 bit"
|
|
||||||
<< "Password Quality: Excellent";
|
<< "Password Quality: Excellent";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -793,11 +782,14 @@ void TestGui::testPasswordEntryEntropy()
|
|||||||
auto* strengthLabel = pwGeneratorWidget->findChild<QLabel*>("strengthLabel");
|
auto* strengthLabel = pwGeneratorWidget->findChild<QLabel*>("strengthLabel");
|
||||||
|
|
||||||
QFETCH(QString, password);
|
QFETCH(QString, password);
|
||||||
QFETCH(QString, expectedEntropyLabel);
|
|
||||||
QFETCH(QString, expectedStrengthLabel);
|
QFETCH(QString, expectedStrengthLabel);
|
||||||
|
|
||||||
|
// Dynamically calculate entropy due to variances with zxcvbn wordlists
|
||||||
|
PasswordHealth health(password);
|
||||||
|
auto expectedEntropy = QString("Entropy: %1 bit").arg(QString::number(health.entropy(), 'f', 2));
|
||||||
|
|
||||||
generatedPassword->setText(password);
|
generatedPassword->setText(password);
|
||||||
QCOMPARE(entropyLabel->text(), expectedEntropyLabel);
|
QCOMPARE(entropyLabel->text(), expectedEntropy);
|
||||||
QCOMPARE(strengthLabel->text(), expectedStrengthLabel);
|
QCOMPARE(strengthLabel->text(), expectedStrengthLabel);
|
||||||
|
|
||||||
QTest::mouseClick(generatedPassword, Qt::LeftButton);
|
QTest::mouseClick(generatedPassword, Qt::LeftButton);
|
||||||
|
Loading…
Reference in New Issue
Block a user