22import hashlib
33import hmac
44import six
5-
6- from jose .constants import ALGORITHMS
7- from jose .exceptions import JWSError
8- from jose .exceptions import JOSEError
5+ import struct
96
107import Crypto .Hash .SHA256
118import Crypto .Hash .SHA384
1613
1714import ecdsa
1815
19- from jose .utils import constant_time_compare
16+ from jose .constants import ALGORITHMS
17+ from jose .exceptions import JWKError
18+ from jose .exceptions import JWSError
19+ from jose .exceptions import JOSEError
2020
2121
2222def get_algorithm_object (algorithm ):
@@ -25,39 +25,41 @@ def get_algorithm_object(algorithm):
2525 """
2626
2727 if algorithm == ALGORITHMS .HS256 :
28- return HMACAlgorithm ( HMACAlgorithm .SHA256 )
28+ return HMACKey ( HMACKey .SHA256 )
2929
3030 if algorithm == ALGORITHMS .HS384 :
31- return HMACAlgorithm ( HMACAlgorithm .SHA384 )
31+ return HMACKey ( HMACKey .SHA384 )
3232
3333 if algorithm == ALGORITHMS .HS512 :
34- return HMACAlgorithm ( HMACAlgorithm .SHA512 )
34+ return HMACKey ( HMACKey .SHA512 )
3535
3636 if algorithm == ALGORITHMS .RS256 :
37- return RSAAlgorithm ( RSAAlgorithm .SHA256 )
37+ return RSAKey ( RSAKey .SHA256 )
3838
3939 if algorithm == ALGORITHMS .RS384 :
40- return RSAAlgorithm ( RSAAlgorithm .SHA384 )
40+ return RSAKey ( RSAKey .SHA384 )
4141
4242 if algorithm == ALGORITHMS .RS512 :
43- return RSAAlgorithm ( RSAAlgorithm .SHA512 )
43+ return RSAKey ( RSAKey .SHA512 )
4444
4545 if algorithm == ALGORITHMS .ES256 :
46- return ECAlgorithm ( ECAlgorithm .SHA256 )
46+ return ECKey ( ECKey .SHA256 )
4747
4848 if algorithm == ALGORITHMS .ES384 :
49- return ECAlgorithm ( ECAlgorithm .SHA384 )
49+ return ECKey ( ECKey .SHA384 )
5050
5151 if algorithm == ALGORITHMS .ES512 :
52- return ECAlgorithm ( ECAlgorithm .SHA512 )
52+ return ECKey ( ECKey .SHA512 )
5353
5454 raise JWSError ('Algorithm not supported: %s' % algorithm )
5555
5656
57- class Algorithm (object ):
57+ class Key (object ):
5858 """
59- The interface for an algorithm used to sign and verify tokens.
59+ The interface for an JWK used to sign and verify tokens.
6060 """
61+ prepared_key = None
62+
6163 def process_sign (self , msg , key ):
6264 """
6365 Processes a signature for the given algorithm.
@@ -82,6 +84,22 @@ def process_prepare_key(self, key):
8284 """
8385 raise NotImplementedError
8486
87+ def process_deserilialize (self ):
88+ """
89+ Processes deserializing a key into a JWK JSON format.
90+
91+ This method should be overriden by the implementing Key class.
92+ """
93+ raise NotImplementedError
94+
95+ def process_jwk (self , jwk ):
96+ """
97+ Process a JWK dict into a Key object.
98+
99+ This method shold be overriden by the implementing Key class.
100+ """
101+ raise NotImplementedError
102+
85103 def prepare_key (self , key ):
86104 """
87105 Performs necessary validation and conversions on the key and returns
@@ -93,10 +111,13 @@ def prepare_key(self, key):
93111 TypeError: If an invalid key is attempted to be used.
94112 """
95113 try :
96- return self .process_prepare_key (key )
97- except Exception , e :
114+ key = self .process_prepare_key (key )
115+ except Exception as e :
98116 raise JOSEError (e )
99117
118+ self .prepared_key = key
119+ return key
120+
100121 def sign (self , msg , key ):
101122 """
102123 Returns a digital signature for the specified message
@@ -109,7 +130,7 @@ def sign(self, msg, key):
109130 """
110131 try :
111132 return self .process_sign (msg , key )
112- except Exception , e :
133+ except Exception as e :
113134 raise JOSEError (e )
114135
115136 def verify (self , msg , key , sig ):
@@ -124,11 +145,11 @@ def verify(self, msg, key, sig):
124145 """
125146 try :
126147 return self .process_verify (msg , key , sig )
127- except Exception , e :
148+ except Exception as e :
128149 raise JOSEError (e )
129150
130151
131- class HMACAlgorithm ( Algorithm ):
152+ class HMACKey ( Key ):
132153 """
133154 Performs signing and verification operations using HMAC
134155 and the specified hash function.
@@ -164,10 +185,10 @@ def process_sign(self, msg, key):
164185 return hmac .new (key , msg , self .hash_alg ).digest ()
165186
166187 def process_verify (self , msg , key , sig ):
167- return constant_time_compare ( sig , self .sign (msg , key ) )
188+ return sig == self .sign (msg , key )
168189
169190
170- class RSAAlgorithm ( Algorithm ):
191+ class RSAKey ( Key ):
171192 """
172193 Performs signing and verification operations using
173194 RSASSA-PKCS-v1_5 and the specified hash function.
@@ -183,9 +204,12 @@ def __init__(self, hash_alg):
183204
184205 def process_prepare_key (self , key ):
185206
186- if isinstance (key , RSA ._RSAobj ):
207+ if isinstance (key , ( RSA ._RSAobj , RSAKey ) ):
187208 return key
188209
210+ if isinstance (key , dict ):
211+ return self .process_jwk (key )
212+
189213 if isinstance (key , six .string_types ):
190214 if isinstance (key , six .text_type ):
191215 key = key .encode ('utf-8' )
@@ -196,14 +220,33 @@ def process_prepare_key(self, key):
196220
197221 return key
198222
223+ def process_jwk (self , jwk ):
224+
225+ def urlsafe_b64decode (encoded ):
226+ import base64
227+ if not encoded :
228+ return encoded
229+ modulo = len (encoded ) % 4
230+ if modulo != 0 :
231+ encoded += ('=' * (4 - modulo ))
232+ return base64 .b64decode (encoded )
233+
234+ if not jwk .get ('kty' ) == 'RSA' :
235+ raise JWKError ("Incorrect key type. Expected: 'RSA', Recieved: %s" % jwk .get ('kty' ))
236+
237+ e = bytes (jwk .get ('e' , 256 ))
238+ n = bytes (jwk .get ('n' ))
239+
240+ return RSA .construct ((long (n ), long (e )))
241+
199242 def process_sign (self , msg , key ):
200243 return PKCS1_v1_5 .new (key ).sign (self .hash_alg .new (msg ))
201244
202245 def process_verify (self , msg , key , sig ):
203246 return PKCS1_v1_5 .new (key ).verify (self .hash_alg .new (msg ), sig )
204247
205248
206- class ECAlgorithm ( Algorithm ):
249+ class ECKey ( Key ):
207250 """
208251 Performs signing and verification operations using
209252 ECDSA and the specified hash function
0 commit comments