1+ """A basic class on which to build the JWS and JWE classes."""
12import json
23import logging
34
45import requests
56
67from cryptojwt .jwk import JWK
78from cryptojwt .key_bundle import KeyBundle
8-
9+ from . exception import HeaderError
910from .jwk .jwk import key_from_jwk_dict
11+ from .jwk .rsa import RSAKey
1012from .jwk .rsa import import_rsa_key
1113from .jwk .rsa import load_x509_cert
12- from .jwk . rsa import RSAKey
13- from .exception import HeaderError
14- from .utils import b64d , as_bytes , as_unicode
14+ from .utils import as_bytes
15+ from .utils import as_unicode
16+ from .utils import b64d
1517
16- logger = logging .getLogger (__name__ )
18+ LOGGER = logging .getLogger (__name__ )
1719
1820__author__ = 'Roland Hedberg'
1921
2022
21- class JWx (object ):
22- args = ["alg" , "jku" , "jwk" , "x5u" , "x5t" , "x5c" , "kid" , "typ" , "cty" ,
23- "crit" ]
24- """
23+ class JWx :
24+ """A basic class with the commonalities between the JWS and JWE classes.
25+
2526 :param alg: The signing algorithm
2627 :param jku: a URI that refers to a resource for a set of JSON-encoded
2728 public keys, one of which corresponds to the key used to digitally
@@ -45,6 +46,8 @@ class JWx(object):
4546 :param kwargs: Extra header parameters
4647 :return: A class instance
4748 """
49+ args = ["alg" , "jku" , "jwk" , "x5u" , "x5t" , "x5c" , "kid" , "typ" , "cty" ,
50+ "crit" ]
4851
4952 def __init__ (self , msg = None , with_digest = False , httpc = None , ** kwargs ):
5053 self .msg = msg
@@ -69,21 +72,7 @@ def __init__(self, msg=None, with_digest=False, httpc=None, **kwargs):
6972 continue
7073
7174 if key == "jwk" :
72- # value MUST be a string
73- if isinstance (_val , dict ):
74- _k = key_from_jwk_dict (_val )
75- self ._dict ["jwk" ] = _val
76- elif isinstance (_val , str ):
77- # verify that it's a real JWK
78- _val = json .loads (_val )
79- _j = key_from_jwk_dict (_val )
80- self ._dict ["jwk" ] = _val
81- elif isinstance (_val , JWK ):
82- self ._dict ['jwk' ] = _val .to_dict ()
83- else :
84- raise ValueError (
85- 'JWK must be a string a JSON object or a JWK '
86- 'instance' )
75+ self ._set_jwk (_val )
8776 self ._jwk = self ._dict ['jwk' ]
8877 elif key == "x5c" :
8978 self ._dict ["x5c" ] = _val
@@ -102,6 +91,20 @@ def __init__(self, msg=None, with_digest=False, httpc=None, **kwargs):
10291 else :
10392 self ._dict [key ] = _val
10493
94+ def _set_jwk (self , val ):
95+ if isinstance (val , dict ):
96+ _k = key_from_jwk_dict (val )
97+ self ._dict ["jwk" ] = val
98+ elif isinstance (val , str ):
99+ # verify that it's a real JWK
100+ _val = json .loads (val )
101+ _j = key_from_jwk_dict (_val )
102+ self ._dict ["jwk" ] = _val
103+ elif isinstance (val , JWK ):
104+ self ._dict ['jwk' ] = val .to_dict ()
105+ else :
106+ raise ValueError ('JWK must be a string a JSON object or a JWK instance' )
107+
105108 def __contains__ (self , item ):
106109 return item in self ._dict
107110
@@ -118,9 +121,31 @@ def __getattr__(self, item):
118121 raise AttributeError (item )
119122
120123 def keys (self ):
124+ """Return all keys."""
121125 return list (self ._dict .keys ())
122126
127+ def _set_header_jwk (self , header , ** kwargs ):
128+ if "jwk" in self :
129+ header ["jwk" ] = self ["jwk" ]
130+ else :
131+ try :
132+ _jwk = kwargs ['jwk' ]
133+ except KeyError :
134+ pass
135+ else :
136+ try :
137+ header ["jwk" ] = _jwk .serialize () # JWK instance
138+ except AttributeError :
139+ if isinstance (_jwk , dict ):
140+ header ['jwk' ] = _jwk # dictionary
141+ else :
142+ _d = json .loads (_jwk ) # JSON
143+ # Verify that it's a valid JWK
144+ _k = key_from_jwk_dict (_d )
145+ header ['jwk' ] = _d
146+
123147 def headers (self , ** kwargs ):
148+ """Return the JWE/JWS header."""
124149 _header = self ._header .copy ()
125150 for param in self .args :
126151 try :
@@ -132,28 +157,7 @@ def headers(self, **kwargs):
132157 except KeyError :
133158 pass
134159
135- if "jwk" in self :
136- _header ["jwk" ] = self ["jwk" ]
137- else :
138- try :
139- _jwk = kwargs ['jwk' ]
140- except KeyError :
141- pass
142- else :
143- try :
144- _header ["jwk" ] = _jwk .serialize () # JWK instance
145- except AttributeError :
146- if isinstance (_jwk , dict ):
147- _header ['jwk' ] = _jwk # dictionary
148- else :
149- try :
150- _d = json .loads (_jwk ) # JSON
151- # Verify that it's a valid JWK
152- _k = key_from_jwk_dict (_d )
153- except Exception :
154- raise
155- else :
156- _header ['jwk' ] = _d
160+ self ._set_header_jwk (_header , ** kwargs )
157161
158162 if "kid" in self :
159163 if not isinstance (self ["kid" ], str ):
@@ -170,7 +174,8 @@ def _get_keys(self):
170174 return _keys
171175
172176 def alg2keytype (self , alg ):
173- raise NotImplemented ()
177+ """Convert an algorithm identifier to a key type identifier."""
178+ raise NotImplementedError ()
174179
175180 def pick_keys (self , keys , use = "" , alg = "" ):
176181 """
@@ -190,10 +195,10 @@ def pick_keys(self, keys, use="", alg=""):
190195
191196 _k = self .alg2keytype (alg )
192197 if _k is None :
193- logger .error ("Unknown algorithm '%s'" % alg )
198+ LOGGER .error ("Unknown algorithm '%s'" , alg )
194199 raise ValueError ('Unknown cryptography algorithm' )
195200
196- logger .debug ("Picking key by key type={0}" . format ( _k ) )
201+ LOGGER .debug ("Picking key by key type=%s" , _k )
197202 _kty = [_k .lower (), _k .upper (), _k .lower ().encode ("utf-8" ),
198203 _k .upper ().encode ("utf-8" )]
199204 _keys = [k for k in keys if k .kty in _kty ]
@@ -205,14 +210,12 @@ def pick_keys(self, keys, use="", alg=""):
205210 except (AttributeError , KeyError ):
206211 _kid = None
207212
208- logger .debug ("Picking key based on alg={0}, kid={1} and use={2}" .format (
209- alg , _kid , use ))
213+ LOGGER .debug ("Picking key based on alg=%s, kid=%s and use=%s" , alg , _kid , use )
210214
211215 pkey = []
212216 for _key in _keys :
213- logger .debug (
214- "Picked: kid:{}, use:{}, kty:{}" .format (
215- _key .kid , _key .use , _key .kty ))
217+ LOGGER .debug (
218+ "Picked: kid:%s, use:%s, kty:%s" , _key .kid , _key .use , _key .kty )
216219 if _kid :
217220 if _kid != _key .kid :
218221 continue
@@ -251,4 +254,5 @@ def _decode(self, payload):
251254 return _msg
252255
253256 def dump_header (self ):
254- return dict ([(x , self ._dict [x ]) for x in self .args if x in self ._dict ])
257+ """Return all attributes with values."""
258+ return {x : self ._dict [x ] for x in self .args if x in self ._dict }
0 commit comments