Skip to content

Commit 80c3ad4

Browse files
committed
add functions to generate a similar key (same kty, crv, size)
1 parent f105494 commit 80c3ad4

File tree

2 files changed

+64
-0
lines changed

2 files changed

+64
-0
lines changed

jwcrypto/jwk.py

+12
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,18 @@ def generate_key(self, **params):
368368

369369
gen(params)
370370

371+
@classmethod
372+
def generate_similar(cls, key):
373+
return cls.generate(**key.get_generate_params())
374+
375+
def get_generate_params(self):
376+
params = {param: self.get(param) for param in ["kty", "crv", "use", "key_ops"] if param in self}
377+
if self.get("kty") == "RSA":
378+
params["size"] = self._get_public_key().key_size
379+
elif self.get("kty") == "oct":
380+
params["size"] = len(base64url_decode(self.k)) * 8
381+
return params
382+
371383
def _get_gen_size(self, params, default_size=None):
372384
size = default_size
373385
if 'size' in params:

jwcrypto/tests.py

+52
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,58 @@ def test_jwk_from_json(self):
506506
y = jwk.JWK.from_json(k.export())
507507
self.assertEqual(k.export(), y.export())
508508

509+
def test_generate_similar(self):
510+
KEY_PARAMS = [
511+
{
512+
"kty": "oct",
513+
"size": 192
514+
},
515+
{
516+
"kty": "RSA",
517+
"size": 3072
518+
},
519+
{
520+
"kty": "EC",
521+
"crv": "P-256"
522+
},
523+
{
524+
"kty": "EC",
525+
"crv": "P-384",
526+
},
527+
{
528+
"kty": "OKP",
529+
"crv": "Ed25519"
530+
},
531+
{
532+
"kty": "OKP",
533+
"crv": "Ed448"
534+
},
535+
{
536+
"kty": "OKP",
537+
"crv": "X25519"
538+
},
539+
{
540+
"kty": "OKP",
541+
"crv": "X448"
542+
},
543+
{
544+
"kty": "RSA",
545+
"size": 3072,
546+
"use": "sig"
547+
},
548+
{
549+
"kty": "oct",
550+
"size": 256,
551+
"key_ops": "sign"
552+
},
553+
]
554+
for params in KEY_PARAMS:
555+
key1 = jwk.JWK.generate(**params)
556+
key2 = jwk.JWK.generate_similar(key1)
557+
for prop in ["kty", "crv", "use", "key_ops"]:
558+
self.assertEqual(key1.get(prop), key2.get(prop))
559+
self.assertEqual(type(key1.get_op_key("sign")), type(key2.get_op_key("sign")))
560+
509561
def test_jwkset(self):
510562
k = jwk.JWK(**RSAPrivateKey)
511563
ks = jwk.JWKSet()

0 commit comments

Comments
 (0)