def _verify_signature(payload, signing_input, header, signature, key='', algorithms=None): alg = header.get('alg') if not alg: raise JWSError('No algorithm was specified in the JWS header.') if algorithms is not None and alg not in algorithms: raise JWSError('The specified alg value is not allowed') try: alg_obj = get_algorithm_object(alg) key = alg_obj.prepare_key(key) if not alg_obj.verify(signing_input, key, signature): raise JWSSignatureError() except JWSSignatureError: raise JWSError('Signature verification failed.') except JWSError: raise JWSError('Invalid or unsupported algorithm: %s' % alg)
def sign(payload, key, headers=None, algorithm=ALGORITHMS.HS256): """Signs a claims set and returns a JWS string. Args: payload (str): A string to sign key (str or dict): The key to use for signing the claim set. Can be individual JWK or JWK set. headers (dict, optional): A set of headers that will be added to the default headers. Any headers that are added as additional headers will override the default headers. algorithm (str, optional): The algorithm to use for signing the the claims. Defaults to HS256. Returns: str: The string representation of the header, claims, and signature. Raises: JWSError: If there is an error signing the token. Examples: >>> jws.sign({'a': 'b'}, 'secret', algorithm='HS256') 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhIjoiYiJ9.jiMyrsmD8AoHWeQgmxZ5yq8z0lXS67_QGs52AzC8Ru8' """ if algorithm not in ALGORITHMS.SUPPORTED: raise JWSError('Algorithm %s not supported.' % algorithm) encoded_header = _encode_header(algorithm, additional_headers=headers) encoded_payload = _encode_payload(payload) signed_output = _sign_header_and_claims(encoded_header, encoded_payload, algorithm, key) return signed_output
def get_algorithm_object(algorithm): """ Returns an algorithm object for the given algorithm. """ if algorithm == ALGORITHMS.HS256: return HMACKey(HMACKey.SHA256) if algorithm == ALGORITHMS.HS384: return HMACKey(HMACKey.SHA384) if algorithm == ALGORITHMS.HS512: return HMACKey(HMACKey.SHA512) if algorithm == ALGORITHMS.RS256: return RSAKey(RSAKey.SHA256) if algorithm == ALGORITHMS.RS384: return RSAKey(RSAKey.SHA384) if algorithm == ALGORITHMS.RS512: return RSAKey(RSAKey.SHA512) if algorithm == ALGORITHMS.ES256: return ECKey(ECKey.SHA256) if algorithm == ALGORITHMS.ES384: return ECKey(ECKey.SHA384) if algorithm == ALGORITHMS.ES512: return ECKey(ECKey.SHA512) raise JWSError('Algorithm not supported: %s' % algorithm)
def _verify_signature(signing_input, header, signature, key="", algorithms=None): alg = header.get("alg") if not alg: raise JWSError("No algorithm was specified in the JWS header.") if algorithms is not None and alg not in algorithms: raise JWSError("The specified alg value is not allowed") keys = _get_keys(key) try: if not _sig_matches_keys(keys, signing_input, signature, alg): raise JWSSignatureError() except JWSSignatureError: raise JWSError("Signature verification failed.") except JWSError: raise JWSError("Invalid or unsupported algorithm: %s" % alg)
def _verify_signature(signing_input, header, signature, key='', algorithms=None): alg = header.get('alg') if not alg: raise JWSError('No algorithm was specified in the JWS header.') if algorithms is not None and alg not in algorithms: raise JWSError('The specified alg value is not allowed') try: key = jwk.construct(key, alg) if not key.verify(signing_input, signature): raise JWSSignatureError() except JWSSignatureError: raise JWSError('Signature verification failed.') except JWSError: raise JWSError('Invalid or unsupported algorithm: %s' % alg)
def _verify_signature(signing_input, header, signature, key='', algorithms=None): alg = header.get('alg') if not alg: raise JWSError('No algorithm was specified in the JWS header.') if algorithms is not None and alg not in algorithms: raise JWSError('The specified alg value is not allowed') logger.info(f'00. key: {key}') keys = _get_keys(key) logger.info(f'01. keys: {keys}') try: if not _sig_matches_keys(keys, signing_input, signature, alg): raise JWSSignatureError() except JWSSignatureError: raise JWSError('Signature verification failed.') except JWSError: raise JWSError('Invalid or unsupported algorithm: %s' % alg)
def _load(jwt): if isinstance(jwt, six.text_type): jwt = jwt.encode('utf-8') try: signing_input, crypto_segment = jwt.rsplit(b'.', 1) header_segment, claims_segment = signing_input.split(b'.', 1) header_data = base64url_decode(header_segment) except ValueError: raise JWSError('Not enough segments') except (TypeError, binascii.Error): raise JWSError('Invalid header padding') try: header = json.loads(header_data.decode('utf-8')) except ValueError as e: raise JWSError('Invalid header string: %s' % e) if not isinstance(header, Mapping): raise JWSError('Invalid header string: must be a json object') try: payload = base64url_decode(claims_segment) except (TypeError, binascii.Error): raise JWSError('Invalid payload padding') try: signature = base64url_decode(crypto_segment) except (TypeError, binascii.Error): raise JWSError('Invalid crypto padding') return (header, payload, signing_input, signature)
def _sign_header_and_claims(encoded_header, encoded_claims, algorithm, key_data): signing_input = b'.'.join([encoded_header, encoded_claims]) try: key = jwk.construct(key_data, algorithm) signature = key.sign(signing_input) except Exception as e: raise JWSError(e) encoded_signature = base64url_encode(signature) encoded_string = b'.'.join([encoded_header, encoded_claims, encoded_signature]) return encoded_string.decode('utf-8')
def _sign_header_and_claims(encoded_header, encoded_claims, algorithm, key): signing_input = b".".join([encoded_header, encoded_claims]) try: if not isinstance(key, Key): key = jwk.construct(key, algorithm) signature = key.sign(signing_input) except Exception as e: raise JWSError(e) encoded_signature = base64url_encode(signature) encoded_string = b".".join([encoded_header, encoded_claims, encoded_signature]) return encoded_string.decode("utf-8")
def _sign_header_and_claims(encoded_header, encoded_claims, algorithm, key): signing_input = b'.'.join([encoded_header, encoded_claims]) try: alg_obj = get_algorithm_object(algorithm) key = alg_obj.prepare_key(key) signature = alg_obj.sign(signing_input, key) except Exception as e: raise JWSError(e) encoded_signature = base64url_encode(signature) encoded_string = b'.'.join( [encoded_header, encoded_claims, encoded_signature]) return encoded_string.decode('utf-8')
def jws(self, keyname=None): """Assumes you loaded a payload. Return the same jws or raise a custom exception.""" key_material = self._get_public_key(keyname) if isinstance(key_material, list): logger.debug("Multiple keys returned. Attempting match.") for key in key_material: key.pop("x5t", None) key.pop("x5c", None) logger.info("Attempting to match against: {}".format(key)) try: sig = jws.verify(self.jws_signature, key, algorithms="RS256", verify=True) logger.info( "Matched a verified signature for: {}".format(key)) return sig except JWSError as e: logger.error(e) raise JWSError( "The signature could not be verified for any trusted key.")
def jws(self, keyname=None): """Assumes you loaded a payload. Return the same jws or raise a custom exception.""" key_material = self._get_public_key(keyname) logger.debug( "The key material for the payload was loaded for: {}".format( keyname), extra={"key_material": key_material}) if isinstance(key_material, list): logger.debug("Multiple keys returned. Attempting match.") for key in key_material: try: key.pop("x5t", None) key.pop("x5c", None) except AttributeError: logger.warn( "x5t and x5c attrs do not exist in key material.") logger.debug("Attempting to match against: {}".format(key)) try: sig = jws.verify(self.jws_signature, key, algorithms="RS256", verify=True) logger.debug( "Matched a verified signature for: {}".format(key), extra={"signature": self.jws_signature}) return sig except JWSError as e: logger.error( "The signature was not valid for the payload.", extra={"signature": self.jws_signature}) logger.error(e) raise JWSError( "The signature could not be verified for any trusted key", key_material)