password-validator-s 1.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- password_validator_s-1.0.0/LICENSE +19 -0
- password_validator_s-1.0.0/PKG-INFO +245 -0
- password_validator_s-1.0.0/README.md +197 -0
- password_validator_s-1.0.0/pyproject.toml +60 -0
- password_validator_s-1.0.0/setup.cfg +4 -0
- password_validator_s-1.0.0/setup.py +3 -0
- password_validator_s-1.0.0/src/password_validator/__init__.py +30 -0
- password_validator_s-1.0.0/src/password_validator/config/__init__.py +0 -0
- password_validator_s-1.0.0/src/password_validator/config/settings.py +135 -0
- password_validator_s-1.0.0/src/password_validator/constants.py +55 -0
- password_validator_s-1.0.0/src/password_validator/engine/__init__.py +0 -0
- password_validator_s-1.0.0/src/password_validator/engine/validator.py +168 -0
- password_validator_s-1.0.0/src/password_validator/enums.py +72 -0
- password_validator_s-1.0.0/src/password_validator/exceptions.py +50 -0
- password_validator_s-1.0.0/src/password_validator/loaders/__init__.py +10 -0
- password_validator_s-1.0.0/src/password_validator/loaders/env_loader.py +149 -0
- password_validator_s-1.0.0/src/password_validator/models.py +261 -0
- password_validator_s-1.0.0/src/password_validator/rules/__init__.py +24 -0
- password_validator_s-1.0.0/src/password_validator/rules/base.py +91 -0
- password_validator_s-1.0.0/src/password_validator/rules/digits.py +35 -0
- password_validator_s-1.0.0/src/password_validator/rules/length.py +43 -0
- password_validator_s-1.0.0/src/password_validator/rules/lowercase.py +34 -0
- password_validator_s-1.0.0/src/password_validator/rules/registry.py +81 -0
- password_validator_s-1.0.0/src/password_validator/rules/special.py +48 -0
- password_validator_s-1.0.0/src/password_validator/rules/uppercase.py +34 -0
- password_validator_s-1.0.0/src/password_validator/strength/__init__.py +8 -0
- password_validator_s-1.0.0/src/password_validator/strength/analyzer.py +101 -0
- password_validator_s-1.0.0/src/password_validator/strength/analyzers/__init__.py +55 -0
- password_validator_s-1.0.0/src/password_validator/strength/analyzers/dictionary.py +347 -0
- password_validator_s-1.0.0/src/password_validator/strength/analyzers/keyboard.py +378 -0
- password_validator_s-1.0.0/src/password_validator/strength/analyzers/repeat.py +311 -0
- password_validator_s-1.0.0/src/password_validator/strength/analyzers/sequential.py +281 -0
- password_validator_s-1.0.0/src/password_validator/strength/config.py +120 -0
- password_validator_s-1.0.0/src/password_validator/strength/scorer.py +473 -0
- password_validator_s-1.0.0/src/password_validator/strength/suggestions.py +224 -0
- password_validator_s-1.0.0/src/password_validator/strength/weights.py +65 -0
- password_validator_s-1.0.0/src/password_validator/version.py +7 -0
- password_validator_s-1.0.0/src/password_validator_s.egg-info/PKG-INFO +245 -0
- password_validator_s-1.0.0/src/password_validator_s.egg-info/SOURCES.txt +42 -0
- password_validator_s-1.0.0/src/password_validator_s.egg-info/dependency_links.txt +1 -0
- password_validator_s-1.0.0/src/password_validator_s.egg-info/requires.txt +1 -0
- password_validator_s-1.0.0/src/password_validator_s.egg-info/top_level.txt +3 -0
- password_validator_s-1.0.0/src/plugins/__init__.py +0 -0
- password_validator_s-1.0.0/src/plugins/manager.py +4 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
Copyright (c) 2026 [Md Shamimur Rahman Shuvo]
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
5
|
+
in the Software without restriction, including without limitation the rights
|
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
8
|
+
furnished to do so, subject to the following conditions:
|
|
9
|
+
|
|
10
|
+
The above copyright notice and this permission notice shall be included in all
|
|
11
|
+
copies or substantial portions of the Software.
|
|
12
|
+
|
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
19
|
+
SOFTWARE.
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: password-validator-s
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Highly configurable password validation and strength analysis package
|
|
5
|
+
Author-email: Md Shamimur Rahman Shuvo <shamimur.shuvo@gmail.com>
|
|
6
|
+
License: Copyright (c) 2026 [Md Shamimur Rahman Shuvo]
|
|
7
|
+
|
|
8
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
9
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
10
|
+
in the Software without restriction, including without limitation the rights
|
|
11
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
12
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
13
|
+
furnished to do so, subject to the following conditions:
|
|
14
|
+
|
|
15
|
+
The above copyright notice and this permission notice shall be included in all
|
|
16
|
+
copies or substantial portions of the Software.
|
|
17
|
+
|
|
18
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
19
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
20
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
21
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
22
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
23
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
24
|
+
SOFTWARE.
|
|
25
|
+
Project-URL: Homepage, https://github.com/ShamimurRahmanShuvo/password-validator
|
|
26
|
+
Project-URL: Repository, https://github.com/ShamimurRahmanShuvo/password-validator
|
|
27
|
+
Project-URL: Documentation, https://github.com/ShamimurRahmanShuvo/password-validator/wiki
|
|
28
|
+
Project-URL: Issues, https://github.com/ShamimurRahmanShuvo/password-validator/issues
|
|
29
|
+
Keywords: password,validation,security,python,authentication,validator
|
|
30
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
31
|
+
Classifier: Intended Audience :: Developers
|
|
32
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
33
|
+
Classifier: Programming Language :: Python :: 3
|
|
34
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
35
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
36
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
37
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
38
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
39
|
+
Classifier: Topic :: Security
|
|
40
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
41
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
42
|
+
Classifier: Operating System :: OS Independent
|
|
43
|
+
Requires-Python: >=3.10
|
|
44
|
+
Description-Content-Type: text/markdown
|
|
45
|
+
License-File: LICENSE
|
|
46
|
+
Requires-Dist: python-dotenv>=1.2.2
|
|
47
|
+
Dynamic: license-file
|
|
48
|
+
|
|
49
|
+
# Password Validator Pro
|
|
50
|
+
|
|
51
|
+
A configurable Python library for password policy validation and password strength analysis.
|
|
52
|
+
|
|
53
|
+
**Version:** 1.0.0
|
|
54
|
+
**Python:** 3.10+
|
|
55
|
+
**License:** MIT
|
|
56
|
+
|
|
57
|
+
## What it provides
|
|
58
|
+
|
|
59
|
+
Password Validator Pro separates two concerns:
|
|
60
|
+
|
|
61
|
+
1. **Password policy validation** — determines whether a password satisfies the configured rules.
|
|
62
|
+
2. **Password strength analysis** — analyzes password characteristics and patterns, produces a score, identifies a strength level, and generates improvement suggestions.
|
|
63
|
+
|
|
64
|
+
### Core capabilities
|
|
65
|
+
|
|
66
|
+
- Minimum and maximum password length validation
|
|
67
|
+
- Uppercase, lowercase, digit, and special-character rules
|
|
68
|
+
- Configurable special-character set
|
|
69
|
+
- Environment-based configuration through `.env` files and process environment variables
|
|
70
|
+
- Custom validation rules through the `Rule` abstraction
|
|
71
|
+
- Rule registration and removal through `RuleRegistry`
|
|
72
|
+
- Repeated-character analysis
|
|
73
|
+
- Repeated-group analysis
|
|
74
|
+
- Sequential-pattern analysis
|
|
75
|
+
- Keyboard-pattern analysis
|
|
76
|
+
- Dictionary and common-password analysis
|
|
77
|
+
- Character composition and estimated entropy metrics
|
|
78
|
+
- Configurable strength scoring weights
|
|
79
|
+
- Password-strength suggestions
|
|
80
|
+
- Structured validation and strength result objects
|
|
81
|
+
- `src/` package layout suitable for modern Python packaging
|
|
82
|
+
|
|
83
|
+
## Installation
|
|
84
|
+
|
|
85
|
+
### From PyPI
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
python -m pip install password-validator
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### From source
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
git clone https://github.com/ShamimurRahmanShuvo/password-validator.git
|
|
95
|
+
cd password-validator
|
|
96
|
+
python -m venv .venv
|
|
97
|
+
source .venv/bin/activate
|
|
98
|
+
python -m pip install -e .
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
For Windows PowerShell, activate the environment with:
|
|
102
|
+
|
|
103
|
+
```powershell
|
|
104
|
+
.venv\Scripts\Activate.ps1
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
See [`docs/installation.md`](docs/installation.md) for the complete installation and packaging guide.
|
|
108
|
+
|
|
109
|
+
## Quick start
|
|
110
|
+
|
|
111
|
+
```python
|
|
112
|
+
from password_validator import PasswordValidator
|
|
113
|
+
|
|
114
|
+
validator = PasswordValidator()
|
|
115
|
+
result = validator.validate("MySecurePassword123!")
|
|
116
|
+
|
|
117
|
+
print(result.valid)
|
|
118
|
+
print(result.passed)
|
|
119
|
+
print(result.failed)
|
|
120
|
+
print(result.errors)
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
The validator uses the package's default password policy unless a `PasswordRuleConfig` is supplied.
|
|
124
|
+
|
|
125
|
+
## Configure the password policy
|
|
126
|
+
|
|
127
|
+
```python
|
|
128
|
+
from password_validator import PasswordValidator
|
|
129
|
+
from password_validator.config.settings import PasswordRuleConfig
|
|
130
|
+
|
|
131
|
+
config = PasswordRuleConfig(
|
|
132
|
+
min_length=12,
|
|
133
|
+
max_length=64,
|
|
134
|
+
require_uppercase=True,
|
|
135
|
+
require_lowercase=True,
|
|
136
|
+
require_digit=True,
|
|
137
|
+
require_special=True,
|
|
138
|
+
special_characters="!@#$%^&*()-_=+[]{}|;:'\",.<>?/`~",
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
validator = PasswordValidator(config=config)
|
|
142
|
+
result = validator.validate("MySecurePassword123!")
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
The package also supports environment-driven configuration. See [`docs/configuration.md`](docs/configuration.md).
|
|
146
|
+
|
|
147
|
+
## Password strength scoring
|
|
148
|
+
|
|
149
|
+
```python
|
|
150
|
+
from password_validator import PasswordStrengthScorer
|
|
151
|
+
|
|
152
|
+
scorer = PasswordStrengthScorer()
|
|
153
|
+
result = scorer.score("MySecurePassword123!")
|
|
154
|
+
|
|
155
|
+
print(result.score)
|
|
156
|
+
print(result.level)
|
|
157
|
+
print(result.metrics)
|
|
158
|
+
print(result.suggestion_message)
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Strength scoring is independent of policy validation. A password can be policy-valid while still receiving a relatively low strength score, or vice versa.
|
|
162
|
+
|
|
163
|
+
See [`docs/strength-analysis.md`](docs/strength-analysis.md).
|
|
164
|
+
|
|
165
|
+
## Custom validation rules
|
|
166
|
+
|
|
167
|
+
Rules implement the `Rule` interface and return a `RuleResult`.
|
|
168
|
+
|
|
169
|
+
```python
|
|
170
|
+
from password_validator.rules.base import Rule, RuleResult
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
class NoUsernameRule(Rule):
|
|
174
|
+
name = "no_username"
|
|
175
|
+
|
|
176
|
+
def __init__(self, username: str):
|
|
177
|
+
self.username = username
|
|
178
|
+
|
|
179
|
+
def validate(self, password: str) -> RuleResult:
|
|
180
|
+
if self.username.lower() in password.lower():
|
|
181
|
+
return self._failed(
|
|
182
|
+
message="Password must not contain the username",
|
|
183
|
+
code="USERNAME_IN_PASSWORD",
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
return self._passed(message="Password does not contain the username")
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
You can pass custom rules directly to `PasswordValidator`:
|
|
190
|
+
|
|
191
|
+
```python
|
|
192
|
+
validator = PasswordValidator(rules=[NoUsernameRule("shuvo")])
|
|
193
|
+
result = validator.validate("MySecurePassword123!")
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
See [`docs/rules.md`](docs/rules.md) and [`docs/plugins.md`](docs/plugins.md).
|
|
197
|
+
|
|
198
|
+
## Documentation
|
|
199
|
+
|
|
200
|
+
- [`Installation`](docs/installation.md) — install, verify, development setup, testing, and packaging
|
|
201
|
+
- [`Configuration`](docs/configuration.md) — policy and strength configuration
|
|
202
|
+
- [`Rules`](docs/rules.md) — built-in rules and custom rule development
|
|
203
|
+
- [`Plugins and extensions`](docs/plugins.md) — extension model and integration guidance
|
|
204
|
+
- [`Validation`](docs/validation.md) — validation API and result objects
|
|
205
|
+
- [`Strength analysis`](docs/strength-analysis.md) — analyzers, scoring, metrics, and suggestions
|
|
206
|
+
- [`Architecture`](docs/architecture.md) — package design and responsibilities
|
|
207
|
+
- [`Testing`](docs/testing.md) — unit/integration testing and coverage
|
|
208
|
+
- [`Security`](docs/security.md) — secure usage and operational guidance
|
|
209
|
+
- [`Troubleshooting`](docs/troubleshooting.md) — common installation and development problems
|
|
210
|
+
- [`Contributing`](docs/contributing.md) — development workflow and contribution expectations
|
|
211
|
+
|
|
212
|
+
## Project layout
|
|
213
|
+
|
|
214
|
+
```text
|
|
215
|
+
password-validator/
|
|
216
|
+
├── config/
|
|
217
|
+
│ └── .env.example
|
|
218
|
+
├── docs/
|
|
219
|
+
├── examples/
|
|
220
|
+
├── src/
|
|
221
|
+
│ ├── password_validator/
|
|
222
|
+
│ │ ├── config/
|
|
223
|
+
│ │ ├── engine/
|
|
224
|
+
│ │ ├── loaders/
|
|
225
|
+
│ │ ├── rules/
|
|
226
|
+
│ │ ├── strength/
|
|
227
|
+
│ │ ├── constants.py
|
|
228
|
+
│ │ ├── enums.py
|
|
229
|
+
│ │ ├── exceptions.py
|
|
230
|
+
│ │ ├── models.py
|
|
231
|
+
│ │ └── version.py
|
|
232
|
+
│ └── plugins/
|
|
233
|
+
├── tests/
|
|
234
|
+
├── pyproject.toml
|
|
235
|
+
├── requirements-dev.txt
|
|
236
|
+
└── README.md
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
## Important security note
|
|
240
|
+
|
|
241
|
+
This library validates and analyzes passwords; it is **not a password storage system**. Never store plaintext passwords or log them. Application code should hash passwords using an appropriate password-hashing mechanism and should avoid placing credentials in exception messages, telemetry, traces, or request logs.
|
|
242
|
+
|
|
243
|
+
## License
|
|
244
|
+
|
|
245
|
+
MIT. See [`LICENSE`](LICENSE).
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
# Password Validator Pro
|
|
2
|
+
|
|
3
|
+
A configurable Python library for password policy validation and password strength analysis.
|
|
4
|
+
|
|
5
|
+
**Version:** 1.0.0
|
|
6
|
+
**Python:** 3.10+
|
|
7
|
+
**License:** MIT
|
|
8
|
+
|
|
9
|
+
## What it provides
|
|
10
|
+
|
|
11
|
+
Password Validator Pro separates two concerns:
|
|
12
|
+
|
|
13
|
+
1. **Password policy validation** — determines whether a password satisfies the configured rules.
|
|
14
|
+
2. **Password strength analysis** — analyzes password characteristics and patterns, produces a score, identifies a strength level, and generates improvement suggestions.
|
|
15
|
+
|
|
16
|
+
### Core capabilities
|
|
17
|
+
|
|
18
|
+
- Minimum and maximum password length validation
|
|
19
|
+
- Uppercase, lowercase, digit, and special-character rules
|
|
20
|
+
- Configurable special-character set
|
|
21
|
+
- Environment-based configuration through `.env` files and process environment variables
|
|
22
|
+
- Custom validation rules through the `Rule` abstraction
|
|
23
|
+
- Rule registration and removal through `RuleRegistry`
|
|
24
|
+
- Repeated-character analysis
|
|
25
|
+
- Repeated-group analysis
|
|
26
|
+
- Sequential-pattern analysis
|
|
27
|
+
- Keyboard-pattern analysis
|
|
28
|
+
- Dictionary and common-password analysis
|
|
29
|
+
- Character composition and estimated entropy metrics
|
|
30
|
+
- Configurable strength scoring weights
|
|
31
|
+
- Password-strength suggestions
|
|
32
|
+
- Structured validation and strength result objects
|
|
33
|
+
- `src/` package layout suitable for modern Python packaging
|
|
34
|
+
|
|
35
|
+
## Installation
|
|
36
|
+
|
|
37
|
+
### From PyPI
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
python -m pip install password-validator
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### From source
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
git clone https://github.com/ShamimurRahmanShuvo/password-validator.git
|
|
47
|
+
cd password-validator
|
|
48
|
+
python -m venv .venv
|
|
49
|
+
source .venv/bin/activate
|
|
50
|
+
python -m pip install -e .
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
For Windows PowerShell, activate the environment with:
|
|
54
|
+
|
|
55
|
+
```powershell
|
|
56
|
+
.venv\Scripts\Activate.ps1
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
See [`docs/installation.md`](docs/installation.md) for the complete installation and packaging guide.
|
|
60
|
+
|
|
61
|
+
## Quick start
|
|
62
|
+
|
|
63
|
+
```python
|
|
64
|
+
from password_validator import PasswordValidator
|
|
65
|
+
|
|
66
|
+
validator = PasswordValidator()
|
|
67
|
+
result = validator.validate("MySecurePassword123!")
|
|
68
|
+
|
|
69
|
+
print(result.valid)
|
|
70
|
+
print(result.passed)
|
|
71
|
+
print(result.failed)
|
|
72
|
+
print(result.errors)
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
The validator uses the package's default password policy unless a `PasswordRuleConfig` is supplied.
|
|
76
|
+
|
|
77
|
+
## Configure the password policy
|
|
78
|
+
|
|
79
|
+
```python
|
|
80
|
+
from password_validator import PasswordValidator
|
|
81
|
+
from password_validator.config.settings import PasswordRuleConfig
|
|
82
|
+
|
|
83
|
+
config = PasswordRuleConfig(
|
|
84
|
+
min_length=12,
|
|
85
|
+
max_length=64,
|
|
86
|
+
require_uppercase=True,
|
|
87
|
+
require_lowercase=True,
|
|
88
|
+
require_digit=True,
|
|
89
|
+
require_special=True,
|
|
90
|
+
special_characters="!@#$%^&*()-_=+[]{}|;:'\",.<>?/`~",
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
validator = PasswordValidator(config=config)
|
|
94
|
+
result = validator.validate("MySecurePassword123!")
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
The package also supports environment-driven configuration. See [`docs/configuration.md`](docs/configuration.md).
|
|
98
|
+
|
|
99
|
+
## Password strength scoring
|
|
100
|
+
|
|
101
|
+
```python
|
|
102
|
+
from password_validator import PasswordStrengthScorer
|
|
103
|
+
|
|
104
|
+
scorer = PasswordStrengthScorer()
|
|
105
|
+
result = scorer.score("MySecurePassword123!")
|
|
106
|
+
|
|
107
|
+
print(result.score)
|
|
108
|
+
print(result.level)
|
|
109
|
+
print(result.metrics)
|
|
110
|
+
print(result.suggestion_message)
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Strength scoring is independent of policy validation. A password can be policy-valid while still receiving a relatively low strength score, or vice versa.
|
|
114
|
+
|
|
115
|
+
See [`docs/strength-analysis.md`](docs/strength-analysis.md).
|
|
116
|
+
|
|
117
|
+
## Custom validation rules
|
|
118
|
+
|
|
119
|
+
Rules implement the `Rule` interface and return a `RuleResult`.
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
from password_validator.rules.base import Rule, RuleResult
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
class NoUsernameRule(Rule):
|
|
126
|
+
name = "no_username"
|
|
127
|
+
|
|
128
|
+
def __init__(self, username: str):
|
|
129
|
+
self.username = username
|
|
130
|
+
|
|
131
|
+
def validate(self, password: str) -> RuleResult:
|
|
132
|
+
if self.username.lower() in password.lower():
|
|
133
|
+
return self._failed(
|
|
134
|
+
message="Password must not contain the username",
|
|
135
|
+
code="USERNAME_IN_PASSWORD",
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
return self._passed(message="Password does not contain the username")
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
You can pass custom rules directly to `PasswordValidator`:
|
|
142
|
+
|
|
143
|
+
```python
|
|
144
|
+
validator = PasswordValidator(rules=[NoUsernameRule("shuvo")])
|
|
145
|
+
result = validator.validate("MySecurePassword123!")
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
See [`docs/rules.md`](docs/rules.md) and [`docs/plugins.md`](docs/plugins.md).
|
|
149
|
+
|
|
150
|
+
## Documentation
|
|
151
|
+
|
|
152
|
+
- [`Installation`](docs/installation.md) — install, verify, development setup, testing, and packaging
|
|
153
|
+
- [`Configuration`](docs/configuration.md) — policy and strength configuration
|
|
154
|
+
- [`Rules`](docs/rules.md) — built-in rules and custom rule development
|
|
155
|
+
- [`Plugins and extensions`](docs/plugins.md) — extension model and integration guidance
|
|
156
|
+
- [`Validation`](docs/validation.md) — validation API and result objects
|
|
157
|
+
- [`Strength analysis`](docs/strength-analysis.md) — analyzers, scoring, metrics, and suggestions
|
|
158
|
+
- [`Architecture`](docs/architecture.md) — package design and responsibilities
|
|
159
|
+
- [`Testing`](docs/testing.md) — unit/integration testing and coverage
|
|
160
|
+
- [`Security`](docs/security.md) — secure usage and operational guidance
|
|
161
|
+
- [`Troubleshooting`](docs/troubleshooting.md) — common installation and development problems
|
|
162
|
+
- [`Contributing`](docs/contributing.md) — development workflow and contribution expectations
|
|
163
|
+
|
|
164
|
+
## Project layout
|
|
165
|
+
|
|
166
|
+
```text
|
|
167
|
+
password-validator/
|
|
168
|
+
├── config/
|
|
169
|
+
│ └── .env.example
|
|
170
|
+
├── docs/
|
|
171
|
+
├── examples/
|
|
172
|
+
├── src/
|
|
173
|
+
│ ├── password_validator/
|
|
174
|
+
│ │ ├── config/
|
|
175
|
+
│ │ ├── engine/
|
|
176
|
+
│ │ ├── loaders/
|
|
177
|
+
│ │ ├── rules/
|
|
178
|
+
│ │ ├── strength/
|
|
179
|
+
│ │ ├── constants.py
|
|
180
|
+
│ │ ├── enums.py
|
|
181
|
+
│ │ ├── exceptions.py
|
|
182
|
+
│ │ ├── models.py
|
|
183
|
+
│ │ └── version.py
|
|
184
|
+
│ └── plugins/
|
|
185
|
+
├── tests/
|
|
186
|
+
├── pyproject.toml
|
|
187
|
+
├── requirements-dev.txt
|
|
188
|
+
└── README.md
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
## Important security note
|
|
192
|
+
|
|
193
|
+
This library validates and analyzes passwords; it is **not a password storage system**. Never store plaintext passwords or log them. Application code should hash passwords using an appropriate password-hashing mechanism and should avoid placing credentials in exception messages, telemetry, traces, or request logs.
|
|
194
|
+
|
|
195
|
+
## License
|
|
196
|
+
|
|
197
|
+
MIT. See [`LICENSE`](LICENSE).
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = [
|
|
3
|
+
"setuptools>=68.0",
|
|
4
|
+
"wheel"
|
|
5
|
+
]
|
|
6
|
+
build-backend = "setuptools.build_meta"
|
|
7
|
+
|
|
8
|
+
[project]
|
|
9
|
+
name = "password-validator-s"
|
|
10
|
+
version = "1.0.0"
|
|
11
|
+
description = "Highly configurable password validation and strength analysis package"
|
|
12
|
+
readme = "README.md"
|
|
13
|
+
license = { file= "LICENSE" }
|
|
14
|
+
|
|
15
|
+
authors = [
|
|
16
|
+
{ name = "Md Shamimur Rahman Shuvo", email = "shamimur.shuvo@gmail.com" }
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
keywords = [
|
|
20
|
+
"password",
|
|
21
|
+
"validation",
|
|
22
|
+
"security",
|
|
23
|
+
"python",
|
|
24
|
+
"authentication",
|
|
25
|
+
"validator"
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
classifiers = [
|
|
29
|
+
"Development Status :: 5 - Production/Stable",
|
|
30
|
+
"Intended Audience :: Developers",
|
|
31
|
+
"License :: OSI Approved :: MIT License",
|
|
32
|
+
"Programming Language :: Python :: 3",
|
|
33
|
+
"Programming Language :: Python :: 3.10",
|
|
34
|
+
"Programming Language :: Python :: 3.11",
|
|
35
|
+
"Programming Language :: Python :: 3.12",
|
|
36
|
+
"Programming Language :: Python :: 3.13",
|
|
37
|
+
"Programming Language :: Python :: 3.14",
|
|
38
|
+
"Topic :: Security",
|
|
39
|
+
"Topic :: Software Development :: Libraries",
|
|
40
|
+
"License :: OSI Approved :: MIT License",
|
|
41
|
+
"Operating System :: OS Independent"
|
|
42
|
+
]
|
|
43
|
+
|
|
44
|
+
requires-python = ">=3.10"
|
|
45
|
+
|
|
46
|
+
dependencies = [
|
|
47
|
+
"python-dotenv>=1.2.2"
|
|
48
|
+
]
|
|
49
|
+
|
|
50
|
+
[project.urls]
|
|
51
|
+
Homepage = "https://github.com/ShamimurRahmanShuvo/password-validator"
|
|
52
|
+
Repository = "https://github.com/ShamimurRahmanShuvo/password-validator"
|
|
53
|
+
Documentation = "https://github.com/ShamimurRahmanShuvo/password-validator/wiki"
|
|
54
|
+
Issues = "https://github.com/ShamimurRahmanShuvo/password-validator/issues"
|
|
55
|
+
|
|
56
|
+
[tool.setuptools]
|
|
57
|
+
package-dir = {"" = "src"}
|
|
58
|
+
|
|
59
|
+
[tool.setuptools.packages.find]
|
|
60
|
+
where = ["src"]
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Entry point for the password_validator package.
|
|
3
|
+
A configurable password validation library that allows users to define custom rules and
|
|
4
|
+
criteria for password strength and security.
|
|
5
|
+
"""
|
|
6
|
+
from .version import (
|
|
7
|
+
__title__,
|
|
8
|
+
__version__,
|
|
9
|
+
__author__,
|
|
10
|
+
__description__
|
|
11
|
+
)
|
|
12
|
+
from .engine.validator import PasswordValidator, ValidationResult
|
|
13
|
+
from .strength.scorer import PasswordStrengthScorer
|
|
14
|
+
|
|
15
|
+
# Package metadata
|
|
16
|
+
VERSION = __version__
|
|
17
|
+
|
|
18
|
+
__all__ = [
|
|
19
|
+
# Package Metadata
|
|
20
|
+
"__version__",
|
|
21
|
+
"__title__",
|
|
22
|
+
"__author__",
|
|
23
|
+
"__description__",
|
|
24
|
+
"VERSION",
|
|
25
|
+
|
|
26
|
+
# Main API
|
|
27
|
+
"PasswordValidator",
|
|
28
|
+
"ValidationResult",
|
|
29
|
+
"PasswordStrengthScorer",
|
|
30
|
+
]
|
|
File without changes
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Application-level configuration for password-validator.
|
|
3
|
+
This module provides the top-level package configuration.
|
|
4
|
+
Strength-specific configuration is maintained separately in:
|
|
5
|
+
password_validator.strength.config.StrengthConfig
|
|
6
|
+
Password policy configuration is maintained here and can be
|
|
7
|
+
loaded from environment variables.
|
|
8
|
+
"""
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
from dataclasses import dataclass
|
|
11
|
+
|
|
12
|
+
from ..loaders.env_loader import EnvLoader
|
|
13
|
+
from ..strength.config import StrengthConfig
|
|
14
|
+
from password_validator.constants import *
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@dataclass(frozen=True, slots=True)
|
|
18
|
+
class PasswordRuleConfig:
|
|
19
|
+
"""
|
|
20
|
+
Configuration for password policy rules.
|
|
21
|
+
These settings determine whether a password satisfies the configured password policy.
|
|
22
|
+
This is separate from password strength scoring.
|
|
23
|
+
"""
|
|
24
|
+
min_length: int = 8
|
|
25
|
+
max_length: int = 128
|
|
26
|
+
|
|
27
|
+
require_uppercase: bool = True
|
|
28
|
+
require_lowercase: bool =True
|
|
29
|
+
require_digit: bool =True
|
|
30
|
+
require_special: bool = True
|
|
31
|
+
special_characters: str = "!@#$%^&*()-_=[]{}|/:;'<>?"
|
|
32
|
+
|
|
33
|
+
"""
|
|
34
|
+
require_whitespace: bool
|
|
35
|
+
min_uppercase: int
|
|
36
|
+
min_lowercase: int
|
|
37
|
+
min_digit: int
|
|
38
|
+
min_special: int
|
|
39
|
+
|
|
40
|
+
allowed_special: str
|
|
41
|
+
allow_spaces: bool
|
|
42
|
+
|
|
43
|
+
max_repeat: int
|
|
44
|
+
check_sequential: bool
|
|
45
|
+
check_common_passwords: bool
|
|
46
|
+
check_dictionary: bool
|
|
47
|
+
|
|
48
|
+
custom_regex: str | None
|
|
49
|
+
min_entropy: int
|
|
50
|
+
language: str
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
@classmethod
|
|
54
|
+
def from_env(cls, env: EnvLoader) -> "PasswordRuleConfig":
|
|
55
|
+
"""
|
|
56
|
+
Loads the password policy configuration from EnvLoader.
|
|
57
|
+
:param env: .env file. Defaults to ".env".
|
|
58
|
+
:return: password policy object
|
|
59
|
+
"""
|
|
60
|
+
|
|
61
|
+
return cls(
|
|
62
|
+
min_length=env.get_int("PASSWORD_MIN_LENGTH", DEFAULT_MIN_LENGTH),
|
|
63
|
+
max_length=env.get_int("PASSWORD_MAX_LENGTH", DEFAULT_MAX_LENGTH),
|
|
64
|
+
|
|
65
|
+
require_uppercase=env.get_bool("PASSWORD_REQUIRE_UPPERCASE", DEFAULT_REQUIRE_UPPERCASE),
|
|
66
|
+
require_lowercase=env.get_bool("PASSWORD_REQUIRE_LOWERCASE", DEFAULT_REQUIRE_LOWERCASE),
|
|
67
|
+
require_digit=env.get_bool("PASSWORD_REQUIRE_DIGIT", DEFAULT_REQUIRE_DIGIT),
|
|
68
|
+
require_special=env.get_bool("PASSWORD_REQUIRE_SPECIAL", DEFAULT_REQUIRE_SPECIAL),
|
|
69
|
+
special_characters=env.get("PASSWORD_SPECIAL_CHARACTERS", DEFAULT_SPECIAL_CHARACTERS)
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
def validate(self) -> None:
|
|
73
|
+
"""
|
|
74
|
+
Validate the configuration itself.
|
|
75
|
+
Raises:
|
|
76
|
+
ValueError: If the configuration is invalid.
|
|
77
|
+
:return:
|
|
78
|
+
"""
|
|
79
|
+
if self.min_length < 1:
|
|
80
|
+
raise ValueError("PASSWORD_MIN_LENGTH must be greater than 0")
|
|
81
|
+
|
|
82
|
+
if self.max_length < self.min_length:
|
|
83
|
+
raise ValueError("PASSWORD_MAX_LENGTH must be greater than or equal to PASSWORD_MIN_LENGTH")
|
|
84
|
+
|
|
85
|
+
if self.require_special and not self.special_characters:
|
|
86
|
+
raise ValueError("PASSWORD_SPECIAL_CHARACTERS cannot be empty when PASSWORD_REQUIRE_SPECIAL=true")
|
|
87
|
+
|
|
88
|
+
@classmethod
|
|
89
|
+
def defaults(cls) -> "PasswordRuleConfig":
|
|
90
|
+
"""
|
|
91
|
+
Return the package defaults.
|
|
92
|
+
Useful for applications that don't use .env.
|
|
93
|
+
:return:
|
|
94
|
+
"""
|
|
95
|
+
return cls()
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
@dataclass(slots=True, frozen=True)
|
|
99
|
+
class Settings:
|
|
100
|
+
"""
|
|
101
|
+
Root configuration object for the password-validator package.
|
|
102
|
+
This object is the main configuration boundary for the package.
|
|
103
|
+
|
|
104
|
+
Environment variables are loaded once and converted into typed configuration objects.
|
|
105
|
+
"""
|
|
106
|
+
rules: PasswordRuleConfig
|
|
107
|
+
strength: StrengthConfig
|
|
108
|
+
|
|
109
|
+
@classmethod
|
|
110
|
+
def from_env(cls, env_file: str = ".env") -> "Settings":
|
|
111
|
+
"""
|
|
112
|
+
Build application settings from environment file.
|
|
113
|
+
:param env_file: Path to the .env file
|
|
114
|
+
:return: Fully initialized settings object
|
|
115
|
+
"""
|
|
116
|
+
env = EnvLoader(env_file)
|
|
117
|
+
rules = PasswordRuleConfig.from_env(env)
|
|
118
|
+
rules.validate()
|
|
119
|
+
strength = StrengthConfig.from_env(env_file)
|
|
120
|
+
|
|
121
|
+
return cls(rules=rules, strength=strength)
|
|
122
|
+
|
|
123
|
+
@classmethod
|
|
124
|
+
def defaults(cls) -> "Settings":
|
|
125
|
+
"""
|
|
126
|
+
Return package defaults without reading an environment file
|
|
127
|
+
:return:
|
|
128
|
+
"""
|
|
129
|
+
rules = PasswordRuleConfig()
|
|
130
|
+
rules.validate()
|
|
131
|
+
|
|
132
|
+
return cls(
|
|
133
|
+
rules=rules,
|
|
134
|
+
strength=StrengthConfig.defaults()
|
|
135
|
+
)
|