or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

constants-algorithms.mdindex.mdjwe-operations.mdjwk-management.mdjws-operations.mdjwt-operations.md

jws-operations.mddocs/

0

# JWS Operations

1

2

Low-level JSON Web Signature functionality for signing arbitrary payloads and verifying signatures. JWS provides the cryptographic foundation for JWT tokens and enables signing of any content, not just JSON claims.

3

4

## Capabilities

5

6

### Payload Signing

7

8

Signs arbitrary payloads using various algorithms and returns JWS compact serialization format.

9

10

```python { .api }

11

def sign(payload, key, headers=None, algorithm='HS256'):

12

"""

13

Signs a payload and returns a JWS string.

14

15

Args:

16

payload (str or dict): A payload to sign. Can be:

17

- String data to sign directly

18

- Dictionary that will be JSON-encoded before signing

19

key (str or bytes or dict): The key to use for signing. Supports:

20

- String secrets for HMAC algorithms

21

- RSA/EC private keys in PEM format

22

- JWK dictionaries

23

- Key objects from jose.jwk

24

headers (dict, optional): Additional headers to include in the JWS header.

25

Will be merged with default headers (alg, typ)

26

algorithm (str): The algorithm to use for signing. Defaults to 'HS256'.

27

Supported: HS256, HS384, HS512, RS256, RS384, RS512, ES256, ES384, ES512

28

29

Returns:

30

str: The JWS token in compact format (header.payload.signature)

31

32

Raises:

33

JWSError: If there is an error signing the payload or algorithm not supported

34

"""

35

```

36

37

**Usage Examples:**

38

39

```python

40

from jose import jws

41

from jose.constants import ALGORITHMS

42

43

# Sign a string payload with HMAC

44

payload = "Hello, World!"

45

token = jws.sign(payload, 'secret', algorithm=ALGORITHMS.HS256)

46

47

# Sign a dictionary payload (auto JSON-encoded)

48

payload = {'message': 'Hello', 'timestamp': 1234567890}

49

token = jws.sign(payload, 'secret', algorithm=ALGORITHMS.HS256)

50

51

# Sign with additional headers

52

headers = {'kid': 'key-1', 'cty': 'text/plain'}

53

token = jws.sign("Important message", 'secret', headers=headers)

54

55

# RSA signing with private key

56

rsa_private_key = """-----BEGIN PRIVATE KEY-----

57

MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC...

58

-----END PRIVATE KEY-----"""

59

60

token = jws.sign("Secure message", rsa_private_key, algorithm=ALGORITHMS.RS256)

61

62

# ECDSA signing

63

ec_private_key = """-----BEGIN PRIVATE KEY-----

64

MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg...

65

-----END PRIVATE KEY-----"""

66

67

token = jws.sign(payload, ec_private_key, algorithm=ALGORITHMS.ES256)

68

69

# Using JWK dictionary

70

jwk_key = {

71

'kty': 'oct',

72

'k': 'GawgguFyGrWKav7AX4VKUg' # base64url-encoded secret

73

}

74

token = jws.sign(payload, jwk_key, algorithm=ALGORITHMS.HS256)

75

```

76

77

### Signature Verification

78

79

Verifies JWS signatures and returns the original payload after successful verification.

80

81

```python { .api }

82

def verify(token, key, algorithms, verify=True):

83

"""

84

Verifies a JWS token and returns the payload.

85

86

Args:

87

token (str or bytes): The JWS token to verify in compact format

88

key (str or bytes or dict or list): The verification key(s). Supports:

89

- String secrets for HMAC algorithms

90

- RSA/EC public keys in PEM format

91

- JWK dictionaries

92

- List of keys to try multiple verification keys

93

- Key objects from jose.jwk

94

algorithms (str or list): Allowed algorithms for verification. Required

95

for security - specify exactly which algorithms you accept

96

verify (bool): Whether to verify the signature. Defaults to True.

97

Set to False only for debugging or when signature is verified elsewhere

98

99

Returns:

100

bytes: The verified payload as bytes

101

102

Raises:

103

JWSError: If verification fails or token format is invalid

104

JWSSignatureError: If signature verification specifically fails

105

"""

106

```

107

108

**Usage Examples:**

109

110

```python

111

from jose import jws

112

from jose.exceptions import JWSError, JWSSignatureError

113

114

try:

115

# Basic HMAC verification

116

payload = jws.verify(token, 'secret', algorithms=['HS256'])

117

print(payload.decode('utf-8')) # Convert bytes to string

118

119

except JWSSignatureError:

120

print("Signature verification failed")

121

except JWSError as e:

122

print(f"JWS verification error: {e}")

123

124

# RSA public key verification

125

rsa_public_key = """-----BEGIN PUBLIC KEY-----

126

MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...

127

-----END PUBLIC KEY-----"""

128

129

payload = jws.verify(token, rsa_public_key, algorithms=['RS256'])

130

131

# Multiple algorithm support

132

payload = jws.verify(token, key, algorithms=['HS256', 'HS384', 'HS512'])

133

134

# Multiple key verification (try different keys)

135

keys = [

136

'primary-secret',

137

'backup-secret',

138

{'kty': 'oct', 'k': 'encoded-key'}

139

]

140

payload = jws.verify(token, keys, algorithms=['HS256'])

141

142

# Skip signature verification (debugging only)

143

payload = jws.verify(token, '', algorithms=['HS256'], verify=False)

144

145

# EC public key verification

146

ec_public_key = """-----BEGIN PUBLIC KEY-----

147

MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE...

148

-----END PUBLIC KEY-----"""

149

150

payload = jws.verify(token, ec_public_key, algorithms=['ES256'])

151

```

152

153

### Header and Payload Inspection

154

155

Retrieve JWS headers and payload without performing signature verification.

156

157

```python { .api }

158

def get_unverified_header(token):

159

"""

160

Get JWS header without verification.

161

162

Args:

163

token (str or bytes): The JWS token

164

165

Returns:

166

dict: The JWS header dictionary

167

168

Raises:

169

JWSError: If the token format is invalid

170

"""

171

172

def get_unverified_headers(token):

173

"""

174

Get JWS header without verification (alias for get_unverified_header).

175

176

Args:

177

token (str or bytes): The JWS token

178

179

Returns:

180

dict: The JWS header dictionary

181

182

Raises:

183

JWSError: If the token format is invalid

184

"""

185

186

def get_unverified_claims(token):

187

"""

188

Get JWS payload without verification.

189

190

Args:

191

token (str or bytes): The JWS token

192

193

Returns:

194

bytes: The JWS payload as bytes

195

196

Raises:

197

JWSError: If the token format is invalid

198

"""

199

```

200

201

**Usage Examples:**

202

203

```python

204

# Inspect JWS header

205

header = jws.get_unverified_header(token)

206

print(f"Algorithm: {header['alg']}")

207

print(f"Key ID: {header.get('kid')}")

208

print(f"Content Type: {header.get('cty')}")

209

210

# Get payload without verification

211

payload_bytes = jws.get_unverified_claims(token)

212

payload_str = payload_bytes.decode('utf-8')

213

print(f"Payload: {payload_str}")

214

215

# Conditional verification based on algorithm

216

header = jws.get_unverified_header(token)

217

if header['alg'] in ['HS256', 'HS384', 'HS512']:

218

payload = jws.verify(token, hmac_secret, algorithms=[header['alg']])

219

elif header['alg'] in ['RS256', 'RS384', 'RS512']:

220

payload = jws.verify(token, rsa_public_key, algorithms=[header['alg']])

221

elif header['alg'] in ['ES256', 'ES384', 'ES512']:

222

payload = jws.verify(token, ec_public_key, algorithms=[header['alg']])

223

```

224

225

## JWS Header Structure

226

227

JWS headers contain metadata about the signature algorithm and optional additional information:

228

229

```python { .api }

230

# Standard JWS header fields

231

header = {

232

'alg': 'HS256', # Algorithm (required)

233

'typ': 'JWT', # Type (optional, commonly 'JWT')

234

'kid': 'key-identifier', # Key ID for key selection (optional)

235

'cty': 'application/json', # Content type (optional)

236

'crit': ['custom-claim'] # Critical header parameters (optional)

237

}

238

```

239

240

**Header Examples:**

241

242

```python

243

# Minimal header (algorithm only)

244

headers = {'alg': 'HS256'}

245

246

# Header with key identification

247

headers = {'alg': 'RS256', 'kid': 'rsa-key-1'}

248

249

# Header with content type for non-JSON payloads

250

headers = {'alg': 'HS256', 'cty': 'text/plain'}

251

252

# Custom headers (use with caution)

253

headers = {

254

'alg': 'HS256',

255

'custom': 'value',

256

'x-app-version': '1.0.0'

257

}

258

```

259

260

## Payload Formats

261

262

JWS can sign various payload formats:

263

264

```python

265

# String payloads

266

payload = "Plain text message"

267

token = jws.sign(payload, key)

268

269

# JSON payloads (dictionaries)

270

payload = {'user': 'john', 'action': 'login'}

271

token = jws.sign(payload, key) # Auto-converted to JSON

272

273

# Binary payloads

274

payload = b"Binary data\x00\x01\x02"

275

token = jws.sign(payload, key)

276

277

# Pre-encoded JSON strings

278

import json

279

payload = json.dumps({'data': 'value'})

280

token = jws.sign(payload, key)

281

```

282

283

## Algorithm Support

284

285

JWS supports multiple signature algorithms:

286

287

**HMAC Algorithms (Symmetric):**

288

- `HS256`: HMAC using SHA-256 hash

289

- `HS384`: HMAC using SHA-384 hash

290

- `HS512`: HMAC using SHA-512 hash

291

292

**RSA Algorithms (Asymmetric):**

293

- `RS256`: RSA PKCS#1 v1.5 using SHA-256

294

- `RS384`: RSA PKCS#1 v1.5 using SHA-384

295

- `RS512`: RSA PKCS#1 v1.5 using SHA-512

296

297

**ECDSA Algorithms (Asymmetric):**

298

- `ES256`: ECDSA using P-256 curve and SHA-256

299

- `ES384`: ECDSA using P-384 curve and SHA-384

300

- `ES512`: ECDSA using P-521 curve and SHA-512

301

302

```python

303

from jose.constants import ALGORITHMS

304

305

# HMAC signing (fastest, requires shared secret)

306

token = jws.sign(payload, 'shared-secret', algorithm=ALGORITHMS.HS256)

307

308

# RSA signing (widely supported, larger signatures)

309

token = jws.sign(payload, rsa_private_key, algorithm=ALGORITHMS.RS256)

310

311

# ECDSA signing (smaller signatures, newer standard)

312

token = jws.sign(payload, ec_private_key, algorithm=ALGORITHMS.ES256)

313

```

314

315

## Error Handling

316

317

JWS operations can raise several specific exceptions:

318

319

```python { .api }

320

class JWSError(JOSEError):

321

"""Base exception for JWS-related errors."""

322

323

class JWSSignatureError(JWSError):

324

"""JWS signature verification failed."""

325

326

class JWSAlgorithmError(JWSError):

327

"""JWS algorithm not supported or invalid."""

328

```

329

330

**Error Handling Examples:**

331

332

```python

333

from jose.exceptions import JWSError, JWSSignatureError, JWSAlgorithmError

334

335

try:

336

payload = jws.verify(token, key, algorithms=['HS256'])

337

except JWSSignatureError:

338

print("Signature verification failed - invalid signature")

339

except JWSAlgorithmError:

340

print("Algorithm not supported or mismatch")

341

except JWSError as e:

342

print(f"JWS error: {e}")

343

344

# Signing errors

345

try:

346

token = jws.sign(payload, key, algorithm='UNSUPPORTED')

347

except JWSError as e:

348

print(f"Signing failed: {e}")

349

```

350

351

## Key Management Integration

352

353

JWS operations integrate with the JWK module for advanced key management:

354

355

```python

356

from jose import jws, jwk

357

358

# Construct key from various formats

359

key = jwk.construct(key_data, algorithm='HS256')

360

token = jws.sign(payload, key)

361

362

# Verify with constructed key

363

payload = jws.verify(token, key, algorithms=['HS256'])

364

365

# Multi-key scenarios

366

keys = [

367

jwk.construct(key1, 'HS256'),

368

jwk.construct(key2, 'HS256'),

369

jwk.construct(key3, 'HS256')

370

]

371

payload = jws.verify(token, keys, algorithms=['HS256'])

372

```

373

374

## Best Practices

375

376

1. **Always specify algorithms**: Never accept arbitrary algorithms in verification

377

2. **Use appropriate key sizes**: 256-bit keys for HS256, 2048+ bit RSA keys

378

3. **Handle verification errors**: Catch and handle signature verification failures

379

4. **Validate headers**: Check header parameters for expected values

380

5. **Key rotation**: Support multiple keys for seamless key rotation

381

6. **Algorithm selection**: Choose algorithms based on your security requirements:

382

- HMAC: Fast, requires shared secrets

383

- RSA: Widely supported, larger signatures

384

- ECDSA: Smaller signatures, modern standard