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

jwk-operations.mddocs/

0

# JSON Web Keys (JWK)

1

2

JSON Web Key handling and cryptographic key abstraction supporting RSA, ECDSA, EdDSA, and symmetric keys. Provides key parsing, validation, algorithm detection, and integration with JWT/JWS operations for secure key management.

3

4

## Capabilities

5

6

### PyJWK - Individual Key Management

7

8

Represents a single JSON Web Key with automatic algorithm detection and cryptographic key parsing.

9

10

```python { .api }

11

class PyJWK:

12

def __init__(self, jwk_data: dict, algorithm: str = None):

13

"""

14

Initialize PyJWK from JWK dictionary.

15

16

Args:

17

jwk_data (dict): JWK data according to RFC 7517

18

algorithm (str): Force specific algorithm (optional)

19

20

Raises:

21

InvalidKeyError: Invalid key format or unsupported key type

22

PyJWKError: General JWK processing error

23

MissingCryptographyError: Cryptography library required

24

"""

25

26

@staticmethod

27

def from_dict(obj: dict, algorithm: str = None) -> 'PyJWK':

28

"""

29

Create PyJWK from dictionary.

30

31

Args:

32

obj (dict): JWK dictionary

33

algorithm (str): Optional algorithm override

34

35

Returns:

36

PyJWK: Initialized key object

37

"""

38

39

@staticmethod

40

def from_json(data: str, algorithm: str = None) -> 'PyJWK':

41

"""

42

Create PyJWK from JSON string.

43

44

Args:

45

data (str): JWK JSON string

46

algorithm (str): Optional algorithm override

47

48

Returns:

49

PyJWK: Initialized key object

50

"""

51

52

@property

53

def key_type(self) -> str:

54

"""Key type (kty parameter): 'RSA', 'EC', 'oct', 'OKP'."""

55

56

@property

57

def key_id(self) -> str:

58

"""Key ID (kid parameter) for key identification."""

59

60

@property

61

def public_key_use(self) -> str:

62

"""Public key use (use parameter): 'sig', 'enc', or None."""

63

64

@property

65

def algorithm_name(self) -> str:

66

"""Detected or assigned algorithm name."""

67

68

@property

69

def Algorithm(self):

70

"""Algorithm implementation object."""

71

72

@property

73

def key(self):

74

"""Underlying cryptographic key object."""

75

```

76

77

Usage examples:

78

79

```python

80

import jwt

81

from jwt import PyJWK

82

83

# RSA public key from JWK

84

rsa_jwk_data = {

85

"kty": "RSA",

86

"kid": "rsa-key-1",

87

"use": "sig",

88

"n": "base64url-encoded-modulus",

89

"e": "AQAB"

90

}

91

92

jwk = PyJWK.from_dict(rsa_jwk_data)

93

print(f"Key type: {jwk.key_type}")

94

print(f"Key ID: {jwk.key_id}")

95

print(f"Algorithm: {jwk.algorithm_name}")

96

97

# Use with JWT decoding

98

token = "eyJ..."

99

payload = jwt.decode(token, jwk.key, algorithms=[jwk.algorithm_name])

100

101

# ECDSA key with explicit algorithm

102

ec_jwk_data = {

103

"kty": "EC",

104

"kid": "ec-key-1",

105

"crv": "P-256",

106

"x": "base64url-encoded-x",

107

"y": "base64url-encoded-y"

108

}

109

110

jwk = PyJWK.from_dict(ec_jwk_data, algorithm="ES256")

111

112

# Symmetric key (HMAC)

113

oct_jwk_data = {

114

"kty": "oct",

115

"kid": "hmac-key-1",

116

"k": "base64url-encoded-secret"

117

}

118

119

jwk = PyJWK.from_dict(oct_jwk_data) # Defaults to HS256

120

```

121

122

### PyJWKSet - Key Set Management

123

124

Manages collections of JSON Web Keys with key lookup capabilities and validation.

125

126

```python { .api }

127

class PyJWKSet:

128

def __init__(self, keys: list):

129

"""

130

Initialize JWK Set from list of JWK dictionaries.

131

132

Args:

133

keys (list): List of JWK dictionaries

134

135

Raises:

136

PyJWKSetError: Invalid JWK Set or no usable keys

137

MissingCryptographyError: Required for asymmetric keys

138

"""

139

140

@staticmethod

141

def from_dict(obj: dict) -> 'PyJWKSet':

142

"""

143

Create PyJWKSet from JWKS dictionary.

144

145

Args:

146

obj (dict): JWKS dictionary with 'keys' array

147

148

Returns:

149

PyJWKSet: Initialized key set

150

"""

151

152

@staticmethod

153

def from_json(data: str) -> 'PyJWKSet':

154

"""

155

Create PyJWKSet from JWKS JSON string.

156

157

Args:

158

data (str): JWKS JSON string

159

160

Returns:

161

PyJWKSet: Initialized key set

162

"""

163

164

def __getitem__(self, kid: str) -> PyJWK:

165

"""

166

Get key by key ID.

167

168

Args:

169

kid (str): Key ID to look up

170

171

Returns:

172

PyJWK: Matching key

173

174

Raises:

175

KeyError: No key found with given ID

176

"""

177

178

@property

179

def keys(self) -> list:

180

"""List of PyJWK objects in this set."""

181

```

182

183

Usage examples:

184

185

```python

186

import jwt

187

from jwt import PyJWKSet

188

189

# JWKS from dictionary

190

jwks_data = {

191

"keys": [

192

{

193

"kty": "RSA",

194

"kid": "rsa-key-1",

195

"use": "sig",

196

"n": "modulus...",

197

"e": "AQAB"

198

},

199

{

200

"kty": "EC",

201

"kid": "ec-key-1",

202

"crv": "P-256",

203

"x": "x-coordinate...",

204

"y": "y-coordinate..."

205

}

206

]

207

}

208

209

jwk_set = PyJWKSet.from_dict(jwks_data)

210

211

# Get specific key by ID

212

key = jwk_set['rsa-key-1']

213

print(f"Found key: {key.algorithm_name}")

214

215

# Iterate through all keys

216

for jwk in jwk_set.keys:

217

print(f"Key {jwk.key_id}: {jwk.algorithm_name}")

218

219

# From JSON string

220

jwks_json = '''{"keys": [...]}'''

221

jwk_set = PyJWKSet.from_json(jwks_json)

222

223

# Use with JWT verification

224

def verify_jwt_with_jwks(token, jwk_set):

225

# Extract key ID from token header

226

unverified_header = jwt.get_unverified_header(token)

227

kid = unverified_header.get('kid')

228

229

if not kid:

230

raise ValueError("Token missing key ID")

231

232

# Get the appropriate key

233

key = jwk_set[kid]

234

235

# Verify token

236

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

237

```

238

239

### Key Type Support

240

241

PyJWK supports all standard JSON Web Key types:

242

243

#### RSA Keys (kty: "RSA")

244

245

```python

246

# RSA public key

247

rsa_public_jwk = {

248

"kty": "RSA",

249

"kid": "rsa-pub-1",

250

"use": "sig",

251

"n": "modulus-base64url", # Required

252

"e": "exponent-base64url" # Required

253

}

254

255

# RSA private key (includes all public parameters plus private)

256

rsa_private_jwk = {

257

"kty": "RSA",

258

"kid": "rsa-priv-1",

259

"use": "sig",

260

"n": "modulus-base64url",

261

"e": "exponent-base64url",

262

"d": "private-exponent-base64url", # Private key

263

# Optional CRT parameters: p, q, dp, dq, qi

264

}

265

```

266

267

#### Elliptic Curve Keys (kty: "EC")

268

269

```python

270

# ECDSA P-256 public key

271

ec_p256_jwk = {

272

"kty": "EC",

273

"kid": "ec-p256-1",

274

"crv": "P-256", # Curve: P-256, P-384, P-521, secp256k1

275

"x": "x-coordinate-base64url",

276

"y": "y-coordinate-base64url"

277

}

278

279

# ECDSA private key (includes 'd' parameter)

280

ec_private_jwk = {

281

"kty": "EC",

282

"kid": "ec-priv-1",

283

"crv": "P-256",

284

"x": "x-coordinate-base64url",

285

"y": "y-coordinate-base64url",

286

"d": "private-key-base64url" # Private key

287

}

288

```

289

290

#### Symmetric Keys (kty: "oct")

291

292

```python

293

# HMAC symmetric key

294

oct_jwk = {

295

"kty": "oct",

296

"kid": "hmac-1",

297

"k": "symmetric-key-base64url" # The symmetric key material

298

}

299

```

300

301

#### EdDSA Keys (kty: "OKP")

302

303

```python

304

# Ed25519 public key

305

ed25519_jwk = {

306

"kty": "OKP",

307

"kid": "ed25519-1",

308

"crv": "Ed25519", # Or "Ed448"

309

"x": "public-key-base64url"

310

}

311

312

# Ed25519 private key

313

ed25519_private_jwk = {

314

"kty": "OKP",

315

"kid": "ed25519-priv-1",

316

"crv": "Ed25519",

317

"x": "public-key-base64url",

318

"d": "private-key-base64url" # Private key

319

}

320

```

321

322

### Algorithm Detection

323

324

PyJWK automatically detects appropriate algorithms based on key type and curve:

325

326

| Key Type | Curve/Size | Default Algorithm |

327

|----------|------------|-------------------|

328

| RSA | Any | RS256 |

329

| EC | P-256 | ES256 |

330

| EC | P-384 | ES384 |

331

| EC | P-521 | ES512 |

332

| EC | secp256k1 | ES256K |

333

| oct | Any | HS256 |

334

| OKP | Ed25519 | EdDSA |

335

| OKP | Ed448 | EdDSA |

336

337

```python

338

# Algorithm detection examples

339

rsa_jwk = PyJWK.from_dict({"kty": "RSA", "n": "...", "e": "AQAB"})

340

print(rsa_jwk.algorithm_name) # "RS256"

341

342

ec_jwk = PyJWK.from_dict({"kty": "EC", "crv": "P-384", "x": "...", "y": "..."})

343

print(ec_jwk.algorithm_name) # "ES384"

344

345

# Override automatic detection

346

forced_jwk = PyJWK.from_dict(rsa_jwk_data, algorithm="PS256")

347

print(forced_jwk.algorithm_name) # "PS256"

348

```

349

350

### Error Handling

351

352

Common JWK-related exceptions:

353

354

```python

355

import jwt

356

from jwt.exceptions import PyJWKError, InvalidKeyError, MissingCryptographyError

357

358

try:

359

jwk = PyJWK.from_dict(invalid_jwk_data)

360

except InvalidKeyError as e:

361

print(f"Invalid key format: {e}")

362

except MissingCryptographyError as e:

363

print(f"Install cryptography: {e}")

364

except PyJWKError as e:

365

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

366

367

try:

368

key = jwk_set['nonexistent-kid']

369

except KeyError as e:

370

print(f"Key not found: {e}")

371

```