From e76e9d42c7317d743ae1577e3d296c7060439e13 Mon Sep 17 00:00:00 2001 From: Stephan Heffner Date: Thu, 26 Dec 2024 04:56:02 +0100 Subject: [PATCH] Passphrase "MIXED case" Type (#11255) * An additional approach to create passphrases with one random word being in UPPERCASE. * Also remove duplicate character count from passphrase generator --------- Co-authored-by: Stephan Heffner Co-authored-by: Jonathan White --- share/translations/keepassxc_en.ts | 12 +- src/core/PassphraseGenerator.cpp | 4 + src/core/PassphraseGenerator.h | 3 +- src/gui/PasswordGeneratorWidget.cpp | 2 +- src/gui/PasswordGeneratorWidget.ui | 176 +++++++++++++--------------- tests/gui/TestGui.cpp | 5 +- 6 files changed, 95 insertions(+), 107 deletions(-) diff --git a/share/translations/keepassxc_en.ts b/share/translations/keepassxc_en.ts index c83fefc75..ef75f3e30 100644 --- a/share/translations/keepassxc_en.ts +++ b/share/translations/keepassxc_en.ts @@ -6902,10 +6902,6 @@ The following data is missing: Word Count: - - Character Count: - - Word Case: @@ -6918,10 +6914,6 @@ The following data is missing: Add custom wordlist - - character - - Close @@ -7035,6 +7027,10 @@ Do you want to overwrite it? Characters: %1 + + MIXED case + + Excluded characters: "0", "1", "l", "I", "O", "|", "﹒", "B", "8", "G", "6" diff --git a/src/core/PassphraseGenerator.cpp b/src/core/PassphraseGenerator.cpp index e7d307e02..dfac05e77 100644 --- a/src/core/PassphraseGenerator.cpp +++ b/src/core/PassphraseGenerator.cpp @@ -122,6 +122,7 @@ QString PassphraseGenerator::generatePassphrase() const } QStringList words; + int randomIndex = randomGen()->randomUInt(static_cast(m_wordCount)); for (int i = 0; i < m_wordCount; ++i) { int wordIndex = randomGen()->randomUInt(static_cast(m_wordlist.size())); auto tmpWord = m_wordlist.at(wordIndex); @@ -134,6 +135,9 @@ QString PassphraseGenerator::generatePassphrase() const case TITLECASE: tmpWord = tmpWord.replace(0, 1, tmpWord.left(1).toUpper()); break; + case MIXEDCASE: + tmpWord = i == randomIndex ? tmpWord.toUpper() : tmpWord.toLower(); + break; case LOWERCASE: tmpWord = tmpWord.toLower(); break; diff --git a/src/core/PassphraseGenerator.h b/src/core/PassphraseGenerator.h index e847f658c..931dbe57e 100644 --- a/src/core/PassphraseGenerator.h +++ b/src/core/PassphraseGenerator.h @@ -30,7 +30,8 @@ public: { LOWERCASE, UPPERCASE, - TITLECASE + TITLECASE, + MIXEDCASE }; double estimateEntropy(int wordCount = 0); diff --git a/src/gui/PasswordGeneratorWidget.cpp b/src/gui/PasswordGeneratorWidget.cpp index c1e82974e..f0f48f61a 100644 --- a/src/gui/PasswordGeneratorWidget.cpp +++ b/src/gui/PasswordGeneratorWidget.cpp @@ -99,6 +99,7 @@ PasswordGeneratorWidget::PasswordGeneratorWidget(QWidget* parent) m_ui->wordCaseComboBox->addItem(tr("lower case"), PassphraseGenerator::LOWERCASE); m_ui->wordCaseComboBox->addItem(tr("UPPER CASE"), PassphraseGenerator::UPPERCASE); m_ui->wordCaseComboBox->addItem(tr("Title Case"), PassphraseGenerator::TITLECASE); + m_ui->wordCaseComboBox->addItem(tr("MIXED case"), PassphraseGenerator::MIXEDCASE); // load system-wide wordlists QDir path(resources()->wordlistPath("")); @@ -276,7 +277,6 @@ void PasswordGeneratorWidget::updatePasswordStrength() PasswordHealth passwordHealth(0); if (m_ui->tabWidget->currentIndex() == Diceware) { passwordHealth.init(m_dicewareGenerator->estimateEntropy()); - m_ui->charactersInPassphraseLabel->setText(QString::number(m_ui->editNewPassword->text().length())); } else { passwordHealth = PasswordHealth(m_ui->editNewPassword->text()); } diff --git a/src/gui/PasswordGeneratorWidget.ui b/src/gui/PasswordGeneratorWidget.ui index 34dab2c36..47f197c81 100644 --- a/src/gui/PasswordGeneratorWidget.ui +++ b/src/gui/PasswordGeneratorWidget.ui @@ -769,26 +769,6 @@ QProgressBar::chunk { - - - - Word Separator: - - - - - - - - 0 - 0 - - - - Wordlist: - - - @@ -834,23 +814,6 @@ QProgressBar::chunk { - - - - Word Count: - - - spinBoxLength - - - - - - - Character Count: - - - @@ -858,61 +821,12 @@ QProgressBar::chunk { - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - - 0 - 0 - - - - - 20 - 0 - - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - + + + + Word Separator: + + @@ -954,10 +868,82 @@ QProgressBar::chunk { - - + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + - character + Word Count: + + + spinBoxLength + + + + + + + + + + 0 + 0 + + + + + 20 + 0 + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + 0 + 0 + + + + Wordlist: diff --git a/tests/gui/TestGui.cpp b/tests/gui/TestGui.cpp index f54c97137..e3d418925 100644 --- a/tests/gui/TestGui.cpp +++ b/tests/gui/TestGui.cpp @@ -1027,11 +1027,12 @@ void TestGui::testDicewareEntryEntropy() // Verify entropy and strength auto* entropyLabel = pwGeneratorWidget->findChild("entropyLabel"); auto* strengthLabel = pwGeneratorWidget->findChild("strengthLabel"); - auto* wordLengthLabel = pwGeneratorWidget->findChild("charactersInPassphraseLabel"); + auto* wordLengthLabel = pwGeneratorWidget->findChild("passwordLengthLabel"); QTRY_COMPARE_WITH_TIMEOUT(entropyLabel->text(), QString("Entropy: 77.55 bit"), 200); QCOMPARE(strengthLabel->text(), QString("Password Quality: Good")); - QCOMPARE(wordLengthLabel->text().toInt(), pwGeneratorWidget->getGeneratedPassword().size()); + QCOMPARE(wordLengthLabel->text(), + QString("Characters: %1").arg(QString::number(pwGeneratorWidget->getGeneratedPassword().length()))); QTest::mouseClick(generatedPassword, Qt::LeftButton); QTest::keyClick(generatedPassword, Qt::Key_Escape););