19
19
from .hmac import SYMKey
20
20
21
21
22
- def key_from_jwk_dict (jwk_dict ):
22
+ EC_PUBLIC_REQUIRED = frozenset (['crv' , 'x' , 'y' ])
23
+ EC_PUBLIC = EC_PUBLIC_REQUIRED
24
+ EC_PRIVATE_REQUIRED = frozenset (['d' ])
25
+ EC_PRIVATE_OPTIONAL = frozenset ()
26
+ EC_PRIVATE = EC_PRIVATE_REQUIRED | EC_PRIVATE_OPTIONAL
27
+
28
+ RSA_PUBLIC_REQUIRED = frozenset (['e' , 'n' ])
29
+ RSA_PUBLIC = RSA_PUBLIC_REQUIRED
30
+ RSA_PRIVATE_REQUIRED = frozenset (['p' , 'q' , 'd' ])
31
+ RSA_PRIVATE_OPTIONAL = frozenset (['qi' , 'dp' , 'dq' ])
32
+ RSA_PRIVATE = RSA_PRIVATE_REQUIRED | RSA_PRIVATE_OPTIONAL
33
+
34
+
35
+ def ensure_ec_params (jwk_dict , private ):
36
+ """Ensure all required EC parameters are present in dictionary"""
37
+ provided = frozenset (jwk_dict .keys ())
38
+ if private is not None and private :
39
+ required = EC_PUBLIC_REQUIRED | EC_PRIVATE_REQUIRED
40
+ else :
41
+ required = EC_PUBLIC_REQUIRED
42
+ return ensure_params ('EC' , provided , required )
43
+
44
+
45
+ def ensure_rsa_params (jwk_dict , private ):
46
+ """Ensure all required RSA parameters are present in dictionary"""
47
+ provided = frozenset (jwk_dict .keys ())
48
+ if private is not None and private :
49
+ required = RSA_PUBLIC_REQUIRED | RSA_PRIVATE_REQUIRED
50
+ else :
51
+ required = RSA_PUBLIC_REQUIRED
52
+ return ensure_params ('RSA' , provided , required )
53
+
54
+
55
+ def ensure_params (kty , provided , required ):
56
+ """Ensure all required parameters are present in dictionary"""
57
+ if not required <= provided :
58
+ missing = required - provided
59
+ raise MissingValue ('Missing properties for kty={}, {}' .format (kty , str (list (missing ))))
60
+
61
+
62
+ def key_from_jwk_dict (jwk_dict , private = None ):
23
63
"""Load JWK from dictionary
24
64
25
65
:param jwk_dict: Dictionary representing a JWK
@@ -28,7 +68,17 @@ def key_from_jwk_dict(jwk_dict):
28
68
# uncouple from the original item
29
69
_jwk_dict = copy .copy (jwk_dict )
30
70
71
+ if 'kty' not in _jwk_dict :
72
+ raise MissingValue ('kty missing' )
73
+
31
74
if _jwk_dict ['kty' ] == 'EC' :
75
+ ensure_ec_params (_jwk_dict , private )
76
+
77
+ if private is not None and not private :
78
+ # remove private components
79
+ for v in EC_PRIVATE :
80
+ _jwk_dict .pop (v , None )
81
+
32
82
if _jwk_dict ["crv" ] in NIST2SEC :
33
83
curve = NIST2SEC [_jwk_dict ["crv" ]]()
34
84
else :
@@ -50,6 +100,13 @@ def key_from_jwk_dict(jwk_dict):
50
100
backends .default_backend ())
51
101
return ECKey (** _jwk_dict )
52
102
elif _jwk_dict ['kty' ] == 'RSA' :
103
+ ensure_rsa_params (_jwk_dict , private )
104
+
105
+ if private is not None and not private :
106
+ # remove private components
107
+ for v in RSA_PRIVATE :
108
+ _jwk_dict .pop (v , None )
109
+
53
110
rsa_pub_numbers = rsa .RSAPublicNumbers (
54
111
base64url_to_long (_jwk_dict ["e" ]),
55
112
base64url_to_long (_jwk_dict ["n" ]))
@@ -81,13 +138,13 @@ def key_from_jwk_dict(jwk_dict):
81
138
else :
82
139
_jwk_dict ['pub_key' ] = rsa_pub_numbers .public_key (
83
140
backends .default_backend ())
84
-
141
+
85
142
if _jwk_dict ['kty' ] != "RSA" :
86
143
raise WrongKeyType ('"{}" should have been "RSA"' .format (_jwk_dict [
87
144
'kty' ]))
88
145
return RSAKey (** _jwk_dict )
89
146
elif _jwk_dict ['kty' ] == 'oct' :
90
- if not 'key' in _jwk_dict and not 'k' in _jwk_dict :
147
+ if 'key' not in _jwk_dict and 'k' not in _jwk_dict :
91
148
raise MissingValue (
92
149
'There has to be one of "k" or "key" in a symmetric key' )
93
150
0 commit comments