Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion _config.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
version:
- 1.6.6
- 2.0.0

issueURL:
- "https://github.com/vt-middleware/passay/issues/"
Expand Down
8 changes: 4 additions & 4 deletions _includes/source/reference/1.java
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
PasswordValidator validator = new PasswordValidator(
PasswordValidator validator = new DefaultPasswordValidator(
// length between 8 and 16 characters
new LengthRule(8, 16),

Expand All @@ -16,7 +16,7 @@

// define some illegal sequences that will fail when >= 5 chars long
// alphabetical is of the form 'abcde', numerical is '34567', qwery is 'asdfg'
// the false parameter indicates that wrapped sequences are allowed; e.g. 'xyzabc'
// the false parameter indicates that wrapped sequences are valid; e.g. 'xyzabc'
new IllegalSequenceRule(EnglishSequenceData.Alphabetical, 5, false),
new IllegalSequenceRule(EnglishSequenceData.Numerical, 5, false),
new IllegalSequenceRule(EnglishSequenceData.USQwerty, 5, false),
Expand All @@ -25,12 +25,12 @@
new WhitespaceRule());

final char[] password = System.console().readPassword("Password: ");
RuleResult result = validator.validate(new PasswordData(new String(password)));
ValidationResult result = validator.validate(new PasswordData(new UnicodeString(password)));
if (result.isValid()) {
System.out.println("Password is valid");
} else {
System.out.println("Invalid password:");
for (String msg : validator.getMessages(result)) {
for (String msg : result.getMessages()) {
System.out.println(msg);
}
}
2 changes: 1 addition & 1 deletion _includes/source/reference/2.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Properties props = new Properties();
props.load(new FileInputStream("/path/to/passay.properties"));
MessageResolver resolver = new PropertiesMessageResolver(props);
PasswordValidator validator = new PasswordValidator(
PasswordValidator validator = new DefaultPasswordValidator(
resolver, new LengthRule(8, 16), new WhitespaceRule());
20 changes: 9 additions & 11 deletions _includes/source/reference/3.java
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
LengthRule r1 = new LengthRule(8, 16);

CharacterCharacteristicsRule r2 = new CharacterCharacteristicsRule();

// Define M (3 in this case)
r2.setNumberOfCharacteristics(3);

// Define elements of N (upper, lower, digit, symbol)
r2.getRules().add(new CharacterRule(EnglishCharacterData.UpperCase, 1));
r2.getRules().add(new CharacterRule(EnglishCharacterData.LowerCase, 1));
r2.getRules().add(new CharacterRule(EnglishCharacterData.Digit, 1));
r2.getRules().add(new CharacterRule(EnglishCharacterData.Special, 1));
CharacterCharacteristicsRule r2 = new CharacterCharacteristicsRule(
// Define M (3 in this case)
3,
// Define elements of N (upper, lower, digit, symbol)
new CharacterRule(EnglishCharacterData.UpperCase, 1),
new CharacterRule(EnglishCharacterData.LowerCase, 1),
new CharacterRule(EnglishCharacterData.Digit, 1),
new CharacterRule(EnglishCharacterData.Special, 1));

WhitespaceRule r3 = new WhitespaceRule();

PasswordValidator validator = new PasswordValidator(r1, r2, r3);
PasswordValidator validator = new DefaultPasswordValidator(r1, r2, r3);
15 changes: 7 additions & 8 deletions _includes/source/reference/5.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,19 @@
// data. A common use case for labels is multiple password encodings where each
// label identifies a particular encoding.
// Salt=86ffd2e3521b5b169ec9a75678c92eed
List<PasswordData.Reference> history = Arrays.asList(
List<Reference> history = Arrays.asList(
// Password=P@ssword1
new PasswordData.HistoricalReference(
new HistoricalReference(
"SHA256",
"j93vuQDT5ZpZ5L9FxSfeh87zznS3CM8govlLNHU8GRWG/9LjUhtbFp7Jp1Z4yS7t"),

// Password=P@ssword2
new PasswordData.HistoricalReference(
new HistoricalReference(
"SHA256",
"mhR+BHzcQXt2fOUWCy4f903AHA6LzNYKlSOQ7r9np02G/9LjUhtbFp7Jp1Z4yS7t"),

// Password=P@ssword3
new PasswordData.HistoricalReference(
new HistoricalReference(
"SHA256",
"BDr/pEo1eMmJoeP6gRKh6QMmiGAyGcddvfAHH+VJ05iG/9LjUhtbFp7Jp1Z4yS7t")
);
Expand All @@ -36,7 +36,6 @@
// ...
new DigestHistoryRule(hasher));

PasswordValidator validator = new PasswordValidator(rules);
PasswordData data = new PasswordData("username", "P@ssword1");
data.setPasswordReferences(history);
RuleResult result = validator.validate(data);
PasswordValidator validator = new DefaultPasswordValidator(rules);
PasswordData data = new PasswordData("username", "P@ssword1", history);
ValidationResult result = validator.validate(data);
4 changes: 2 additions & 2 deletions _includes/source/reference/6.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
// at least one digit character
new CharacterRule(EnglishCharacterData.Digit, 1));

PasswordGenerator generator = new PasswordGenerator();
PasswordGenerator generator = new PasswordGenerator(12, rules);

// Generated password is 12 characters long, which complies with policy
String password = generator.generatePassword(12, rules);
UnicodeString password = generator.generate();
Binary file modified _includes/source/source.zip
Binary file not shown.
28 changes: 28 additions & 0 deletions download.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,34 @@ If you would like to use this project in your maven build, include the following

## Release Notes

### Version 2.0.0 - 05Apr2026

v2 contains many API breaking changes which were introduced to support new features and improve extensibility. The following list is not comprehensive, but are likely the most impactful:

- Setters removed on many classes in favor of constructor parameters
- `PasswordValidator` is now an interface and returns `ValidationResult`
- `DefaultPasswordValidator` is the primary implementation provided by passay
- Many classes reorganized into new sub-packages
- `org.passay.data` for `CharacterData` and `SequenceData`
- `org.passay.rule` for `Rule` implementations
- `org.passay.resolver` for `MessageResolver` implementations
- `org.passay.support` for password data classes
- New maven modules to avoid the use of optional dependencies
- _passay-crypt_ for classes requiring cryptographic functions
- _passay-bloom_ for Bloom implementation and dependencies
- _passay-spring_ for classes with Spring dependencies

Issue | Description
:---- | :----------
[passay-181]({{ site.issueURL }}181) | Add retryLimit support for password generation
[passay-180]({{ site.issueURL }}180) | BufferOverflowException when generating password
[passay-177]({{ site.issueURL }}177) | Password generator improvements; Leverage both Allowed and Illegal characters
[passay-175]({{ site.issueURL }}175) | Clear password data from memory
[passay-172]({{ site.issueURL }}172) | Allow PasswordValidator to fail fast when using expensive rules
[passay-171]({{ site.issueURL }}171) | Remove RepeatCharacterRegexRule in favor of RepeatCharactersRule
[passay-169]({{ site.issueURL }}169) | Add property keys and count categories for special character variants
[passay-167]({{ site.issueURL }}167) | Character counts should use code points

### Version 1.6.6 - 14Oct2024

Issue | Description
Expand Down
15 changes: 3 additions & 12 deletions index.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,17 @@
layout: default
title: Password policy enforcement for Java
---
Passay builds on the success of [vt-password](https://code.google.com/p/vt-middleware/wiki/vtpassword) and provides
a comprehensive and extensible feature set.
Passay provides a comprehensive and extensible feature set for password validation and generation.

## Password validation
Enforce password policy by validating candidate passwords against a configurable rule set.
Passay provides a comprehensive set of rules for common cases and supports extension through a simple
[rule interface](javadocs/org/passay/Rule.html).
[rule interface](javadocs/org/passay/rule/Rule.html).

## Password generation
Generate passwords using a configurable rule set. The [password generator](javadocs/org/passay/PasswordGenerator.html)
Generate passwords using a configurable rule set. The [password generator](javadocs/org/passay/generate/PasswordGenerator.html)
is extensible like all Passay components.

## Command line tools
Automate password policy enforcement and support tooling scenarios using the command line interface.

# Using
Passay artifacts are available in Maven Central. If you would like to use this project in your maven build,
include the following in your pom.xml:
Expand All @@ -29,8 +25,3 @@ include the following in your pom.xml:
</dependency>
</dependencies>

# History
Passay is the descendant of the venerable [vt-password](https://code.google.com/p/vt-middleware/wiki/vtpassword) Java
library produced by the Middleware group at Virginia Tech. Passay builds on the lessons learned from vt-password,
which was [well-regarded](http://stackoverflow.com/questions/3200292/password-strength-checking-library) in its own
right. Passay is more convenient, more extensible, and ready for internationalization.
66 changes: 36 additions & 30 deletions reference/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ title: Reference manual
---
The Passay API consists of 3 core components:

1. [`Rule`](../javadocs/org/passay/Rule.html) - one or more rules define a password policy rule set
1. [`Rule`](../javadocs/org/passay/rule/Rule.html) - one or more rules define a password policy rule set
2. [`PasswordValidator`](../javadocs/org/passay/PasswordValidator.html) - validates a password against a rule set
3. [`PasswordGenerator`](../javadocs/org/passay/PasswordGenerator.html) - produces passwords that satisfy a given rule set
3. [`PasswordGenerator`](../javadocs/org/passay/generate/PasswordGenerator.html) - produces passwords that satisfy a given rule set

# Rule overview
Rules are the building blocks for both password validation and generation, and it is helpful to review the ruleset that
Expand All @@ -18,53 +18,51 @@ passay provides out of the box. There are two broad categories of rules:
The following sections briefly describe the available rules in both categories.

## Positive matching rules
1. [`AllowedCharacterRule`](../javadocs/org/passay/AllowedCharacterRule.html) -
1. [`AllowedCharacterRule`](../javadocs/org/passay/rule/AllowedCharacterRule.html) -
requires passwords to contain _all_ of a set of characters
2. [`AllowedRegexRule`](../javadocs/org/passay/AllowedRegexRule.html) -
2. [`AllowedRegexRule`](../javadocs/org/passay/rule/AllowedRegexRule.html) -
requires passwords to conform to a regular expression
3. [`CharacterCharacteristicsRule`](../javadocs/org/passay/CharacterCharacteristicsRule.html) -
3. [`CharacterCharacteristicsRule`](../javadocs/org/passay/rule/CharacterCharacteristicsRule.html) -
requires passwords to contain M of N classes of characters; for example, 3 of 4 of the following: digit, upper-case letters, lower-case letters, symbols
4. [`CharacterRule`](../javadocs/org/passay/CharacterRule.html) -
4. [`CharacterRule`](../javadocs/org/passay/rule/CharacterRule.html) -
requires passwords to contain at least N characters from a given character set (e.g. digits, upper-case letters, lowercase-letters, symbols)
5. [`LengthRule`](../javadocs/org/passay/LengthRule.html) - requires passwords to meet a minimum required length
6. [`LengthComplexityRule`](../javadocs/org/passay/LengthComplexityRule.html) -
5. [`LengthRule`](../javadocs/org/passay/rule/LengthRule.html) - requires passwords to meet a minimum required length
6. [`LengthComplexityRule`](../javadocs/org/passay/rule/LengthComplexityRule.html) -
requires passwords to meet a specific set of rules based on the length of the password. For example, passwords between 8-12 characters long must contain both a number and symbol. Passwords 13 characters and longer must only contain alphabetical characters

## Negative matching rules
1. Dictionary rules
1. [`DictionaryRule`](../javadocs/org/passay/DictionaryRule.html) -
1. [`DictionaryRule`](../javadocs/org/passay/rule/DictionaryRule.html) -
rejects passwords that _match_ an entry in a dictionary (exact match semantics)
2. [`DictionarySubstringRule`](../javadocs/org/passay/DictionarySubstringRule.html) -
2. [`DictionarySubstringRule`](../javadocs/org/passay/rule/DictionarySubstringRule.html) -
rejects passwords that _contain_ an entry in a dictionary (substring match semantics)
3. [`DigestDictionaryRule`](../javadocs/org/passay/DigestDictionaryRule.html) -
3. [`DigestDictionaryRule`](../javadocs/org/passay/rule/DigestDictionaryRule.html) -
rejects passwords that _match_ a digested entry in a dictionary (hash/digest comparison)
2. History rules
1. [`HistoryRule`](../javadocs/org/passay/HistoryRule.html) -
1. [`HistoryRule`](../javadocs/org/passay/rule/HistoryRule.html) -
rejects passwords that match previous passwords (cleartext comparison)
2. [`DigestHistoryRule`](../javadocs/org/passay/DigestHistoryRule.html) -
2. [`DigestHistoryRule`](../javadocs/org/passay/rule/DigestHistoryRule.html) -
rejects passwords that match previous password digests (hash/digest comparison)
3. [`CharacterOccurrencesRule`](../javadocs/org/passay/CharacterOccurrencesRule.html) -
3. [`CharacterOccurrencesRule`](../javadocs/org/passay/rule/CharacterOccurrencesRule.html) -
rejects passwords that contain too many occurances of the same character
4. [`IllegalCharacterRule`](../javadocs/org/passay/IllegalCharacterRule.html) -
4. [`IllegalCharacterRule`](../javadocs/org/passay/rule/IllegalCharacterRule.html) -
rejects passwords that contain _any_ of a set of characters
5. [`IllegalRegexRule`](../javadocs/org/passay/IllegalRegexRule.html) -
5. [`IllegalRegexRule`](../javadocs/org/passay/rule/IllegalRegexRule.html) -
rejects passwords that conform to a regular expression
6. [`IllegalSequenceRule`](../javadocs/org/passay/IllegalSequenceRule.html) -
6. [`IllegalSequenceRule`](../javadocs/org/passay/rule/IllegalSequenceRule.html) -
rejects passwords that contain a sequence of N characters (e.g. _12345_)
7. [`NumberRangeRule`](../javadocs/org/passay/NumberRangeRule.html) -
7. [`NumberRangeRule`](../javadocs/org/passay/rule/NumberRangeRule.html) -
rejects passwords that contain any number within a defined range (e.g. _1000-9999_)
8. Source rules
1. [`SourceRule`](../javadocs/org/passay/SourceRule.html) -
1. [`SourceRule`](../javadocs/org/passay/rule/SourceRule.html) -
rejects passwords that match those from another source (cleartext comparison)
2. [`DigestSourceRule`](../javadocs/org/passay/DigestSourceRule.html) -
2. [`DigestSourceRule`](../javadocs/org/passay/rule/DigestSourceRule.html) -
rejects passwords that match the digest of those from another source (hash/digest comparison)
9. [`RepeatCharacterRegexRule`](../javadocs/org/passay/RepeatCharacterRegexRule.html) -
rejects passwords that contain a repeated ASCII character
10. [`RepeatCharactersRule`](../javadocs/org/passay/RepeatCharactersRule.html) -
9. [`RepeatCharactersRule`](../javadocs/org/passay/rule/RepeatCharactersRule.html) -
rejects passwords that contain multiple sequences of repeating characters
11. [`UsernameRule`](../javadocs/org/passay/UsernameRule.html) -
10. [`UsernameRule`](../javadocs/org/passay/rule/UsernameRule.html) -
rejects passwords that contain the username of the user providing the password
12. [`WhitespaceRule`](../javadocs/org/passay/WhitespaceRule.html) -
11. [`WhitespaceRule`](../javadocs/org/passay/rule/WhitespaceRule.html) -
rejects passwords that contain whitespace characters

# Password validation
Expand All @@ -82,7 +80,7 @@ The following code excerpt constructs a validator that enforces the policy.
{% endhighlight %}

## Advanced validation: customizing messages
Passay provides the [`MessageResolver`](../javadocs/org/passay/MessageResolver.html) interface to allow arbitrary
Passay provides the [`MessageResolver`](../javadocs/org/passay/resolver/MessageResolver.html) interface to allow arbitrary
conversion of password validation results to meaningful text intended for display to users. The default mechanism
uses a message bundle to define validation messages whose default values are shown below.

Expand All @@ -108,6 +106,9 @@ uses a message bundle to define validation messages whose default values are sho
INSUFFICIENT_ALPHABETICAL=Password must contain %1$s or more alphabetical characters.
INSUFFICIENT_DIGIT=Password must contain %1$s or more digit characters.
INSUFFICIENT_SPECIAL=Password must contain %1$s or more special characters.
INSUFFICIENT_SPECIAL_ASCII=Password must contain %1$s or more special characters.
INSUFFICIENT_SPECIAL_UNICODE=Password must contain %1$s or more special characters.
INSUFFICIENT_SPECIAL_LATIN=Password must contain %1$s or more special characters.
INSUFFICIENT_CHARACTERISTICS=Password matches %1$s of %3$s character rules, but %2$s are required.
INSUFFICIENT_COMPLEXITY=Password meets %2$s complexity rules, but %3$s are required.
INSUFFICIENT_COMPLEXITY_RULES=No rules have been configured for a password of length %1$s.
Expand Down Expand Up @@ -174,7 +175,7 @@ The following rules support enforcement of unique passwords in the context of pa
1. [`HistoryRule`](../javadocs/org/passay/HistoryRule.html) - for passwords stored as cleartext (insecure, uncommon)
2. [`DigestHistoryRule`](../javadocs/org/passay/HistoryRule.html) - for passwords stored as a hash/digest

Both rules require querying a data source for historical password data, but in practice `DigestHistoryRule` is the more useful component since passwords are typically stored as a hash/digest. Digest support requires the use of message digest components provided by the [cryptacular](http://www.cryptacular.org/) crypto library, which is an optional dependency of this library. The example below demonstrates history-based validation for passwords stored in the following format:
Both rules require querying a data source for historical password data, but in practice `DigestHistoryRule` is the more useful component since passwords are typically stored as a hash/digest. Digest support requires the use of message digest components provided by the [cryptacular](http://www.cryptacular.org/) library, which is available by adding a dependency on the _passay-crypt_ maven module. The example below demonstrates history-based validation for passwords stored in the following format:

1. SHA-256 digest algorithm
2. The hash is computed by digesting two values in turn:
Expand All @@ -190,9 +191,14 @@ This is a realistic scenario for passwords stored in an LDAP directory using the
{% endhighlight %}

# Password generation
The password generation API uses a specialized ruleset consisting exclusively of `CharacterRule`, a specialization of
`Rule`, to define the requisite character classes in generated passwords. The example below demonstrates
password generation for the following policy:
The password generation API is used to create random passwords that meet an existing rule set. The `PasswordGenerator` class creates character appenders based on the supplied rule types and then validates generated passwords against those rules. The following `Rule` types are examined for generation:

1. `CharacterRule`, to define the requisite character classes in generated passwords.
2. `CharacterCharacteristicsRule`, which contains a set of `CharacterRule`.
3. `AllowedCharacterRule`, to define the set of allowed characters.
4. `IllegalCharacterRule`, to define the set of illegal characters.

The example below demonstrates password generation for the following policy:

1. Length of 8 to 16 characters
2. Must contain at least one of the following: upper case, lower case and digit
Expand Down