@@ -144,14 +144,27 @@ def verify_signature(self, data, signature):
144144 logging .debug (f"Signature verification failed: { str (e )} " )
145145 return False
146146
147+ @staticmethod
148+ def _compact_json (data ):
149+ """Serialize JSON without extra whitespace for shorter QR payloads."""
150+ return json .dumps (data , sort_keys = True , separators = (',' , ':' ))
151+
152+ @staticmethod
153+ def _jws_hash_algorithm ():
154+ return hashes .SHA256 ()
155+
156+ @classmethod
157+ def _jws_standard_salt_length (cls ):
158+ return cls ._jws_hash_algorithm ().digest_size
159+
147160 def sign_jws (self , data ):
148161 """Create a JWS-compact style signature (Header.Payload.Signature)"""
149162 try :
150163 header = {"alg" : "PS256" , "typ" : "JWS" }
151- header_b64 = base64 .urlsafe_b64encode (json . dumps (header , sort_keys = True ).encode ()).decode ().rstrip ('=' )
164+ header_b64 = base64 .urlsafe_b64encode (self . _compact_json (header ).encode ()).decode ().rstrip ('=' )
152165
153166 if isinstance (data , dict ):
154- payload_string = json . dumps (data , sort_keys = True )
167+ payload_string = self . _compact_json (data )
155168 else :
156169 payload_string = str (data )
157170 payload_b64 = base64 .urlsafe_b64encode (payload_string .encode ()).decode ().rstrip ('=' )
@@ -161,10 +174,10 @@ def sign_jws(self, data):
161174 signature = self .private_key .sign (
162175 signing_input .encode (),
163176 padding .PSS (
164- mgf = padding .MGF1 (hashes . SHA256 ()),
165- salt_length = padding . PSS . MAX_LENGTH
177+ mgf = padding .MGF1 (self . _jws_hash_algorithm ()),
178+ salt_length = self . _jws_standard_salt_length ()
166179 ),
167- hashes . SHA256 ()
180+ self . _jws_hash_algorithm ()
168181 )
169182 signature_b64 = base64 .urlsafe_b64encode (signature ).decode ().rstrip ('=' )
170183
@@ -189,17 +202,24 @@ def pad_b64(s):
189202
190203 signature = base64 .urlsafe_b64decode (pad_b64 (signature_b64 ))
191204 payload_json = json .loads (base64 .urlsafe_b64decode (pad_b64 (payload_b64 )).decode ())
192-
193- self .public_key .verify (
194- signature ,
195- signing_input .encode (),
196- padding .PSS (
197- mgf = padding .MGF1 (hashes .SHA256 ()),
198- salt_length = padding .PSS .MAX_LENGTH
199- ),
200- hashes .SHA256 ()
201- )
202- return True , payload_json
205+
206+ last_error = None
207+ for salt_length in (self ._jws_standard_salt_length (), padding .PSS .MAX_LENGTH ):
208+ try :
209+ self .public_key .verify (
210+ signature ,
211+ signing_input .encode (),
212+ padding .PSS (
213+ mgf = padding .MGF1 (self ._jws_hash_algorithm ()),
214+ salt_length = salt_length
215+ ),
216+ self ._jws_hash_algorithm ()
217+ )
218+ return True , payload_json
219+ except Exception as verify_error :
220+ last_error = verify_error
221+
222+ raise last_error or ValueError ("JWS verification failed" )
203223 except Exception as e :
204224 logging .debug (f"JWS verification failed: { str (e )} " )
205225 return False , None
0 commit comments