0
# Password Hashing
1
2
High-level password hashing interface with the PasswordHasher class, designed for typical password storage and verification use cases with secure defaults.
3
4
## Capabilities
5
6
### PasswordHasher Class
7
8
High-level class for password hashing with sensible defaults. Uses Argon2id by default and generates random salts automatically. Designed for convenience while maintaining security best practices.
9
10
```python { .api }
11
class PasswordHasher:
12
"""
13
High level class to hash passwords with sensible defaults.
14
15
Uses Argon2id by default and uses a random salt for hashing. Can verify
16
any type of Argon2 as long as the hash is correctly encoded.
17
"""
18
19
def __init__(
20
self,
21
time_cost: int = DEFAULT_TIME_COST,
22
memory_cost: int = DEFAULT_MEMORY_COST,
23
parallelism: int = DEFAULT_PARALLELISM,
24
hash_len: int = DEFAULT_HASH_LENGTH,
25
salt_len: int = DEFAULT_RANDOM_SALT_LENGTH,
26
encoding: str = "utf-8",
27
type: Type = Type.ID,
28
):
29
"""
30
Initialize PasswordHasher with specified parameters.
31
32
Args:
33
time_cost: Number of iterations (computation time)
34
memory_cost: Memory usage in kibibytes
35
parallelism: Number of parallel threads
36
hash_len: Length of hash in bytes
37
salt_len: Length of random salt in bytes
38
encoding: Text encoding for string passwords
39
type: Argon2 variant to use
40
"""
41
```
42
43
#### Usage Example
44
45
```python
46
from argon2 import PasswordHasher
47
48
# Use default parameters (recommended for most applications)
49
ph = PasswordHasher()
50
51
# Or customize for specific security requirements
52
ph_custom = PasswordHasher(
53
time_cost=4, # More iterations for higher security
54
memory_cost=131072, # 128 MiB memory usage
55
parallelism=2, # Fewer threads for limited environments
56
hash_len=64, # Longer hash output
57
)
58
```
59
60
### Password Hashing
61
62
Hash passwords with automatic salt generation and configurable parameters.
63
64
```python { .api }
65
def hash(self, password: str | bytes, *, salt: bytes | None = None) -> str:
66
"""
67
Hash password and return an encoded hash.
68
69
Args:
70
password: Password to hash (str or bytes)
71
salt: Optional salt bytes. If None, random salt is generated.
72
WARNING: Only provide salt if you know what you're doing.
73
74
Returns:
75
Encoded Argon2 hash string
76
77
Raises:
78
argon2.exceptions.HashingError: If hashing fails
79
"""
80
```
81
82
#### Usage Example
83
84
```python
85
from argon2 import PasswordHasher
86
87
ph = PasswordHasher()
88
89
# Hash a password (recommended - automatic salt generation)
90
password = "my_secure_password"
91
hash_string = ph.hash(password)
92
print(hash_string)
93
# Output: $argon2id$v=19$m=65536,t=3,p=4$base64salt$base64hash
94
95
# Hash with custom salt (advanced usage)
96
import os
97
custom_salt = os.urandom(16)
98
hash_with_salt = ph.hash(password, salt=custom_salt)
99
```
100
101
### Password Verification
102
103
Verify passwords against stored hashes with constant-time comparison to prevent timing attacks.
104
105
```python { .api }
106
def verify(self, hash: str | bytes, password: str | bytes) -> Literal[True]:
107
"""
108
Verify that password matches hash.
109
110
Args:
111
hash: Encoded hash string (from hash() method)
112
password: Password to verify
113
114
Returns:
115
True if password matches hash
116
117
Raises:
118
argon2.exceptions.VerifyMismatchError: Password doesn't match
119
argon2.exceptions.VerificationError: Verification failed for other reasons
120
argon2.exceptions.InvalidHashError: Hash format is invalid
121
"""
122
```
123
124
#### Usage Example
125
126
```python
127
from argon2 import PasswordHasher
128
from argon2.exceptions import VerifyMismatchError
129
130
ph = PasswordHasher()
131
132
# Store this hash in your database
133
stored_hash = ph.hash("user_password")
134
135
# Later, during login verification
136
try:
137
ph.verify(stored_hash, "user_password")
138
print("Login successful!")
139
except VerifyMismatchError:
140
print("Invalid password!")
141
```
142
143
### Rehash Detection
144
145
Check if stored hashes need to be updated due to changed security parameters.
146
147
```python { .api }
148
def check_needs_rehash(self, hash: str | bytes) -> bool:
149
"""
150
Check whether hash was created using the instance's parameters.
151
152
Use this to detect when passwords should be rehashed due to:
153
- Changed security parameters
154
- Updated library defaults
155
- Security policy changes
156
157
Args:
158
hash: Encoded Argon2 hash string
159
160
Returns:
161
True if hash should be rehashed with current parameters
162
"""
163
```
164
165
#### Usage Example
166
167
```python
168
from argon2 import PasswordHasher
169
170
ph = PasswordHasher()
171
172
# During login, check if hash needs updating
173
stored_hash = "$argon2id$v=19$m=102400,t=2,p=8$..." # Old parameters
174
175
if ph.check_needs_rehash(stored_hash):
176
# User provided correct password, update hash in database
177
new_hash = ph.hash(user_password)
178
# Save new_hash to database
179
print("Password hash updated to current security standards")
180
```
181
182
### Class Methods
183
184
Create PasswordHasher instances from parameter objects.
185
186
```python { .api }
187
@classmethod
188
def from_parameters(cls, params: Parameters) -> PasswordHasher:
189
"""
190
Construct a PasswordHasher from a Parameters object.
191
192
Args:
193
params: Parameters object with Argon2 configuration
194
195
Returns:
196
PasswordHasher instance configured with params
197
"""
198
```
199
200
#### Usage Example
201
202
```python
203
from argon2 import PasswordHasher
204
from argon2.profiles import RFC_9106_HIGH_MEMORY
205
206
# Create hasher from predefined profile
207
ph = PasswordHasher.from_parameters(RFC_9106_HIGH_MEMORY)
208
209
# Or from extracted parameters
210
from argon2 import extract_parameters
211
existing_hash = "$argon2id$v=19$m=65536,t=3,p=4$..."
212
params = extract_parameters(existing_hash)
213
ph_same = PasswordHasher.from_parameters(params)
214
```
215
216
### Properties
217
218
Access current hasher configuration parameters.
219
220
```python { .api }
221
@property
222
def time_cost(self) -> int:
223
"""Current time cost (iterations)"""
224
225
@property
226
def memory_cost(self) -> int:
227
"""Current memory cost (kibibytes)"""
228
229
@property
230
def parallelism(self) -> int:
231
"""Current parallelism (threads)"""
232
233
@property
234
def hash_len(self) -> int:
235
"""Current hash length (bytes)"""
236
237
@property
238
def salt_len(self) -> int:
239
"""Current salt length (bytes)"""
240
241
@property
242
def type(self) -> Type:
243
"""Current Argon2 type"""
244
```
245
246
#### Usage Example
247
248
```python
249
from argon2 import PasswordHasher
250
251
ph = PasswordHasher()
252
253
print(f"Using {ph.type.name} with:")
254
print(f" Time cost: {ph.time_cost}")
255
print(f" Memory: {ph.memory_cost} KiB")
256
print(f" Threads: {ph.parallelism}")
257
print(f" Hash length: {ph.hash_len} bytes")
258
```