Пример #1
0
def verify_signature(request, key_id, headers, signature):
    # Fetch the key
    req = requests.get(key_id, headers={"Accept": "application/ld+json"})
    pubkey = req.json()["publicKey"]["publicKeyPem"]

    #verify
    digest = request.META.get("HTTP_DIGEST", None)
    request_headers = {
        "signature": signature,
        "host": request.get_host(),
        "date": request.META['HTTP_DATE'],
        "content-type": request.META["CONTENT_TYPE"]
    }
    if digest:
        new_digest = hashlib.sha256()
        new_digest.update(request.body)
        new_digest = base64.encodestring(new_digest.digest()).strip()
        request_headers["digest"] = (b"SHA-256=" + new_digest).decode("UTF-8")

    # TODO: check date stamp to avoid replay attacks
    # TODO: check attribution

    hv = HeaderVerifier(request_headers,
                        pubkey,
                        headers,
                        request.method,
                        request.path,
                        sign_header='Signature')
    return hv.verify()
Пример #2
0
 def authenticate(self, request):
     """
     Perform the actual authentication.
     
     Note that the exception raised is always the same. This is so that we
     don't leak information about in/valid keyIds and other such useful
     things.
     """
     auth_header = authentication.get_authorization_header(request)
     if not auth_header or len(auth_header) == 0:
         return None
     
     method, fields = utils.parse_authorization_header(auth_header)
     
     # Ignore foreign Authorization headers.
     if method.lower() != 'signature':
         return None
     
     # Verify basic header structure.
     if len(fields) == 0:
         raise FAILED
     
     # Ensure all required fields were included.
     if len(set(("keyid","algorithm","signature")) - set(fields.keys())) > 0:
         raise FAILED
     
     # Fetch the secret associated with the keyid
     user, secret = self.fetch_user_data(
         fields["keyid"],
         algorithm=fields["algorithm"]
         )
     
     if not (user and secret):
         raise FAILED
     
     # Gather all request headers and translate them as stated in the Django docs:
     # https://docs.djangoproject.com/en/1.6/ref/request-response/#django.http.HttpRequest.META
     headers = {}
     for key in request.META.keys():
         if key.startswith("HTTP_") or \
             key in ("CONTENT_TYPE", "CONTENT_LENGTH"):
             
             header = key[5:].lower().replace('_', '-')
             headers[header] = request.META[key]
     
     # Verify headers
     hs = HeaderVerifier(
         headers,
         secret,
         required_headers=self.required_headers,
         method=request.method.lower(),
         path=request.get_full_path()
         )
     
     # All of that just to get to this.
     if not hs.verify():
         raise FAILED            
     
     return (user, fields["keyid"])
    def authenticate(self, request):
        """
        Perform the actual authentication.

        Note that the exception raised is always the same. This is so that we
        don't leak information about in/valid keyIds and other such useful
        things.
        """

        auth_header = authentication.get_authorization_header(request)
        if not auth_header or len(auth_header) == 0:
            return None

        method, fields = utils.parse_authorization_header(auth_header)

        # Ignore foreign Authorization headers.
        if method.lower() != 'signature':
            return None

        # Verify basic header structure.
        if len(fields) == 0:
            raise FAILED

        # Ensure all required fields were included.
        if len(set(("keyid", "algorithm", "signature")) -
               set(fields.keys())) > 0:
            raise FAILED

        # Fetch the secret associated with the keyid
        try:
            user, secret = self.fetch_user_data(fields['keyid'],
                                                algorithm=fields["algorithm"])
        except Exception as ex:
            print('Received Exception: {}'.format(ex))

        if not (user and secret):
            raise FAILED

        # Gather all request headers and translate them as stated in the Django docs:
        # https://docs.djangoproject.com/en/1.6/ref/request-response/#django.http.HttpRequest.META
        headers = {}
        for key in request.META.keys():
            if key.startswith("HTTP_") or \
                            key in ("CONTENT_TYPE", "CONTENT_LENGTH"):
                header = key[5:].lower().replace('_', '-')
                headers[header] = request.META[key]

        # Verify headers
        hs = HeaderVerifier(headers,
                            secret,
                            required_headers=self.required_headers,
                            method=request.method.lower(),
                            path=request.get_full_path())

        # All of that just to get to this.
        if not hs.verify():
            raise FAILED

        return user, secret
Пример #4
0
    def authenticate(self, request):

        # Check if request has a "Signature" request header.
        authorization_header = self.header_canonical('Authorization')
        auth_string = request.META.get(authorization_header)
        if not auth_string:
            raise exceptions.AuthenticationFailed('No signature provided')

        # Check for API key header.
        api_key = None
        if self.ALGORITHM.lower().startswith('rsa'):
            api_key = self.get_keyid_from_auth_string(auth_string)
        else:
            api_key_header = self.header_canonical(self.API_KEY_HEADER)
            api_key = request.META.get(api_key_header)

        if not api_key:
            raise exceptions.AuthenticationFailed('No api key provided')

        # Fetch credentials for API key from the data store.
        try:
            user, secret = self.fetch_user_data(api_key)
        except TypeError:
            raise exceptions.AuthenticationFailed('Bad API key')

        # Build string to sign from "headers" part of Signature value.
        path = request.get_full_path()
        sent_signature = request.META.get(
            self.header_canonical('Authorization'))
        host = request.META.get(self.header_canonical('Host'))
        signature_headers = self.get_headers_from_signature(sent_signature)
        unsigned = self.build_dict_to_sign(request, signature_headers)

        unsigned.update({'authorization': auth_string})

        #unsigned['date'] = unsigned['date'] + 'd'

        try:
            hv = HeaderVerifier(headers=unsigned,
                                secret=secret,
                                required_headers=self.REQUIRED_HEADERS,
                                method=request.method,
                                path=path,
                                host=host)
        except (HttpSigException, KeyError, Exception) as e:
            raise exceptions.AuthenticationFailed(str(e))

        try:
            if not hv.verify():
                raise exceptions.AuthenticationFailed('Bad signature')
        except Exception as e:
            raise exceptions.AuthenticationFailed(str(e))

        return (user, api_key)
Пример #5
0
    def is_signature_valid(self, site, request):
        """Return whether the request signature is valid for ``site``."""
        secret = site.private_key if site.is_key_algo_symmetric() else site.public_key

        x = _header_canonical("Authorization")
        sent_signature = request.META.get(x)
        signature_headers = self.get_headers_from_signature(sent_signature)
        if len({"date", "x-beacon-user"} & set(signature_headers)) != 2:
            raise exceptions.AuthenticationFailed("Headers Date and X-Beacon-User must be signed")
        if "authorization" not in signature_headers:
            signature_headers += ["authorization"]
        headers_to_sign = self.build_dict_to_verify(request, signature_headers)

        # Sign string and compare.
        verifier = HeaderVerifier(headers=headers_to_sign, secret=secret)
        return verifier.verify()
Пример #6
0
    def authenticate(self, request):
        """
        Perform the actual authentication.

        Note that the exception raised is always the same. This is so that we
        don't leak information about in/valid keyIds and other such useful
        things.
        """
        auth_header = authentication.get_authorization_header(request)
        if not auth_header or len(auth_header) == 0:
            return None

        method, fields = utils.parse_authorization_header(auth_header)

        # Ignore foreign Authorization headers.
        if method.lower() != "signature":
            return None

        # Verify basic header structure.
        if len(fields) == 0:
            raise FAILED

        # Ensure all required fields were included.
        if len(set(("keyid", "algorithm", "signature")) -
               set(fields.keys())) > 0:
            raise FAILED

        # Fetch the secret associated with the keyid
        user, secret = self.fetch_user_data(fields["keyid"],
                                            algorithm=fields["algorithm"])

        if not (user and secret):
            raise FAILED

        # Verify headers
        hs = HeaderVerifier(
            request.headers,
            secret,
            required_headers=self.required_headers,
            method=request.method.lower(),
            path=request.get_full_path(),
        )

        # All of that just to get to this.
        if not hs.verify():
            raise FAILED

        # Check if the signature is expired
        expires = request.headers.get("(expires)", None)
        try:
            expires = int(expires)
        except TypeError:
            expires = None
        if expires and time.time() > expires:
            raise FAILED

        if 'On-Behalf-Of' in request.headers:
            user = self.fetch_on_behalf_of_user(
                request.headers['On-Behalf-Of'])
            if not user:
                raise exceptions.AuthenticationFailed(
                    "On behalf of user was not found.")
            return (user, None)

        return (user, fields["keyid"])