def test_incorrect_headers(self): HOST = "example.com" METHOD = "POST" PATH = '/foo?param=value&pet=dog' hs = HeaderSigner(secret=self.sign_secret, key_id="Test", algorithm=self.algorithm, headers=[ '(request-target)', 'host', 'date', 'content-type', 'content-md5', 'content-length' ]) unsigned = { 'Host': HOST, 'Date': 'Thu, 05 Jan 2012 21:31:40 GMT', 'Content-Type': 'application/json', 'Content-MD5': 'Sd/dVLAcvNLSq16eXua5uQ==', 'Content-Length': '18', } signed = hs.sign(unsigned, method=METHOD, path=PATH) hv = HeaderVerifier(headers=signed, secret=self.verify_secret, required_headers=["some-other-header"], host=HOST, method=METHOD, path=PATH) with self.assertRaises(Exception) as ex: hv.verify()
def test_incorrect_headers(self): HOST = "example.com" METHOD = "POST" PATH = '/foo?param=value&pet=dog' hs = HeaderSigner(secret=self.sign_secret, key_id="Test", algorithm=self.algorithm, headers=[ '(request-target)', 'host', 'date', 'content-type', 'content-md5', 'content-length']) unsigned = { 'Host': HOST, 'Date': 'Thu, 05 Jan 2012 21:31:40 GMT', 'Content-Type': 'application/json', 'Content-MD5': 'Sd/dVLAcvNLSq16eXua5uQ==', 'Content-Length': '18', } signed = hs.sign(unsigned, method=METHOD, path=PATH) hv = HeaderVerifier(headers=signed, secret=self.verify_secret, required_headers=["some-other-header"], host=HOST, method=METHOD, path=PATH) with self.assertRaises(Exception) as ex: hv.verify()
def test_extra_auth_headers(self): HOST = "example.com" METHOD = "POST" PATH = '/foo?param=value&pet=dog' hs = HeaderSigner(key_id="Test", secret=self.sign_secret, algorithm=self.algorithm, headers=[ '(request-target)', 'host', 'date', 'content-type', 'content-md5', 'content-length' ]) unsigned = { 'Host': HOST, 'Date': 'Thu, 05 Jan 2012 21:31:40 GMT', 'Content-Type': 'application/json', 'Content-MD5': 'Sd/dVLAcvNLSq16eXua5uQ==', 'Content-Length': '18', } signed = hs.sign(unsigned, method=METHOD, path=PATH) hv = HeaderVerifier(headers=signed, secret=self.verify_secret, method=METHOD, path=PATH, required_headers=['date', '(request-target)']) self.assertTrue(hv.verify())
def test_incorrect_headers(self): HOST = self.header_host METHOD = self.test_method PATH = self.test_path hs = HeaderSigner(secret=self.sign_secret, key_id="Test", algorithm=self.algorithm, sign_header=self.sign_header, headers=[ '(request-target)', 'host', 'date', 'content-type', 'digest', 'content-length' ], sign_algorithm=self.sign_algorithm) unsigned = { 'Host': HOST, 'Date': self.header_date, 'Content-Type': self.header_content_type, 'Digest': self.header_digest, 'Content-Length': self.header_content_length, } signed = hs.sign(unsigned, method=METHOD, path=PATH) hv = HeaderVerifier(headers=signed, secret=self.verify_secret, required_headers=["some-other-header"], host=HOST, method=METHOD, path=PATH, sign_header=self.sign_header, sign_algorithm=self.sign_algorithm) with self.assertRaises(ValueError) as e: hv.verify() self.assertEqual(str(e.exception), 'some-other-header is a required header(s)')
def test_signed_headers(self): HOST = self.header_host METHOD = self.test_method PATH = self.test_path hs = HeaderSigner( key_id="Test", secret=self.sign_secret, algorithm=self.algorithm, sign_header=self.sign_header, headers=[ '(request-target)', 'host', 'date', 'content-type', 'digest', 'content-length' ]) unsigned = { 'Host': HOST, 'Date': self.header_date, 'Content-Type': self.header_content_type, 'Digest': self.header_digest, 'Content-Length': self.header_content_length, } signed = hs.sign(unsigned, method=METHOD, path=PATH) hv = HeaderVerifier( headers=signed, secret=self.verify_secret, host=HOST, method=METHOD, path=PATH, sign_header=self.sign_header) self.assertTrue(hv.verify())
def test_extra_auth_headers(self): HOST = "example.com" METHOD = "POST" PATH = '/foo?param=value&pet=dog' hs = HeaderSigner(key_id="Test", secret=self.sign_secret, sign_header=self.sign_header, algorithm=self.algorithm, headers=[ '(request-target)', 'host', 'date', 'content-type', 'digest', 'content-length' ], sign_algorithm=self.sign_algorithm) unsigned = { 'Host': HOST, 'Date': self.header_date, 'Content-Type': self.header_content_type, 'Digest': self.header_digest, 'Content-Length': self.header_content_length, } signed = hs.sign(unsigned, method=METHOD, path=PATH) hv = HeaderVerifier(headers=signed, secret=self.verify_secret, method=METHOD, path=PATH, sign_header=self.sign_header, required_headers=['date', '(request-target)'], sign_algorithm=self.sign_algorithm) self.assertTrue(hv.verify())
def test_extra_auth_headers(self): HOST = "example.com" METHOD = "POST" PATH = '/foo?param=value&pet=dog' hs = HeaderSigner( key_id="Test", secret=self.sign_secret, sign_header=self.sign_header, algorithm=self.algorithm, headers=[ '(request-target)', 'host', 'date', 'content-type', 'digest', 'content-length' ]) unsigned = { 'Host': HOST, 'Date': self.header_date, 'Content-Type': self.header_content_type, 'Digest': self.header_digest, 'Content-Length': self.header_content_length, } signed = hs.sign(unsigned, method=METHOD, path=PATH) hv = HeaderVerifier( headers=signed, secret=self.verify_secret, method=METHOD, path=PATH, sign_header=self.sign_header, required_headers=['date', '(request-target)']) self.assertTrue(hv.verify())
def test_incorrect_headers(self): HOST = self.header_host METHOD = self.test_method PATH = self.test_path hs = HeaderSigner(secret=self.sign_secret, key_id="Test", algorithm=self.algorithm, sign_header=self.sign_header, headers=[ '(request-target)', 'host', 'date', 'content-type', 'digest', 'content-length']) unsigned = { 'Host': HOST, 'Date': self.header_date, 'Content-Type': self.header_content_type, 'Digest': self.header_digest, 'Content-Length': self.header_content_length, } signed = hs.sign(unsigned, method=METHOD, path=PATH) hv = HeaderVerifier(headers=signed, secret=self.verify_secret, required_headers=["some-other-header"], host=HOST, method=METHOD, path=PATH, sign_header=self.sign_header) with self.assertRaises(Exception): hv.verify()
def test_signed_headers(self): HOST = self.header_host METHOD = self.test_method PATH = self.test_path hs = HeaderSigner(key_id="Test", secret=self.sign_secret, algorithm=self.algorithm, sign_header=self.sign_header, headers=[ '(request-target)', 'host', 'date', 'content-type', 'digest', 'content-length' ], sign_algorithm=self.sign_algorithm) unsigned = { 'Host': HOST, 'Date': self.header_date, 'Content-Type': self.header_content_type, 'Digest': self.header_digest, 'Content-Length': self.header_content_length, } signed = hs.sign(unsigned, method=METHOD, path=PATH) hv = HeaderVerifier(headers=signed, secret=self.verify_secret, host=HOST, method=METHOD, path=PATH, sign_header=self.sign_header, sign_algorithm=self.sign_algorithm) self.assertTrue(hv.verify())
def test_default(self): unsigned = {'Date': 'Thu, 05 Jan 2012 21:31:40 GMT'} hs = HeaderSigner(key_id="Test", secret=self.sign_secret, algorithm=self.algorithm) signed = hs.sign(unsigned) hv = HeaderVerifier(headers=signed, secret=self.verify_secret) self.assertTrue(hv.verify())
def test_default(self): unsigned = {'Date': self.header_date} hs = HeaderSigner(key_id="Test", secret=self.sign_secret, algorithm=self.algorithm) signed = hs.sign(unsigned) hv = HeaderVerifier(headers=signed, secret=self.verify_secret) self.assertTrue(hv.verify())
def test_default(self): unsigned = { 'Date': 'Thu, 05 Jan 2012 21:31:40 GMT' } hs = HeaderSigner(key_id="Test", secret=self.sign_secret, algorithm=self.algorithm) signed = hs.sign(unsigned) hv = HeaderVerifier(headers=signed, secret=self.verify_secret) self.assertTrue(hv.verify())
def test_mix_default_256_1(self): unsigned = {'Date': self.header_date} hs = HeaderSigner(key_id="Test", secret=self.other_private_key, algorithm='rsa-sha256', sign_header=self.sign_header) signed = hs.sign(unsigned) hv = HeaderVerifier(headers=signed, secret=self.public_key, sign_header=self.sign_header) self.assertFalse(hv.verify())
def test_default(self): unsigned = { 'Date': self.header_date } hs = HeaderSigner( key_id="Test", secret=self.sign_secret, algorithm=self.algorithm, sign_header=self.sign_header) signed = hs.sign(unsigned) hv = HeaderVerifier( headers=signed, secret=self.verify_secret, sign_header=self.sign_header) self.assertTrue(hv.verify())
def verify_headers(self, app, secret_key, http_method, required_headers): if http_method in ['get', 'head', 'delete']: url_path = request.full_path.rstrip("?") else: url_path = request.path current_app.logger.debug("url path: %s" % url_path) verifier = HeaderVerifier(request.headers, secret_key, required_headers=required_headers, path=url_path, method=request.method) return verifier.verify()
def verify(filename): example = json.load(open(filename, 'r')) marn_key = open(example['keyFilename'], 'r').read() hv = HeaderVerifier( headers=example, secret=marn_key, method='POST', path=example['url'], host=example['Host'], sign_header='Signature', ) return hv.verify()
def test_correct_derived_algorithm(self): unsigned = {'Date': self.header_date} hs = HeaderSigner(key_id="Test", secret=self.sign_secret, algorithm=self.algorithm, sign_header=self.sign_header, sign_algorithm=self.sign_algorithm) signed = hs.sign(unsigned) hv = HeaderVerifier(headers=signed, secret=self.verify_secret, sign_header=self.sign_header, algorithm="hs2019", sign_algorithm=self.sign_algorithm) self.assertTrue(hv.verify())
def test_algorithm_mismatch(self): unsigned = {'Date': self.header_date} hs = HeaderSigner(key_id="Test", secret=self.sign_secret, algorithm=self.algorithm, sign_header=self.sign_header, sign_algorithm=self.sign_algorithm) signed = hs.sign(unsigned) hv = HeaderVerifier(headers=signed, secret=self.verify_secret, sign_header=self.sign_header, algorithm="rsa-sha256", sign_algorithm=self.sign_algorithm) self.assertFalse(hv.verify())
async def process(self, app, headers: list = None, validate_signature: bool = True) -> Response: """Process the request with the SmartApp.""" if validate_signature and self._supports_validation: try: verifier = HeaderVerifier(headers=headers, secret=app.public_key, method='POST', path=app.path) result = verifier.verify() except Exception as ex: raise SignatureVerificationError from ex if not result: raise SignatureVerificationError response = await self._process(app) app.dispatcher.send(self.lifecycle, self, response, app) return response
def _run_validation_inner(message, ): """ Validates a message. Don't call this function directly; call validate(), above. Returns True iff the message is valid. message_id -- the primary key of an IncomingMessage that was generated by validate(). """ logger.info('%s: begin validation', message) try: key_id = message.key_id except ValueError: logger.warning('%s: message is unsigned; dropping', message) return False try: from kepi.trilby_api.models import Person actor = fetch(message.actor, Person) except json.decoder.JSONDecodeError as jde: logger.info('%s: invalid JSON; dropping: %s', message, jde) return False except UnicodeDecodeError: logger.info('%s: invalid UTF-8; dropping', message) return False if actor is None: logger.info('%s: remote actor does not exist; dropping message', message) # FIXME: If this message is an instruction to delete a remote user, # it's valid if the remote user is Gone. Need to pass this out # from fetch() somehow. return False logger.debug('%s: message signature is: %s', message, message.signature) logger.debug('%s: message body is: %s', message, message.body) logger.debug('%s: actor details are: %s', message, actor) # XXX key used to sign must "_obviously_belong_to" the actor try: key = actor.publicKey except TypeError as te: logger.info( '%s: actor has an invalid public key (%s); dropping message', message, te, ) return False logger.debug('Verifying; key=%s, path=%s, host=%s', key, message.path, message.host) logger.debug( 'All params: %s', { 'headers': { 'Content-Type': message.content_type, 'Date': message.date, 'Signature': message.signature, 'Host': message.host, 'Digest': message.digest, }, 'secret': key, 'method': 'POST', 'path': message.path, 'host': message.host, 'sign_header': 'Signature', }) hv = HeaderVerifier( headers={ 'Content-Type': message.content_type, 'Date': message.date, 'Signature': message.signature, 'Host': message.host, 'Digest': message.digest, }, secret=key, method='POST', path=message.path, host=message.host, sign_header='Signature', ) if not hv.verify(): logger.info('%s: spoofing attempt; message dropped', message) return False logger.debug('%s: validation passed!', message) return True
def test_huge_secret(self): with self.assertRaises(ValueError) as e: HeaderVerifier(secret='x' * 1000000, headers={}) self.assertEqual(str(e.exception), 'secret cant be larger than 100000 chars')
def test_none_secret(self): with self.assertRaises(ValueError) as e: HeaderVerifier(secret=None, headers={}) self.assertEqual(str(e.exception), 'secret cant be empty')