0
# Constants and Algorithms
1
2
Core algorithm constants, configuration options, and utility values used throughout the JOSE implementations. This module provides standardized algorithm identifiers and collections for easy reference and validation.
3
4
## Capabilities
5
6
### Algorithm Constants
7
8
The ALGORITHMS object provides constants for all supported cryptographic algorithms across JWT, JWS, and JWE operations.
9
10
#### Digital Signature Algorithms
11
12
```python { .api }
13
# HMAC Algorithms (Symmetric)
14
ALGORITHMS.HS256 = "HS256" # HMAC using SHA-256 hash
15
ALGORITHMS.HS384 = "HS384" # HMAC using SHA-384 hash
16
ALGORITHMS.HS512 = "HS512" # HMAC using SHA-512 hash
17
18
# RSA Algorithms (Asymmetric)
19
ALGORITHMS.RS256 = "RS256" # RSA PKCS#1 v1.5 using SHA-256
20
ALGORITHMS.RS384 = "RS384" # RSA PKCS#1 v1.5 using SHA-384
21
ALGORITHMS.RS512 = "RS512" # RSA PKCS#1 v1.5 using SHA-512
22
23
# ECDSA Algorithms (Asymmetric)
24
ALGORITHMS.ES256 = "ES256" # ECDSA using P-256 curve and SHA-256
25
ALGORITHMS.ES384 = "ES384" # ECDSA using P-384 curve and SHA-384
26
ALGORITHMS.ES512 = "ES512" # ECDSA using P-521 curve and SHA-512
27
28
# Special Algorithm
29
ALGORITHMS.NONE = "none" # No signature algorithm (use with caution)
30
```
31
32
**Usage Examples:**
33
34
```python
35
from jose.constants import ALGORITHMS
36
from jose import jwt, jws
37
38
# Use constants for consistency and avoiding typos
39
token = jwt.encode({'user': 'john'}, 'secret', algorithm=ALGORITHMS.HS256)
40
claims = jwt.decode(token, 'secret', algorithms=[ALGORITHMS.HS256])
41
42
# RSA signing
43
rsa_token = jwt.encode({'user': 'jane'}, rsa_private_key, algorithm=ALGORITHMS.RS256)
44
45
# ECDSA signing
46
ec_token = jwt.encode({'user': 'bob'}, ec_private_key, algorithm=ALGORITHMS.ES256)
47
48
# Multiple algorithm support
49
claims = jwt.decode(token, key, algorithms=[ALGORITHMS.HS256, ALGORITHMS.HS384, ALGORITHMS.HS512])
50
```
51
52
#### Content Encryption Algorithms
53
54
```python { .api }
55
# AES-GCM Algorithms (Authenticated Encryption)
56
ALGORITHMS.A128GCM = "A128GCM" # AES-128-GCM
57
ALGORITHMS.A192GCM = "A192GCM" # AES-192-GCM
58
ALGORITHMS.A256GCM = "A256GCM" # AES-256-GCM (Recommended)
59
60
# AES-CBC + HMAC Algorithms (Legacy Compatibility)
61
ALGORITHMS.A128CBC_HS256 = "A128CBC-HS256" # AES-128-CBC + HMAC-SHA-256
62
ALGORITHMS.A192CBC_HS384 = "A192CBC-HS384" # AES-192-CBC + HMAC-SHA-384
63
ALGORITHMS.A256CBC_HS512 = "A256CBC-HS512" # AES-256-CBC + HMAC-SHA-512
64
65
# AES-CBC Pseudo Algorithms (Internal Use)
66
ALGORITHMS.A128CBC = "A128CBC" # AES-128-CBC
67
ALGORITHMS.A192CBC = "A192CBC" # AES-192-CBC
68
ALGORITHMS.A256CBC = "A256CBC" # AES-256-CBC
69
```
70
71
**Usage Examples:**
72
73
```python
74
from jose import jwe
75
from jose.constants import ALGORITHMS
76
77
# Modern authenticated encryption (recommended)
78
encrypted = jwe.encrypt(plaintext, key, ALGORITHMS.A256GCM, ALGORITHMS.DIR)
79
80
# Legacy compatibility modes
81
encrypted = jwe.encrypt(plaintext, key, ALGORITHMS.A256CBC_HS512, ALGORITHMS.DIR)
82
83
# Different key lengths
84
encrypted = jwe.encrypt(plaintext, key_128, ALGORITHMS.A128GCM, ALGORITHMS.DIR)
85
encrypted = jwe.encrypt(plaintext, key_192, ALGORITHMS.A192GCM, ALGORITHMS.DIR)
86
encrypted = jwe.encrypt(plaintext, key_256, ALGORITHMS.A256GCM, ALGORITHMS.DIR)
87
```
88
89
#### Key Management Algorithms
90
91
```python { .api }
92
# Direct Encryption
93
ALGORITHMS.DIR = "dir" # Direct use of Content Encryption Key
94
95
# RSA Key Wrapping
96
ALGORITHMS.RSA1_5 = "RSA1_5" # RSA PKCS#1 v1.5 (deprecated)
97
ALGORITHMS.RSA_OAEP = "RSA-OAEP" # RSA OAEP with SHA-1 and MGF1
98
ALGORITHMS.RSA_OAEP_256 = "RSA-OAEP-256" # RSA OAEP with SHA-256 and MGF1 (recommended)
99
100
# AES Key Wrapping
101
ALGORITHMS.A128KW = "A128KW" # AES-128 Key Wrap
102
ALGORITHMS.A192KW = "A192KW" # AES-192 Key Wrap
103
ALGORITHMS.A256KW = "A256KW" # AES-256 Key Wrap
104
105
# Elliptic Curve Diffie-Hellman
106
ALGORITHMS.ECDH_ES = "ECDH-ES" # ECDH Ephemeral Static
107
ALGORITHMS.ECDH_ES_A128KW = "ECDH-ES+A128KW" # ECDH-ES + AES-128 Key Wrap
108
ALGORITHMS.ECDH_ES_A192KW = "ECDH-ES+A192KW" # ECDH-ES + AES-192 Key Wrap
109
ALGORITHMS.ECDH_ES_A256KW = "ECDH-ES+A256KW" # ECDH-ES + AES-256 Key Wrap
110
111
# AES-GCM Key Wrapping
112
ALGORITHMS.A128GCMKW = "A128GCMKW" # AES-128-GCM Key Wrap
113
ALGORITHMS.A192GCMKW = "A192GCMKW" # AES-192-GCM Key Wrap
114
ALGORITHMS.A256GCMKW = "A256GCMKW" # AES-256-GCM Key Wrap
115
116
# Password-Based Key Wrapping
117
ALGORITHMS.PBES2_HS256_A128KW = "PBES2-HS256+A128KW" # PBES2-HS256 + AES-128 Key Wrap
118
ALGORITHMS.PBES2_HS384_A192KW = "PBES2-HS384+A192KW" # PBES2-HS384 + AES-192 Key Wrap
119
ALGORITHMS.PBES2_HS512_A256KW = "PBES2-HS512+A256KW" # PBES2-HS512 + AES-256 Key Wrap
120
```
121
122
**Usage Examples:**
123
124
```python
125
from jose import jwe
126
from jose.constants import ALGORITHMS
127
128
# Direct encryption (key = CEK)
129
encrypted = jwe.encrypt(plaintext, direct_key, ALGORITHMS.A256GCM, ALGORITHMS.DIR)
130
131
# RSA key wrapping (recommended)
132
encrypted = jwe.encrypt(plaintext, rsa_public_key, ALGORITHMS.A256GCM, ALGORITHMS.RSA_OAEP_256)
133
134
# AES key wrapping
135
encrypted = jwe.encrypt(plaintext, aes_kek, ALGORITHMS.A256GCM, ALGORITHMS.A256KW)
136
137
# Legacy RSA (not recommended)
138
encrypted = jwe.encrypt(plaintext, rsa_public_key, ALGORITHMS.A256GCM, ALGORITHMS.RSA1_5)
139
```
140
141
### Algorithm Collections
142
143
Pre-defined sets of related algorithms for validation and filtering.
144
145
```python { .api }
146
# Signature Algorithm Collections
147
ALGORITHMS.HMAC = {HS256, HS384, HS512} # All HMAC algorithms
148
ALGORITHMS.RSA_DS = {RS256, RS384, RS512} # RSA digital signature algorithms
149
ALGORITHMS.EC_DS = {ES256, ES384, ES512} # EC digital signature algorithms
150
ALGORITHMS.RSA = RSA_DS.union(RSA_KW) # All RSA algorithms
151
ALGORITHMS.EC = EC_DS.union(EC_KW) # All EC algorithms
152
153
# Encryption Algorithm Collections
154
ALGORITHMS.AES_ENC = {A128GCM, A192GCM, A256GCM, A128CBC_HS256, A192CBC_HS384, A256CBC_HS512}
155
ALGORITHMS.AES_KW = {A128KW, A192KW, A256KW} # AES key wrapping algorithms
156
ALGORITHMS.RSA_KW = {RSA1_5, RSA_OAEP, RSA_OAEP_256} # RSA key wrapping algorithms
157
ALGORITHMS.GCM = {A128GCM, A192GCM, A256GCM} # GCM algorithms
158
ALGORITHMS.HMAC_AUTH_TAG = {A128CBC_HS256, A192CBC_HS384, A256CBC_HS512} # HMAC auth tag algorithms
159
160
# Additional Collections
161
ALGORITHMS.AES_PSEUDO = {A128CBC, A192CBC, A256CBC, A128GCM, A192GCM, A256GCM} # AES pseudo algorithms
162
ALGORITHMS.AES_JWE_ENC = {A128CBC_HS256, A192CBC_HS384, A256CBC_HS512, A128GCM, A192GCM, A256GCM} # JWE encryption algorithms
163
ALGORITHMS.AES = AES_ENC.union(AES_KW) # All AES algorithms
164
ALGORITHMS.AEC_GCM_KW = {A128GCMKW, A192GCMKW, A256GCMKW} # AES-GCM key wrapping algorithms
165
ALGORITHMS.PBES2_KW = {PBES2_HS256_A128KW, PBES2_HS384_A192KW, PBES2_HS512_A256KW} # PBES2 key wrapping algorithms
166
ALGORITHMS.EC_KW = {ECDH_ES, ECDH_ES_A128KW, ECDH_ES_A192KW, ECDH_ES_A256KW} # EC key wrapping algorithms
167
168
# Support Collections
169
ALGORITHMS.SUPPORTED = set # All algorithms supported by current backend
170
ALGORITHMS.ALL = set # All defined algorithms (including unsupported)
171
ALGORITHMS.KEYS = {} # Dictionary for registered key classes
172
```
173
174
**Usage Examples:**
175
176
```python
177
from jose.constants import ALGORITHMS
178
from jose import jwt
179
180
# Check if algorithm is HMAC
181
if algorithm in ALGORITHMS.HMAC:
182
# Use symmetric key
183
token = jwt.encode(claims, symmetric_key, algorithm=algorithm)
184
185
# Check if algorithm is RSA
186
elif algorithm in ALGORITHMS.RSA_DS:
187
# Use RSA private key
188
token = jwt.encode(claims, rsa_private_key, algorithm=algorithm)
189
190
# Validate algorithm support
191
if algorithm not in ALGORITHMS.SUPPORTED:
192
raise ValueError(f"Algorithm {algorithm} not supported")
193
194
# Accept only secure algorithms
195
secure_algorithms = ALGORITHMS.HMAC.union(ALGORITHMS.RSA_DS).union(ALGORITHMS.EC_DS)
196
claims = jwt.decode(token, key, algorithms=list(secure_algorithms))
197
```
198
199
### Hash Function Mapping
200
201
Mapping from algorithms to their corresponding hash functions.
202
203
```python { .api }
204
ALGORITHMS.HASHES = {
205
HS256: hashlib.sha256, # SHA-256 for HS256
206
HS384: hashlib.sha384, # SHA-384 for HS384
207
HS512: hashlib.sha512, # SHA-512 for HS512
208
RS256: hashlib.sha256, # SHA-256 for RS256
209
RS384: hashlib.sha384, # SHA-384 for RS384
210
RS512: hashlib.sha512, # SHA-512 for RS512
211
ES256: hashlib.sha256, # SHA-256 for ES256
212
ES384: hashlib.sha384, # SHA-384 for ES384
213
ES512: hashlib.sha512 # SHA-512 for ES512
214
}
215
```
216
217
**Usage Examples:**
218
219
```python
220
from jose.constants import ALGORITHMS
221
import hashlib
222
223
# Get hash function for algorithm
224
hash_func = ALGORITHMS.HASHES.get(ALGORITHMS.HS256) # returns hashlib.sha256
225
if hash_func:
226
digest = hash_func(b'message').digest()
227
228
# Check hash function availability
229
for alg, hash_func in ALGORITHMS.HASHES.items():
230
print(f"{alg}: {hash_func.__name__}")
231
```
232
233
### Compression Algorithms
234
235
Constants for compression algorithms used in JWE operations.
236
237
```python { .api }
238
# Compression Constants
239
ZIPS.DEF = "DEF" # DEFLATE compression algorithm
240
ZIPS.NONE = None # No compression
241
242
# Supported Compression
243
ZIPS.SUPPORTED = {DEF, NONE} # Supported compression algorithms
244
```
245
246
**Usage Examples:**
247
248
```python
249
from jose import jwe
250
from jose.constants import ALGORITHMS, ZIPS
251
252
# With DEFLATE compression
253
encrypted = jwe.encrypt(
254
large_plaintext,
255
key,
256
encryption=ALGORITHMS.A256GCM,
257
algorithm=ALGORITHMS.DIR,
258
zip=ZIPS.DEF
259
)
260
261
# Without compression (default)
262
encrypted = jwe.encrypt(
263
plaintext,
264
key,
265
encryption=ALGORITHMS.A256GCM,
266
algorithm=ALGORITHMS.DIR,
267
zip=ZIPS.NONE # or omit zip parameter
268
)
269
270
# Validate compression algorithm
271
if compression_alg in ZIPS.SUPPORTED:
272
encrypted = jwe.encrypt(plaintext, key, zip=compression_alg)
273
```
274
275
### Size Limits
276
277
Configuration constants for operational limits.
278
279
```python { .api }
280
JWE_SIZE_LIMIT = 250 * 1024 # 250 KB maximum JWE payload size
281
```
282
283
**Usage Examples:**
284
285
```python
286
from jose.constants import JWE_SIZE_LIMIT
287
288
# Check payload size before encryption
289
if len(plaintext) > JWE_SIZE_LIMIT:
290
raise ValueError(f"Payload too large: {len(plaintext)} bytes > {JWE_SIZE_LIMIT} bytes")
291
292
encrypted = jwe.encrypt(plaintext, key)
293
```
294
295
## Algorithm Recommendations
296
297
### For New Applications
298
299
**Digital Signatures:**
300
- **JWT/JWS**: Use `ALGORITHMS.HS256` for symmetric keys, `ALGORITHMS.RS256` or `ALGORITHMS.ES256` for asymmetric
301
- **Performance**: HMAC algorithms are fastest
302
- **Security**: ES256 provides smaller signatures than RS256
303
304
**Content Encryption:**
305
- **JWE**: Use `ALGORITHMS.A256GCM` for content encryption
306
- **Key Management**: Use `ALGORITHMS.RSA_OAEP_256` for RSA key wrapping, `ALGORITHMS.DIR` for pre-shared keys
307
308
```python
309
# Recommended combinations for new applications
310
from jose.constants import ALGORITHMS
311
312
# High-security symmetric
313
jwt_token = jwt.encode(claims, secret, algorithm=ALGORITHMS.HS256)
314
315
# High-security asymmetric
316
jwt_token = jwt.encode(claims, rsa_private_key, algorithm=ALGORITHMS.RS256)
317
318
# Modern asymmetric (smaller signatures)
319
jwt_token = jwt.encode(claims, ec_private_key, algorithm=ALGORITHMS.ES256)
320
321
# Secure encryption
322
encrypted = jwe.encrypt(
323
plaintext,
324
rsa_public_key,
325
encryption=ALGORITHMS.A256GCM,
326
algorithm=ALGORITHMS.RSA_OAEP_256
327
)
328
```
329
330
### Legacy Compatibility
331
332
For compatibility with older systems that may not support modern algorithms:
333
334
```python
335
# Legacy JWT compatibility
336
legacy_algorithms = [
337
ALGORITHMS.HS256, ALGORITHMS.HS384, ALGORITHMS.HS512, # HMAC
338
ALGORITHMS.RS256, ALGORITHMS.RS384, ALGORITHMS.RS512 # RSA
339
]
340
341
# Legacy JWE compatibility
342
legacy_encrypted = jwe.encrypt(
343
plaintext,
344
key,
345
encryption=ALGORITHMS.A256CBC_HS512, # CBC + HMAC instead of GCM
346
algorithm=ALGORITHMS.DIR
347
)
348
```
349
350
## Algorithm Security Properties
351
352
### Security Levels
353
354
**Symmetric Algorithms (HMAC):**
355
- `HS256`: 128-bit security level
356
- `HS384`: 192-bit security level
357
- `HS512`: 256-bit security level
358
359
**Asymmetric Algorithms:**
360
- `RS256/ES256`: ~128-bit security level
361
- `RS384/ES384`: ~192-bit security level
362
- `RS512/ES512`: ~256-bit security level
363
364
**Encryption Algorithms:**
365
- `A128GCM`: 128-bit security level
366
- `A192GCM`: 192-bit security level
367
- `A256GCM`: 256-bit security level
368
369
### Performance Characteristics
370
371
```python
372
# Performance ranking (fastest to slowest)
373
# 1. HMAC algorithms (HS256, HS384, HS512) - Symmetric, very fast
374
# 2. ECDSA algorithms (ES256, ES384, ES512) - Asymmetric, fast
375
# 3. RSA algorithms (RS256, RS384, RS512) - Asymmetric, slower
376
377
# Signature size ranking (smallest to largest)
378
# 1. ECDSA algorithms - Small signatures (~64-132 bytes)
379
# 2. HMAC algorithms - Medium signatures (~32-64 bytes)
380
# 3. RSA algorithms - Large signatures (~256-512 bytes)
381
```
382
383
## Usage Patterns
384
385
### Algorithm Validation
386
387
```python
388
from jose.constants import ALGORITHMS
389
390
def validate_algorithm(algorithm, allowed_types='all'):
391
"""Validate algorithm against allowed types."""
392
if allowed_types == 'symmetric' and algorithm not in ALGORITHMS.HMAC:
393
raise ValueError("Only symmetric algorithms allowed")
394
elif allowed_types == 'asymmetric' and algorithm in ALGORITHMS.HMAC:
395
raise ValueError("Only asymmetric algorithms allowed")
396
elif algorithm not in ALGORITHMS.SUPPORTED:
397
raise ValueError(f"Algorithm {algorithm} not supported")
398
return True
399
400
# Usage
401
validate_algorithm(ALGORITHMS.HS256, 'symmetric') # OK
402
validate_algorithm(ALGORITHMS.RS256, 'asymmetric') # OK
403
```
404
405
### Dynamic Algorithm Selection
406
407
```python
408
from jose.constants import ALGORITHMS
409
410
def select_algorithm(key_type, security_level=256):
411
"""Select appropriate algorithm based on key type and security level."""
412
if key_type == 'symmetric':
413
if security_level >= 256:
414
return ALGORITHMS.HS512
415
elif security_level >= 192:
416
return ALGORITHMS.HS384
417
else:
418
return ALGORITHMS.HS256
419
elif key_type == 'rsa':
420
if security_level >= 256:
421
return ALGORITHMS.RS512
422
elif security_level >= 192:
423
return ALGORITHMS.RS384
424
else:
425
return ALGORITHMS.RS256
426
elif key_type == 'ec':
427
if security_level >= 256:
428
return ALGORITHMS.ES512
429
elif security_level >= 192:
430
return ALGORITHMS.ES384
431
else:
432
return ALGORITHMS.ES256
433
else:
434
raise ValueError(f"Unknown key type: {key_type}")
435
436
# Usage
437
algorithm = select_algorithm('symmetric', 256) # Returns HS512
438
algorithm = select_algorithm('ec', 128) # Returns ES256
439
```
440
441
## Best Practices
442
443
1. **Use Constants**: Always use `ALGORITHMS` constants instead of string literals
444
2. **Algorithm Validation**: Validate algorithms against `ALGORITHMS.SUPPORTED`
445
3. **Security Requirements**: Choose algorithms based on your security requirements
446
4. **Performance Needs**: Consider performance implications of algorithm choice
447
5. **Future-Proofing**: Design systems to support algorithm upgrades
448
6. **Legacy Support**: Maintain compatibility while encouraging modern algorithms
449
7. **Key Sizes**: Ensure key sizes match algorithm requirements
450
8. **Regular Updates**: Stay informed about algorithm deprecations and recommendations