Skip to content

Commit dad0a98

Browse files
committed
Add guide page
1 parent 6cbf445 commit dad0a98

File tree

2 files changed

+110
-0
lines changed

2 files changed

+110
-0
lines changed

docs/guide.md

+105
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
# Guide
2+
3+
This will guide you through the basic features of `pwdlib`.
4+
5+
## Password hashing
6+
7+
To manage password hashes, `pwdlib` exposes the [`PasswordHash`](./reference/pwdlib.md#pwdlib.PasswordHash) class. The difference with a "plain" hash algorithm helper is that it supports **multiple algorithms**. Why it's useful?
8+
9+
Currently, the safest and recommended algorithm for password hashing is [Argon2](https://en.wikipedia.org/wiki/Argon2). But it's probable that in the coming years, a new and even safer algorithm emerges. Thanks to a wrapper like [`PasswordHash`](./reference/pwdlib.md#pwdlib.PasswordHash), we'll be able to verify hash generated with the older algorithm while upgrading them to the newer one.
10+
11+
This is how you create an instance of [`PasswordHash`](./reference/pwdlib.md#pwdlib.PasswordHash) with Argon2 and Bcrypt support:
12+
13+
```py
14+
from pwdlib import PasswordHash, exceptions
15+
from pwdlib.hashers.argon2 import Argon2Hasher
16+
from pwdlib.hashers.bcrypt import BcryptHasher
17+
18+
password_hash = PasswordHash((
19+
Argon2Hasher(),
20+
BcryptHasher(),
21+
))
22+
```
23+
24+
[`PasswordHash`](./reference/pwdlib.md#pwdlib.PasswordHash) expects a tuple (or list) of hashing algorithms.
25+
26+
!!! warning "The corresponding dependencies must be installed"
27+
28+
Hashing algorithms are available through third-party implementations. Therefore, you should install the extra for all the algorithms you want to use.
29+
30+
**For Argon2**
31+
32+
```sh
33+
pip install 'pwdlib[argon2]'
34+
```
35+
36+
**For Bcrypt**
37+
38+
```sh
39+
pip install 'pwdlib[bcrypt]'
40+
```
41+
42+
**Both!**
43+
44+
```sh
45+
pip install 'pwdlib[argon2,bcrypt]'
46+
```
47+
48+
The **first** algorithm in the list is considered the **current algorithm**. New and updated hashes will use this algorithm.
49+
50+
!!! tip "I don't know what to choose!"
51+
52+
If you start a new application, you can instantiate [`PasswordHash`](./reference/pwdlib.md#pwdlib.PasswordHash) using the [`recommended`](./reference/pwdlib.md#pwdlib.PasswordHash.recommended) class method. It'll use the Argon2 algorithm under the hood.
53+
54+
```py
55+
password_hash = PasswordHash.recommended()
56+
```
57+
58+
### Hash a password
59+
60+
Once you have a [`PasswordHash`](./reference/pwdlib.md#pwdlib.PasswordHash) instance, you can [`hash`](./reference/pwdlib.md#pwdlib.PasswordHash.hash) a user's password:
61+
62+
```py
63+
hash = password_hash.hash("herminetincture")
64+
```
65+
66+
The resulting string is a hash generated from the **current algorithm**, which you can safely store in your database.
67+
68+
!!! question "Where is the salt?"
69+
70+
If you know about password hashing algorithms, you probably know that *salting* the password is an important security feature. Back in the days, it was common to store the salt separately from the hash. Nowadays, most algorithms have a specific structure allowing them to store algorithm parameters and salt along with the hash in one string.
71+
72+
For example, here is an Argon2 hash:
73+
74+
```
75+
$argon2id$v=19$m=65536,t=3,p=4$ugY9gvgMUycvF7hrnoi8oQ$uqcZOh96YysaG+s3A+RcZIccgaiQsynxfBlqUNxeRT4
76+
```
77+
78+
### Verify a password
79+
80+
When you want to verify a password corresponds to a hash, use the [`verify`](./reference/pwdlib.md#pwdlib.PasswordHash.verify) method:
81+
82+
```py
83+
valid = password_hash.verify(hash, "herminetincture")
84+
```
85+
86+
Under the hood, it'll check against all the enabled algorithms. It means that if older users still have a hash with a legacy algorithm, we'll still be able to verify it.
87+
88+
The resulting boolean indicates you if the hash corresponds to this password or not.
89+
90+
However, in most cases, you probably want to use the method we describe below.
91+
92+
### Verify and update a password
93+
94+
As we said, [`verify`](./reference/pwdlib.md#pwdlib.PasswordHash.verify) checks the hash against all the enabled algorithms. However, it's generally a good idea to take this chance to update the hash to the more secure current algorithm.
95+
96+
This is the purpose of the [`verify_and_update`](./reference/pwdlib.md#pwdlib.PasswordHash.verify_and_update) method: it verifies the password against a hash and, if it's valid and using an outdated algorithm, will hash it again using the current algorithm.
97+
98+
99+
```py
100+
valid, updated_hash = password_hash.verify_and_update(hash, "herminetincture")
101+
```
102+
103+
If the hash needs to be updated, `updated_hash` will be a string. Otherwise, it's `None`. Then, don't forget to update it in your database.
104+
105+
It's worth to note that the hash is also upgraded if the **settings of the algorithm** has been changed, like the time or memory cost.

mkdocs.yml

+5
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ theme:
3232
toggle:
3333
icon: material/brightness-4
3434
name: Switch to light mode
35+
features:
36+
- content.code.copy
3537

3638
markdown_extensions:
3739
- toc:
@@ -43,9 +45,11 @@ markdown_extensions:
4345
- pymdownx.inlinehilite
4446
- pymdownx.snippets
4547
- pymdownx.superfences
48+
- admonition
4649

4750
plugins:
4851
- search
52+
- autorefs
4953
- mkdocstrings:
5054
handlers:
5155
python:
@@ -60,6 +64,7 @@ watch:
6064

6165
nav:
6266
- About: index.md
67+
- Guide: guide.md
6368
- Reference:
6469
- pwdlib: reference/pwdlib.md
6570
- pwdlib.exceptions: reference/pwdlib.exceptions.md

0 commit comments

Comments
 (0)