示例#1
0
    async def test_invalid_signature_in_pn_registration(self):

        body = {
            "registration_id": TEST_APN_ID,
        }

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

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

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

        async with self.pool.acquire() as con:

            rows1 = await con.fetch(
                "SELECT * FROM notification_registrations WHERE toshi_id = $1",
                TEST_ADDRESS)
            rows2 = await con.fetch(
                "SELECT * FROM notification_registrations WHERE toshi_id = $1",
                FAUCET_ADDRESS)

        self.assertEqual(len(rows1), 0)
        self.assertEqual(len(rows2), 0)
    async def test_transactions_with_known_sender_toshi_id_but_invalid_signature(
            self):

        body = {"from": FAUCET_ADDRESS, "to": TEST_ADDRESS, "value": 10**10}

        resp = await self.fetch("/tx/skel", method="POST", body=body)

        self.assertEqual(resp.code, 200)

        tx = sign_transaction(json_decode(resp.body)['tx'], FAUCET_PRIVATE_KEY)

        body = {"tx": tx}

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

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

        self.assertEqual(resp.code, 400, resp.body)
        self.assertIsNotNone(resp.body)
        error = json_decode(resp.body)
        self.assertIn('errors', error)
        self.assertEqual(len(error['errors']), 1)
示例#3
0
    async def test_invalid_signature_in_deregistration(self):

        async with self.pool.acquire() as con:

            await con.fetchrow(
                "INSERT INTO notification_registrations VALUES ($2, 'apn', $1, $2)",
                TEST_APN_ID, TEST_ADDRESS)

        body = {"registration_id": TEST_APN_ID}
        timestamp = int(time.time())
        signature = sign_request(FAUCET_PRIVATE_KEY, "POST",
                                 "/v1/apn/deregister", timestamp,
                                 json_encode(body).encode('utf-8'))

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

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

        async with self.pool.acquire() as con:

            rows = await con.fetch(
                "SELECT * FROM notification_registrations WHERE toshi_id = $1",
                TEST_ADDRESS)

        self.assertEqual(len(rows), 1)
示例#4
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)
示例#5
0
    async def test_wrong_address(self):

        timestamp = int(time.time())
        body = {"payment_address": TEST_PAYMENT_ADDRESS}
        signature = sign_request(TEST_PRIVATE_KEY, "POST", "/v1/user", timestamp, body)
        address = "{}00000".format(TEST_ADDRESS[:-5])

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

        self.assertResponseCodeEqual(resp, 400, resp.body)
示例#6
0
    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
示例#7
0
    async def connect(self):

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

        address = private_key_to_address(self.signing_key)
        timestamp = int(time.time())
        signature = sign_request(self.signing_key, "GET", path, timestamp,
                                 None)

        request = tornado.httpclient.HTTPRequest(
            self.url,
            headers={
                'User-Agent': 'Toshi-Test-Websocket-Client',
                TOSHI_ID_ADDRESS_HEADER: address,
                TOSHI_SIGNATURE_HEADER: signature,
                TOSHI_TIMESTAMP_HEADER: str(timestamp)
            })

        self.con = await tornado.websocket.websocket_connect(request)
        return self.con