Skip to content

Commit

Permalink
Passphrase "MIXED case" Type (#11255)
Browse files Browse the repository at this point in the history
* 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 <[email protected]>
Co-authored-by: Jonathan White <[email protected]>
  • Loading branch information
3 people authored Dec 26, 2024
1 parent 9670a5e commit e76e9d4
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 90 deletions.
12 changes: 4 additions & 8 deletions share/translations/keepassxc_en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6902,10 +6902,6 @@ The following data is missing:
<source>Word Count:</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Character Count:</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Word Case:</source>
<translation type="unfinished"></translation>
Expand All @@ -6918,10 +6914,6 @@ The following data is missing:
<source>Add custom wordlist</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>character</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Close</source>
<translation type="unfinished"></translation>
Expand Down Expand Up @@ -7035,6 +7027,10 @@ Do you want to overwrite it?</source>
<source>Characters: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>MIXED case</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Excluded characters: &quot;0&quot;, &quot;1&quot;, &quot;l&quot;, &quot;I&quot;, &quot;O&quot;, &quot;|&quot;, &quot;&quot;, &quot;B&quot;, &quot;8&quot;, &quot;G&quot;, &quot;6&quot;</source>
<translation type="unfinished"></translation>
Expand Down
4 changes: 4 additions & 0 deletions src/core/PassphraseGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ QString PassphraseGenerator::generatePassphrase() const
}

QStringList words;
int randomIndex = randomGen()->randomUInt(static_cast<quint32>(m_wordCount));
for (int i = 0; i < m_wordCount; ++i) {
int wordIndex = randomGen()->randomUInt(static_cast<quint32>(m_wordlist.size()));
auto tmpWord = m_wordlist.at(wordIndex);
Expand All @@ -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;
Expand Down
3 changes: 2 additions & 1 deletion src/core/PassphraseGenerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ class PassphraseGenerator
{
LOWERCASE,
UPPERCASE,
TITLECASE
TITLECASE,
MIXEDCASE
};

double estimateEntropy(int wordCount = 0);
Expand Down
2 changes: 1 addition & 1 deletion src/gui/PasswordGeneratorWidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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(""));
Expand Down Expand Up @@ -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());
}
Expand Down
142 changes: 64 additions & 78 deletions src/gui/PasswordGeneratorWidget.ui
Original file line number Diff line number Diff line change
Expand Up @@ -769,26 +769,6 @@ QProgressBar::chunk {
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<layout class="QGridLayout" name="gridLayout_3">
<item row="2" column="1" alignment="Qt::AlignRight">
<widget class="QLabel" name="labelWordSeparator">
<property name="text">
<string>Word Separator:</string>
</property>
</widget>
</item>
<item row="0" column="1" alignment="Qt::AlignRight">
<widget class="QLabel" name="labelWordList">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Wordlist:</string>
</property>
</widget>
</item>
<item row="1" column="2">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="sizeConstraint">
Expand Down Expand Up @@ -834,29 +814,59 @@ QProgressBar::chunk {
</item>
</layout>
</item>
<item row="1" column="1" alignment="Qt::AlignRight">
<widget class="QLabel" name="labelWordCount">
<item row="3" column="1" alignment="Qt::AlignRight">
<widget class="QLabel" name="wordCaseLabel">
<property name="text">
<string>Word Count:</string>
</property>
<property name="buddy">
<cstring>spinBoxLength</cstring>
<string>Word Case:</string>
</property>
</widget>
</item>
<item row="4" column="1" alignment="Qt::AlignRight">
<widget class="QLabel" name="characterCountLabel">
<item row="2" column="1" alignment="Qt::AlignRight">
<widget class="QLabel" name="labelWordSeparator">
<property name="text">
<string>Character Count:</string>
<string>Word Separator:</string>
</property>
</widget>
</item>
<item row="3" column="1" alignment="Qt::AlignRight">
<widget class="QLabel" name="wordCaseLabel">
<property name="text">
<string>Word Case:</string>
</property>
</widget>
<item row="0" column="2">
<layout class="QHBoxLayout" name="horizontalLayout_10">
<item>
<widget class="QComboBox" name="comboBoxWordList">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="buttonDeleteWordList">
<property name="focusPolicy">
<enum>Qt::TabFocus</enum>
</property>
<property name="toolTip">
<string>Delete selected wordlist</string>
</property>
<property name="accessibleDescription">
<string>Delete selected wordlist</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="buttonAddWordList">
<property name="focusPolicy">
<enum>Qt::TabFocus</enum>
</property>
<property name="toolTip">
<string>Add custom wordlist</string>
</property>
<property name="accessibleDescription">
<string>Add custom wordlist</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="3" column="2">
<layout class="QHBoxLayout" name="horizontalLayout_6">
Expand All @@ -878,6 +888,16 @@ QProgressBar::chunk {
</item>
</layout>
</item>
<item row="1" column="1" alignment="Qt::AlignRight">
<widget class="QLabel" name="labelWordCount">
<property name="text">
<string>Word Count:</string>
</property>
<property name="buddy">
<cstring>spinBoxLength</cstring>
</property>
</widget>
</item>
<item row="2" column="2">
<layout class="QHBoxLayout" name="horizontalLayout_9">
<item>
Expand Down Expand Up @@ -914,50 +934,16 @@ QProgressBar::chunk {
</item>
</layout>
</item>
<item row="0" column="2">
<layout class="QHBoxLayout" name="horizontalLayout_10">
<item>
<widget class="QComboBox" name="comboBoxWordList">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="buttonDeleteWordList">
<property name="focusPolicy">
<enum>Qt::TabFocus</enum>
</property>
<property name="toolTip">
<string>Delete selected wordlist</string>
</property>
<property name="accessibleDescription">
<string>Delete selected wordlist</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="buttonAddWordList">
<property name="focusPolicy">
<enum>Qt::TabFocus</enum>
</property>
<property name="toolTip">
<string>Add custom wordlist</string>
</property>
<property name="accessibleDescription">
<string>Add custom wordlist</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="4" column="2" alignment="Qt::AlignLeft">
<widget class="QLabel" name="charactersInPassphraseLabel">
<item row="0" column="1" alignment="Qt::AlignRight">
<widget class="QLabel" name="labelWordList">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>character</string>
<string>Wordlist:</string>
</property>
</widget>
</item>
Expand Down
5 changes: 3 additions & 2 deletions tests/gui/TestGui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1027,11 +1027,12 @@ void TestGui::testDicewareEntryEntropy()
// Verify entropy and strength
auto* entropyLabel = pwGeneratorWidget->findChild<QLabel*>("entropyLabel");
auto* strengthLabel = pwGeneratorWidget->findChild<QLabel*>("strengthLabel");
auto* wordLengthLabel = pwGeneratorWidget->findChild<QLabel*>("charactersInPassphraseLabel");
auto* wordLengthLabel = pwGeneratorWidget->findChild<QLabel*>("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););
Expand Down

0 comments on commit e76e9d4

Please sign in to comment.