0
# JWS Operations
1
2
Lower-level JSON Web Signature operations for signing and verifying arbitrary payloads. Provides direct access to the signature layer without JWT-specific claim validation, useful for custom payload formats or when you need fine-grained control over the signature process.
3
4
## Capabilities
5
6
### JWS Encoding
7
8
Creates signed JSON Web Signatures from byte payloads with flexible header management and algorithm support.
9
10
```python { .api }
11
class PyJWS:
12
def __init__(self, algorithms: list = None, options: dict = None):
13
"""
14
Initialize JWS instance with algorithm whitelist.
15
16
Args:
17
algorithms (list): Allowed algorithms for this instance
18
options (dict): Default options for verification
19
"""
20
21
def encode(self, payload: bytes, key, algorithm: str = None,
22
headers: dict = None, json_encoder = None,
23
is_payload_detached: bool = False, sort_headers: bool = True) -> str:
24
"""
25
Create a JWS signature for the given payload.
26
27
Args:
28
payload (bytes): Data to be signed
29
key: Private key for signing
30
algorithm (str): Signing algorithm
31
headers (dict): Additional headers
32
json_encoder: Custom JSON encoder
33
is_payload_detached (bool): Create detached signature
34
sort_headers (bool): Sort header keys
35
36
Returns:
37
str: JWS token
38
39
Raises:
40
InvalidKeyError: Invalid key for algorithm
41
InvalidAlgorithmError: Unsupported algorithm
42
"""
43
```
44
45
Usage examples:
46
47
```python
48
import jwt
49
50
# Basic JWS encoding
51
jws = jwt.PyJWS()
52
payload = b'{"user_id": 123, "role": "admin"}'
53
token = jws.encode(payload, 'secret', algorithm='HS256')
54
55
# With custom headers
56
headers = {'typ': 'JWT', 'kid': 'key-1'}
57
token = jws.encode(payload, 'secret', algorithm='HS256', headers=headers)
58
59
# Detached payload (payload not included in token)
60
token = jws.encode(payload, 'secret', algorithm='HS256', is_payload_detached=True)
61
```
62
63
### JWS Decoding
64
65
Decodes and verifies JSON Web Signatures returning the raw payload bytes without JWT-specific processing.
66
67
```python { .api }
68
class PyJWS:
69
def decode(self, jws: str | bytes, key = '', algorithms: list = None,
70
options: dict = None, detached_payload: bytes = None) -> bytes:
71
"""
72
Verify JWS signature and return payload.
73
74
Args:
75
jws (str | bytes): JWS token to verify
76
key: Public key for verification
77
algorithms (list): Allowed algorithms
78
options (dict): Verification options
79
detached_payload (bytes): Payload for detached signatures
80
81
Returns:
82
bytes: Verified payload
83
84
Raises:
85
DecodeError: Token format errors
86
InvalidSignatureError: Signature verification failed
87
InvalidAlgorithmError: Algorithm not allowed
88
"""
89
90
def decode_complete(self, jws: str | bytes, key = '', algorithms: list = None,
91
options: dict = None, detached_payload: bytes = None) -> dict:
92
"""
93
Decode JWS returning header, payload, and signature.
94
95
Returns:
96
dict: {'header': dict, 'payload': bytes, 'signature': bytes}
97
"""
98
```
99
100
Usage examples:
101
102
```python
103
import jwt
104
from jwt.exceptions import InvalidSignatureError
105
106
jws = jwt.PyJWS()
107
108
# Basic decoding
109
try:
110
payload = jws.decode(token, 'secret', algorithms=['HS256'])
111
print(f"Payload: {payload.decode('utf-8')}")
112
except InvalidSignatureError:
113
print("Signature verification failed")
114
115
# With detached payload
116
payload = jws.decode(token, 'secret', algorithms=['HS256'],
117
detached_payload=original_payload)
118
119
# Get complete structure
120
decoded = jws.decode_complete(token, 'secret', algorithms=['HS256'])
121
print(f"Header: {decoded['header']}")
122
print(f"Payload: {decoded['payload']}")
123
```
124
125
### Header Operations
126
127
Extract and validate JWT headers without signature verification, useful for determining key IDs or algorithm information.
128
129
```python { .api }
130
class PyJWS:
131
def get_unverified_header(self, jwt: str | bytes) -> dict:
132
"""
133
Extract JWT header without signature verification.
134
135
Args:
136
jwt (str | bytes): JWT token
137
138
Returns:
139
dict: JWT header
140
141
Raises:
142
DecodeError: Invalid token format
143
InvalidTokenError: Invalid header structure
144
"""
145
```
146
147
Usage example:
148
149
```python
150
import jwt
151
152
jws = jwt.PyJWS()
153
154
# Extract header to determine key ID
155
header = jws.get_unverified_header(token)
156
key_id = header.get('kid')
157
algorithm = header.get('alg')
158
159
print(f"Key ID: {key_id}, Algorithm: {algorithm}")
160
161
# Use header info to select appropriate key
162
if key_id == 'key-1':
163
key = get_key_1()
164
elif key_id == 'key-2':
165
key = get_key_2()
166
167
payload = jws.decode(token, key, algorithms=[algorithm])
168
```
169
170
### Algorithm Management
171
172
Manage cryptographic algorithms for JWS instances with registration and whitelisting capabilities.
173
174
```python { .api }
175
class PyJWS:
176
def register_algorithm(self, alg_id: str, alg_obj) -> None:
177
"""
178
Register a new algorithm for use with this JWS instance.
179
180
Args:
181
alg_id (str): Algorithm identifier
182
alg_obj: Algorithm implementation
183
184
Raises:
185
ValueError: Algorithm already registered
186
TypeError: Invalid algorithm object
187
"""
188
189
def unregister_algorithm(self, alg_id: str) -> None:
190
"""
191
Remove an algorithm from this JWS instance.
192
193
Args:
194
alg_id (str): Algorithm identifier
195
196
Raises:
197
KeyError: Algorithm not registered
198
"""
199
200
def get_algorithm_by_name(self, alg_name: str):
201
"""
202
Get algorithm implementation by name.
203
204
Args:
205
alg_name (str): Algorithm name
206
207
Returns:
208
Algorithm object
209
210
Raises:
211
NotImplementedError: Algorithm not supported
212
"""
213
214
def get_algorithms(self) -> list:
215
"""
216
Get list of supported algorithm names.
217
218
Returns:
219
list: Algorithm names
220
"""
221
```
222
223
Usage example:
224
225
```python
226
import jwt
227
228
jws = jwt.PyJWS()
229
230
# Check supported algorithms
231
algorithms = jws.get_algorithms()
232
print(f"Supported: {algorithms}")
233
234
# Get algorithm object
235
hs256 = jws.get_algorithm_by_name('HS256')
236
237
# Register custom algorithm (advanced usage)
238
from jwt.algorithms import Algorithm
239
class CustomAlgorithm(Algorithm):
240
def sign(self, msg, key):
241
# Custom signing logic
242
pass
243
244
def verify(self, msg, key, sig):
245
# Custom verification logic
246
pass
247
248
jws.register_algorithm('CUSTOM', CustomAlgorithm())
249
```
250
251
## Global JWS Functions
252
253
Convenience functions that use a global PyJWS instance:
254
255
```python { .api }
256
def get_unverified_header(jwt: str | bytes) -> dict:
257
"""Extract header without verification (global function)."""
258
259
def register_algorithm(alg_id: str, alg_obj) -> None:
260
"""Register algorithm globally."""
261
262
def unregister_algorithm(alg_id: str) -> None:
263
"""Unregister algorithm globally."""
264
265
def get_algorithm_by_name(alg_name: str):
266
"""Get algorithm by name (global function)."""
267
```
268
269
Usage example:
270
271
```python
272
import jwt
273
274
# Using global functions
275
header = jwt.get_unverified_header(token)
276
jwt.register_algorithm('CUSTOM', custom_alg)
277
algorithm = jwt.get_algorithm_by_name('HS256')
278
```
279
280
## Verification Options
281
282
JWS verification options are simpler than JWT options:
283
284
```python { .api }
285
# Default JWS verification options
286
{
287
'verify_signature': True # Verify signature
288
}
289
```
290
291
Usage example:
292
293
```python
294
# Disable signature verification (dangerous!)
295
options = {'verify_signature': False}
296
payload = jws.decode(token, options=options)
297
```
298
299
## Detached Signatures
300
301
JWS supports detached signatures where the payload is not included in the token:
302
303
```python
304
import jwt
305
306
jws = jwt.PyJWS()
307
payload = b'sensitive data'
308
309
# Create detached signature
310
token = jws.encode(payload, 'secret', algorithm='HS256', is_payload_detached=True)
311
312
# Verify with separate payload
313
verified = jws.decode(token, 'secret', algorithms=['HS256'],
314
detached_payload=payload)
315
```