Skip to content

Conversation

@solardiz
Copy link
Member

@solardiz solardiz commented Dec 7, 2025

This has many changes that I worked on during two weeks. I had many different revisions (dead-end branches) of these, and I finally feel this is ready.

Most notably, this adds and integrates a default list of common passwords. Work on this uncovered many other minor issues and optimization opportunities (as well as greater need for optimization), which are also dealt with here.

Documentation is updated accordingly, except for version number bump and change log entries - this is yet to be added, maybe outside of this PR.

Move magic numbers into named macros.  No functional change.
That were awkwardly wrapped to under 80.  No functional change.
Preparation for a further change.  No functional change yet.
This was previously limited to our hard-coded character sequences, but is
now extended to any non-purely-alphabetic substrings.

The desired effect is with external wordlists containing many alternating
character class strings (e.g., keyboard walks), which we previously skipped
substring-matching passphrase-alikes against because of the limitation.
Preparation for a further change.  No functional change yet.
to avoid inconsistent rejection of strings with leetspeak where the
equivalent without leetspeak could have been accepted as a passphrase.

This amends "Always discount non-words from passphrases" such that its
effect is removed for the built-in wordlist (which only contains words),
but will remain for external wordlists containing non-words.
…ases

when the entire "passphrase" has little more than one word in leetspeak,
with digits within that word confused for word separators.

This amends "Do not discount leetspeak from passphrases" for the case when
the wordlist entry has the word written without leetspeak, but the password
has it with leetspeak.
to better reflect what's actually common, and exclude what is not.
based on testing against current JtR password.lst.
Based on review of top base words in current JtR password.lst.
and a script to (re)generate it.  With this 800-line list, we by default
do not accept anything from JtR default password.lst (1795690 entries).

Resolves: openwall#48
Specifically, include top 100k of HIBPv8 overlap with RockYou.
as an optimization, except in rare special case where further matches of
same sub-needle in same haystack could have different outcome if the other
place in haystack_original looked different and that would matter.

A test case is wordlist entry "eleet3l33t" vs. passphrase "3l33t4ab5cd",
where matching against "3l33t" isn't treated the same as against "eleet".

Wordlist entries that meaningfully exhibit this property for non-trivial
substring lengths are so rare that we could as well give up on this
exception, which would simplify and speed up processing.  Maybe later.
Stop (and proceed to next sub-needle) when the current sub-needle would no
longer fit in the rest of the haystack.  Also switch from strncmp() to
memcmp() now that we've pre-checked the length.
since it's security-sensitive and we do not zeroize the map for speed.
It initially provided good speedup (with glibc), but it no longer helps
as much on top of our new pre-check, and it risks leaving sensitive data
around in its implementation's tables.

We still have one older use of strstr() in pam_passwdqc.c, though.
as it risks leaving sensitive data around in its implementation's tables.
Use strcmp() against the randomly-generated password instead, even though
this may be slightly worse user experience.
We may discount common sequences from what would have qualified as a
passphrase, so claiming "not a passphrase" could have been confusing.
No longer require non-ASCII words to be separated specifically by spaces,
but allow any ASCII non-letters as separators.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant