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 | 142 +++++++++++++--------------- tests/gui/TestGui.cpp | 5 +- 6 files changed, 78 insertions(+), 90 deletions(-) diff --git a/share/translations/keepassxc_en.ts b/share/translations/keepassxc_en.ts index c83fefc759..ef75f3e301 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 e7d307e023..dfac05e779 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 e847f658cf..931dbe57e1 100644 --- a/src/core/PassphraseGenerator.h +++ b/src/core/PassphraseGenerator.h @@ -30,7 +30,8 @@ class PassphraseGenerator { LOWERCASE, UPPERCASE, - TITLECASE + TITLECASE, + MIXEDCASE }; double estimateEntropy(int wordCount = 0); diff --git a/src/gui/PasswordGeneratorWidget.cpp b/src/gui/PasswordGeneratorWidget.cpp index c1e82974eb..f0f48f61a8 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 34dab2c36c..47f197c816 100644 --- a/src/gui/PasswordGeneratorWidget.ui +++ b/src/gui/PasswordGeneratorWidget.ui @@ -769,26 +769,6 @@ QProgressBar::chunk { - - - - Word Separator: - - - - - - - - 0 - 0 - - - - Wordlist: - - - @@ -834,29 +814,59 @@ QProgressBar::chunk { - - + + - Word Count: - - - spinBoxLength + Word Case: - - + + - Character Count: + Word Separator: - - - - Word Case: - - + + + + + + + 0 + 0 + + + + + + + + Qt::TabFocus + + + Delete selected wordlist + + + Delete selected wordlist + + + + + + + Qt::TabFocus + + + Add custom wordlist + + + Add custom wordlist + + + + @@ -878,6 +888,16 @@ QProgressBar::chunk { + + + + Word Count: + + + spinBoxLength + + + @@ -914,50 +934,16 @@ QProgressBar::chunk { - - - - - - - 0 - 0 - - - - - - - - Qt::TabFocus - - - Delete selected wordlist - - - Delete selected wordlist - - - - - - - Qt::TabFocus - - - Add custom wordlist - - - Add custom wordlist - - - - - - - + + + + + 0 + 0 + + - character + Wordlist: diff --git a/tests/gui/TestGui.cpp b/tests/gui/TestGui.cpp index f54c971379..e3d4189258 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););