コード例 #1
0
    async def test_negative_timestamp(self):

        signing_key = TEST_PRIVATE_KEY
        timestamp = int(time.time())
        signature = sign_request(signing_key, "GET", "/", timestamp, None)

        resp = await self.fetch_signed("/",
                                       method="GET",
                                       address=TEST_ADDRESS,
                                       timestamp=timestamp,
                                       signature=signature)

        self.assertResponseCodeEqual(resp, 204)

        # try replay simply changing the timestamp to negative
        timestamp = -timestamp
        resp = await self.fetch_signed("/",
                                       method="GET",
                                       address=TEST_ADDRESS,
                                       timestamp=timestamp,
                                       signature=signature)

        self.assertResponseCodeEqual(resp, 400)

        # sign with negative timestamp
        signature = sign_request(signing_key, "GET", "/", timestamp, None)
        resp = await self.fetch_signed("/",
                                       method="GET",
                                       address=TEST_ADDRESS,
                                       timestamp=timestamp,
                                       signature=signature)

        self.assertResponseCodeEqual(resp, 400)
コード例 #2
0
    def fetch_signed(self, path, *, signing_key=None, signature=None, timestamp=None, address=None, **kwargs):

        if not isinstance(path, str) or not path.startswith("/"):
            # for simplicity's sake, don't accept HTTPRequest objects or external urls in the tests
            raise Exception("first argument must be path string starting with a / (e.g. /v1/tx)")

        # find out if there's a path prefix added by get_url
        prefix = "/{}".format(self.get_url(path).split('/', 3)[-1]).split(path)[0]

        headers = kwargs.setdefault('headers', tornado.httputil.HTTPHeaders())

        if 'body' in kwargs:
            body = kwargs.pop('body')
            if isinstance(body, dict):
                headers['Content-Type'] = "application/json"
                body = tornado.escape.json_encode(body).encode('utf-8')
            elif isinstance(body, str):
                # try and find the charset to use to encode this
                if 'Content-Type' in headers:
                    idx = headers['Content-Type'].find('charset=')
                    if idx >= 0:
                        charset = headers['Content-Type'][idx + 8:]
                        idx = charset.find(';')
                        if idx >= 0:
                            charset = charset[:idx]
                    else:
                        charset = 'utf-8'
                else:
                    charset = 'utf-8'
                # encode to a byte string
                body = body.encode(charset)
            elif not isinstance(body, bytes):
                raise Exception("Unable to handle bodys of type '{}'".format(type(body)))
        else:
            body = None

        method = kwargs.setdefault('method', 'GET').upper()

        if signing_key is None and (address is None or signature is None):
            raise Exception("signing_key is required unless address and signature is given")

        if timestamp is None and signature is not None:
            raise Exception("timestamp is required if signature is given explicitly")

        if address is None:
            address = private_key_to_address(signing_key)
        if timestamp is None:
            timestamp = int(time.time())
        if signature is None:
            signature = sign_request(signing_key, method, "{}{}".format(prefix, path), timestamp, body)

        headers[TOSHI_ID_ADDRESS_HEADER] = address
        headers[TOSHI_SIGNATURE_HEADER] = signature
        headers[TOSHI_TIMESTAMP_HEADER] = str(timestamp)

        # because tornado doesn't like POSTs with body set to None
        if body is None and method == "POST":
            body = b""

        return self.fetch(path, body=body, **kwargs)
コード例 #3
0
    async def test_urlencoded_data(self):

        # generate random 2048 byte "file"
        filedata = os.urandom(2048)

        content_type, body = encode_multipart_formdata(
            [], [("file", "test.bin", filedata)])
        headers = {
            "Content-Type": content_type,
            'content-length': str(len(body))
        }

        timestamp = int(time.time())
        signature = sign_request(TEST_PRIVATE_KEY, "POST", "/", timestamp,
                                 body)

        resp = await self.fetch_signed("/",
                                       method="POST",
                                       body=body,
                                       headers=headers,
                                       signature=signature,
                                       timestamp=timestamp,
                                       address=TEST_ADDRESS)

        self.assertResponseCodeEqual(resp, 204)
コード例 #4
0
    async def test_query_argument_fetch(self):

        signing_key = TEST_PRIVATE_KEY
        address = TEST_ADDRESS
        timestamp = int(time.time())
        signature = sign_request(signing_key, "GET", "/", timestamp, None)

        resp = await self.fetch("/?{}".format(
            generate_query_args(signature=signature,
                                address=address,
                                timestamp=timestamp)))

        self.assertResponseCodeEqual(resp, 204)
    def __call__(self, r):

        method = r.method
        path = "/{}".format(r.url.split('/', 3)[-1])
        body = r.body

        timestamp = int(time.time())

        signature = sign_request(self.signing_key, method, path, timestamp,
                                 body)

        r.headers[TOSHI_ID_ADDRESS_HEADER] = self.address
        r.headers[TOSHI_SIGNATURE_HEADER] = signature
        r.headers[TOSHI_TIMESTAMP_HEADER] = str(timestamp)

        return r
コード例 #6
0
    async def connect(self):

        # find out if there's a path prefix added by get_url
        path = "/{}".format(self.url.split('/', 3)[-1])

        headers = {'User-Agent': 'Dgas-Test-Websocket-Client'}
        if self.signing_key:
            address = private_key_to_address(self.signing_key)
            timestamp = int(time.time())
            signature = sign_request(self.signing_key, "GET", path, timestamp, None)

            headers.update({
                TOSHI_ID_ADDRESS_HEADER: address,
                TOSHI_SIGNATURE_HEADER: signature,
                TOSHI_TIMESTAMP_HEADER: str(timestamp)
            })

        request = tornado.httpclient.HTTPRequest(self.url, headers=headers)

        self.con = await tornado.websocket.websocket_connect(request)
        return self.con
コード例 #7
0
    async def test_invalid_signature(self):

        body = {"registration_id": "1234567890"}

        timestamp = int(time.time())
        signature = sign_request(FAUCET_PRIVATE_KEY, "POST", "/", timestamp,
                                 json_encode(body).encode('utf-8'))

        resp = await self.fetch_signed("/",
                                       method="POST",
                                       body=body,
                                       address=TEST_ADDRESS,
                                       timestamp=timestamp,
                                       signature=signature)

        self.assertEqual(resp.code, 400, resp.body)

        # make sure query string also fails
        resp = await self.fetch("/?{}".format(
            generate_query_args(signature=signature,
                                address=TEST_ADDRESS,
                                timestamp=timestamp)))

        self.assertEqual(resp.code, 400, resp.body)