or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

algorithm-management.mdindex.mdjwk-operations.mdjwks-client.mdjws-operations.mdjwt-operations.md

algorithm-management.mddocs/

0

# Algorithm Management

1

2

Cryptographic algorithm registration and management system providing custom algorithm support, algorithm whitelisting for security, and flexible algorithm configuration for both global and instance-level operations.

3

4

## Capabilities

5

6

### Global Algorithm Functions

7

8

Global functions for managing algorithms across all PyJWT operations using a shared algorithm registry.

9

10

```python { .api }

11

def register_algorithm(alg_id: str, alg_obj) -> None:

12

"""

13

Register a custom algorithm globally for all JWT/JWS operations.

14

15

Args:

16

alg_id (str): Algorithm identifier (e.g., 'CUSTOM256')

17

alg_obj: Algorithm implementation object

18

19

Raises:

20

ValueError: Algorithm already registered

21

TypeError: Invalid algorithm object

22

"""

23

24

def unregister_algorithm(alg_id: str) -> None:

25

"""

26

Remove an algorithm from the global registry.

27

28

Args:

29

alg_id (str): Algorithm identifier to remove

30

31

Raises:

32

KeyError: Algorithm not registered

33

"""

34

35

def get_algorithm_by_name(alg_name: str):

36

"""

37

Retrieve algorithm implementation by name from global registry.

38

39

Args:

40

alg_name (str): Algorithm name

41

42

Returns:

43

Algorithm object implementation

44

45

Raises:

46

NotImplementedError: Algorithm not supported or cryptography missing

47

"""

48

49

def get_unverified_header(jwt: str | bytes) -> dict:

50

"""

51

Extract JWT header without signature verification.

52

53

Args:

54

jwt (str | bytes): JWT token

55

56

Returns:

57

dict: JWT header dictionary

58

59

Raises:

60

DecodeError: Invalid token format

61

InvalidTokenError: Invalid header structure

62

"""

63

```

64

65

Usage examples:

66

67

```python

68

import jwt

69

from jwt.algorithms import Algorithm

70

71

# Check algorithm availability

72

try:

73

alg = jwt.get_algorithm_by_name('RS256')

74

print(f"RS256 available: {alg}")

75

except NotImplementedError as e:

76

print(f"RS256 not available: {e}")

77

78

# Extract header for algorithm info

79

token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9..."

80

header = jwt.get_unverified_header(token)

81

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

82

83

# Register custom algorithm globally

84

class CustomHMAC(Algorithm):

85

def sign(self, msg, key):

86

# Custom signing implementation

87

import hashlib

88

import hmac

89

return hmac.new(key, msg, hashlib.sha3_256).digest()

90

91

def verify(self, msg, key, sig):

92

# Custom verification implementation

93

expected = self.sign(msg, key)

94

return hmac.compare_digest(sig, expected)

95

96

jwt.register_algorithm('CUSTOM-HMAC', CustomHMAC())

97

98

# Use custom algorithm

99

payload = {'user_id': 123}

100

token = jwt.encode(payload, b'secret', algorithm='CUSTOM-HMAC')

101

decoded = jwt.decode(token, b'secret', algorithms=['CUSTOM-HMAC'])

102

103

# Remove algorithm when no longer needed

104

jwt.unregister_algorithm('CUSTOM-HMAC')

105

```

106

107

### Instance-Level Algorithm Management

108

109

Algorithm management for specific PyJWT and PyJWS instances with custom algorithm sets and whitelisting.

110

111

```python { .api }

112

# PyJWS instance methods

113

class PyJWS:

114

def register_algorithm(self, alg_id: str, alg_obj) -> None:

115

"""Register algorithm for this JWS instance only."""

116

117

def unregister_algorithm(self, alg_id: str) -> None:

118

"""Unregister algorithm from this JWS instance."""

119

120

def get_algorithm_by_name(self, alg_name: str):

121

"""Get algorithm from this JWS instance."""

122

123

def get_algorithms(self) -> list:

124

"""List algorithms available to this JWS instance."""

125

126

# PyJWT inherits algorithm management through its internal PyJWS instance

127

```

128

129

Usage examples:

130

131

```python

132

import jwt

133

134

# Create JWS instance with limited algorithms

135

jws = jwt.PyJWS(algorithms=['HS256', 'HS512']) # Only allow HMAC

136

print(f"Allowed algorithms: {jws.get_algorithms()}")

137

138

# Add algorithm to specific instance

139

custom_alg = CustomHMAC()

140

jws.register_algorithm('CUSTOM', custom_alg)

141

142

# This instance now supports CUSTOM, but global instance doesn't

143

token = jws.encode(b'payload', b'key', algorithm='CUSTOM')

144

145

# Different instance with different algorithms

146

secure_jws = jwt.PyJWS(algorithms=['RS256', 'ES256']) # Only asymmetric

147

secure_jws.register_algorithm('CUSTOM-RSA', CustomRSA())

148

```

149

150

### Algorithm Security and Whitelisting

151

152

Security-focused algorithm management with explicit whitelisting and algorithm restrictions.

153

154

```python

155

import jwt

156

157

# Secure algorithm whitelisting

158

ALLOWED_ALGORITHMS = ['RS256', 'ES256', 'EdDSA'] # Only strong asymmetric

159

160

def verify_secure_token(token, key):

161

"""Verify token with strict algorithm policy."""

162

return jwt.decode(token, key, algorithms=ALLOWED_ALGORITHMS)

163

164

# Instance with security policy

165

secure_jwt = jwt.PyJWT()

166

secure_jws = jwt.PyJWS(algorithms=ALLOWED_ALGORITHMS)

167

168

# Block weak algorithms

169

weak_algorithms = ['none', 'HS256'] # Example: block 'none' and symmetric

170

for alg in weak_algorithms:

171

try:

172

jwt.unregister_algorithm(alg)

173

except KeyError:

174

pass # Algorithm not registered

175

176

# Verify no weak algorithms remain

177

available = jwt.PyJWS().get_algorithms()

178

dangerous = set(available) & set(weak_algorithms)

179

if dangerous:

180

print(f"Warning: Dangerous algorithms still available: {dangerous}")

181

```

182

183

### Algorithm Implementation Interface

184

185

Base interface for implementing custom algorithms compatible with PyJWT.

186

187

```python { .api }

188

class Algorithm:

189

"""

190

Base class for all algorithm implementations.

191

192

Custom algorithms must inherit from this class and implement

193

required methods for signing and verification.

194

"""

195

196

def sign(self, msg: bytes, key) -> bytes:

197

"""

198

Sign message with the given key.

199

200

Args:

201

msg (bytes): Message to sign

202

key: Cryptographic key for signing

203

204

Returns:

205

bytes: Signature

206

"""

207

raise NotImplementedError()

208

209

def verify(self, msg: bytes, key, sig: bytes) -> bool:

210

"""

211

Verify signature against message and key.

212

213

Args:

214

msg (bytes): Original message

215

key: Cryptographic key for verification

216

sig (bytes): Signature to verify

217

218

Returns:

219

bool: True if signature is valid

220

"""

221

raise NotImplementedError()

222

223

def prepare_key(self, key):

224

"""

225

Prepare and validate key for use with this algorithm.

226

227

Args:

228

key: Raw key material

229

230

Returns:

231

Prepared key object

232

233

Raises:

234

InvalidKeyError: Key is invalid for this algorithm

235

"""

236

return key

237

```

238

239

### Custom Algorithm Examples

240

241

Examples of implementing custom algorithms for specific use cases:

242

243

#### Custom HMAC with Different Hash Function

244

245

```python

246

import hashlib

247

import hmac

248

from jwt.algorithms import Algorithm

249

250

class HMACSHA3_256(Algorithm):

251

"""HMAC using SHA3-256 hash function."""

252

253

def sign(self, msg: bytes, key: bytes) -> bytes:

254

return hmac.new(key, msg, hashlib.sha3_256).digest()

255

256

def verify(self, msg: bytes, key: bytes, sig: bytes) -> bool:

257

expected = self.sign(msg, key)

258

return hmac.compare_digest(sig, expected)

259

260

def prepare_key(self, key):

261

if not isinstance(key, (bytes, str)):

262

raise jwt.InvalidKeyError("HMAC key must be bytes or string")

263

if isinstance(key, str):

264

key = key.encode('utf-8')

265

return key

266

267

# Register and use

268

jwt.register_algorithm('HS3-256', HMACSHA3_256())

269

token = jwt.encode({'data': 'test'}, 'secret', algorithm='HS3-256')

270

```

271

272

#### Custom Algorithm with Key Validation

273

274

```python

275

from jwt.algorithms import Algorithm

276

from jwt.exceptions import InvalidKeyError

277

278

class SecureHMAC(Algorithm):

279

"""HMAC with minimum key length requirement."""

280

281

MIN_KEY_LENGTH = 32 # Require 256-bit keys minimum

282

283

def prepare_key(self, key):

284

if isinstance(key, str):

285

key = key.encode('utf-8')

286

287

if not isinstance(key, bytes):

288

raise InvalidKeyError("Key must be bytes or string")

289

290

if len(key) < self.MIN_KEY_LENGTH:

291

raise InvalidKeyError(f"Key must be at least {self.MIN_KEY_LENGTH} bytes")

292

293

return key

294

295

def sign(self, msg: bytes, key: bytes) -> bytes:

296

return hmac.new(key, msg, hashlib.sha256).digest()

297

298

def verify(self, msg: bytes, key: bytes, sig: bytes) -> bool:

299

expected = self.sign(msg, key)

300

return hmac.compare_digest(sig, expected)

301

302

# Usage with key validation

303

jwt.register_algorithm('SECURE-HMAC', SecureHMAC())

304

305

try:

306

# This will fail - key too short

307

jwt.encode({'data': 'test'}, 'short', algorithm='SECURE-HMAC')

308

except InvalidKeyError as e:

309

print(f"Key rejected: {e}")

310

311

# This will work - key meets minimum length

312

long_key = 'a' * 32

313

token = jwt.encode({'data': 'test'}, long_key, algorithm='SECURE-HMAC')

314

```

315

316

### Algorithm Discovery and Introspection

317

318

Tools for discovering available algorithms and their capabilities:

319

320

```python

321

import jwt

322

323

def list_available_algorithms():

324

"""List all globally available algorithms."""

325

jws = jwt.PyJWS()

326

algorithms = jws.get_algorithms()

327

328

for alg_name in sorted(algorithms):

329

try:

330

alg_obj = jwt.get_algorithm_by_name(alg_name)

331

print(f"{alg_name}: {type(alg_obj).__name__}")

332

except NotImplementedError as e:

333

print(f"{alg_name}: Not available ({e})")

334

335

def check_cryptography_algorithms():

336

"""Check which algorithms require cryptography library."""

337

from jwt.algorithms import requires_cryptography, has_crypto

338

339

print(f"Cryptography installed: {has_crypto}")

340

print(f"Algorithms requiring cryptography: {requires_cryptography}")

341

342

if not has_crypto:

343

print("Install cryptography for full algorithm support:")

344

print("pip install PyJWT[crypto]")

345

346

# Run diagnostics

347

list_available_algorithms()

348

check_cryptography_algorithms()

349

```

350

351

### Security Best Practices

352

353

Recommended patterns for secure algorithm management:

354

355

```python

356

import jwt

357

358

# 1. Use explicit algorithm whitelists

359

PRODUCTION_ALGORITHMS = ['RS256', 'ES256', 'EdDSA']

360

361

def secure_decode(token, key):

362

return jwt.decode(token, key, algorithms=PRODUCTION_ALGORITHMS)

363

364

# 2. Block dangerous algorithms

365

BLOCKED_ALGORITHMS = ['none', 'HS256'] # Example policy

366

367

for alg in BLOCKED_ALGORITHMS:

368

try:

369

jwt.unregister_algorithm(alg)

370

except KeyError:

371

pass

372

373

# 3. Use asymmetric algorithms in production

374

def create_production_jwt_instance():

375

return jwt.PyJWT(algorithms=['RS256', 'ES256'])

376

377

# 4. Validate algorithm in token matches expected

378

def verify_with_algorithm_check(token, key, expected_algorithm):

379

header = jwt.get_unverified_header(token)

380

if header.get('alg') != expected_algorithm:

381

raise ValueError(f"Unexpected algorithm: {header.get('alg')}")

382

383

return jwt.decode(token, key, algorithms=[expected_algorithm])

384

385

# 5. Regular algorithm audit

386

def audit_algorithms():

387

"""Audit currently available algorithms for security compliance."""

388

available = jwt.PyJWS().get_algorithms()

389

390

dangerous = {'none'} # Example dangerous algorithms

391

weak = {'HS256', 'HS384', 'HS512'} # Example: symmetric keys

392

393

found_dangerous = set(available) & dangerous

394

found_weak = set(available) & weak

395

396

if found_dangerous:

397

print(f"CRITICAL: Dangerous algorithms available: {found_dangerous}")

398

if found_weak:

399

print(f"WARNING: Weak algorithms available: {found_weak}")

400

401

return len(found_dangerous) == 0 and len(found_weak) == 0

402

403

# Run security audit

404

if not audit_algorithms():

405

print("Algorithm security policy violations detected!")

406

```