70 lines
2.5 KiB
Python
70 lines
2.5 KiB
Python
from __future__ import absolute_import
|
|
|
|
import jws.algos as algos
|
|
|
|
from .exceptions import AlgorithmNotImplemented, ParameterNotImplemented, ParameterNotUnderstood, RouteMissingError
|
|
|
|
class HeaderBase(object):
|
|
def __init__(self, name, value, data):
|
|
self.name = name
|
|
self.value = self.clean(value)
|
|
self.data = data
|
|
def sign(self): return self.value
|
|
def verify(self): return self.value
|
|
def clean(self, value): return value
|
|
|
|
class GenericString(HeaderBase):
|
|
def clean(self, value):
|
|
return str(value)
|
|
|
|
class SignNotImplemented(HeaderBase):
|
|
def sign(self):
|
|
raise ParameterNotImplemented("Header Parameter %s not implemented in the context of signing" % self.name)
|
|
|
|
class VerifyNotImplemented(HeaderBase):
|
|
def verify(self):
|
|
raise ParameterNotImplemented("Header Parameter %s not implemented in the context of verifying" % self.name)
|
|
|
|
class NotImplemented(HeaderBase):
|
|
def clean(self, *a):
|
|
raise ParameterNotUnderstood("Could not find an action for Header Parameter '%s'" % self.name)
|
|
|
|
class Algorithm(HeaderBase):
|
|
def clean(self, value):
|
|
try:
|
|
self.methods = algos.route(value)
|
|
except RouteMissingError as e:
|
|
raise AlgorithmNotImplemented('"%s" not implemented.' % value)
|
|
|
|
def sign(self):
|
|
self.data['signer'] = self.methods['sign']
|
|
def verify(self):
|
|
self.data['verifier'] = self.methods['verify']
|
|
|
|
KNOWN_HEADERS = {
|
|
# REQUIRED, signing algo, see signing_methods
|
|
'alg': Algorithm,
|
|
# OPTIONAL, type of signed content
|
|
'typ': GenericString,
|
|
# OPTIONAL, JSON Key URL. See http://self-issued.info/docs/draft-jones-json-web-key.html
|
|
'jku': VerifyNotImplemented,
|
|
# OPTIONAL, key id, hint for which key to use.
|
|
'kid': VerifyNotImplemented,
|
|
# OPTIONAL, x.509 URL pointing to certificate or certificate chain
|
|
'x5u': VerifyNotImplemented,
|
|
# OPTIONAL, x.509 certificate thumbprint
|
|
'x5t': VerifyNotImplemented,
|
|
}
|
|
|
|
# data is by reference
|
|
def process(data, step):
|
|
for param in data['header']:
|
|
# The JWS Header Input MUST be validated to only include parameters
|
|
# and values whose syntax and semantics are both understood and
|
|
# supported. --- this is why it defaults to NotImplemented, which
|
|
# raises an exception
|
|
cls = KNOWN_HEADERS.get(param, NotImplemented)
|
|
instance = cls(param, data['header'][param], data)
|
|
procedure = getattr(instance, step)
|
|
procedure()
|
|
return data
|