Skip to content

Commit

Permalink
Add method to export Keys ans Sets as dictionaries
Browse files Browse the repository at this point in the history
This allows to avoid json_decoding again to manipulate the exported
data.

Signed-off-by: Simo Sorce <simo@redhat.com>
  • Loading branch information
simo5 committed Apr 23, 2020
1 parent 9e29ac7 commit 544cdf2
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 13 deletions.
39 changes: 26 additions & 13 deletions jwcrypto/jwk.py
Expand Up @@ -576,7 +576,7 @@ def from_json(cls, key):
obj.import_key(**jkey)
return obj

def export(self, private_key=True):
def export(self, private_key=True, as_dict=False):
"""Exports the key in the standard JSON format.
Exports the key regardless of type, if private_key is False
and the key is_symmetric an exceptionis raised.
Expand All @@ -587,16 +587,20 @@ def export(self, private_key=True):
if private_key is True:
# Use _export_all for backwards compatibility, as this
# function allows to export symmetrict keys too
return self._export_all()
else:
return self.export_public()
return self._export_all(as_dict)

return self.export_public(as_dict)

def export_public(self):
def export_public(self, as_dict=False):
"""Exports the public key in the standard JSON format.
It fails if one is not available like when this function
is called on a symmetric key.
:param as_dict(bool): If set to True export as python dict not JSON
"""
pub = self._public_params()
if as_dict is True:
return pub
return json_encode(pub)

def _public_params(self):
Expand All @@ -614,24 +618,28 @@ def _public_params(self):
pub[param] = self._key[param]
return pub

def _export_all(self):
def _export_all(self, as_dict=False):
d = dict()
d.update(self._params)
d.update(self._key)
d.update(self._unknown)
if as_dict is True:
return d
return json_encode(d)

def export_private(self):
def export_private(self, as_dict=False):
"""Export the private key in the standard JSON format.
It fails for a JWK that has only a public key or is symmetric.
:param as_dict(bool): If set to True export as python dict not JSON
"""
if self.has_private:
return self._export_all()
return self._export_all(as_dict)
raise InvalidJWKType("No private key available")

def export_symmetric(self):
def export_symmetric(self, as_dict=False):
if self.is_symmetric:
return self._export_all()
return self._export_all(as_dict)
raise InvalidJWKType("Not a symmetric key")

def public(self):
Expand Down Expand Up @@ -975,20 +983,25 @@ def update(self, *args, **kwargs):
def add(self, elem):
self['keys'].add(elem)

def export(self, private_keys=True):
"""Exports a RFC 7517 keyset using the standard JSON format
def export(self, private_keys=True, as_dict=False):
"""Exports a RFC 7517 keyset.
Exports as json by default, or as dict if requested.
:param private_key(bool): Whether to export private keys.
Defaults to True.
:param as_dict(bool): Whether to retun a dict instead of
a JSON object
"""
exp_dict = dict()
for k, v in iteritems(self):
if k == 'keys':
keys = list()
for jwk in v:
keys.append(json_decode(jwk.export(private_keys)))
keys.append(jwk.export(private_keys, as_dict=True))
v = keys
exp_dict[k] = v
if as_dict is True:
return exp_dict
return json_encode(exp_dict)

def import_keyset(self, keyset):
Expand Down
15 changes: 15 additions & 0 deletions jwcrypto/tests.py
Expand Up @@ -458,6 +458,21 @@ def test_export_private(self):
self.assertFalse(pubkey.has_private)
self.assertEqual(prikey.key_id, pubkey.key_id)

def test_export_as_dict(self):
key = jwk.JWK(**SymmetricKeys['keys'][1])
k = key.export_symmetric(as_dict=True)
self.assertEqual(k['kid'], SymmetricKeys['keys'][1]['kid'])
key = jwk.JWK.from_pem(PublicCert)
k = key.export_public(as_dict=True)
self.assertEqual(k['kid'], PublicCertThumbprint)
key = jwk.JWK.from_pem(RSAPrivatePEM, password=RSAPrivatePassword)
k = key.export_private(as_dict=True)
self.assertEqual(k['kid'],
u'x31vrbZceU2qOPLtrUwPkLa3PNakMn9tOsq_ntFVrJc')
keyset = jwk.JWKSet.from_json(json_encode(PrivateKeys))
ks = keyset.export(as_dict=True)
self.assertTrue('keys' in ks)

def test_public(self):
key = jwk.JWK.from_pem(RSAPrivatePEM, password=RSAPrivatePassword)
self.assertTrue(key.has_public)
Expand Down

0 comments on commit 544cdf2

Please sign in to comment.