10
  "   li~eJva&Tţy !H    """Tests for josepy.jws."""
import base64
import unittest

import mock
import OpenSSL

from josepy import errors, json_util, jwa, jwk, test_util

CERT = test_util.load_comparable_cert('cert.pem')
KEY = jwk.JWKRSA.load(test_util.load_vector('rsa512_key.pem'))


class MediaTypeTest(unittest.TestCase):
    """Tests for josepy.jws.MediaType."""

    def test_decode(self):
        from josepy.jws import MediaType
        self.assertEqual('application/app', MediaType.decode('application/app'))
        self.assertEqual('application/app', MediaType.decode('app'))
        self.assertRaises(
            errors.DeserializationError, MediaType.decode, 'app;foo')

    def test_encode(self):
        from josepy.jws import MediaType
        self.assertEqual('app', MediaType.encode('application/app'))
        self.assertEqual('application/app;foo',
                         MediaType.encode('application/app;foo'))


class HeaderTest(unittest.TestCase):
    """Tests for josepy.jws.Header."""

    def setUp(self):
        from josepy.jws import Header
        self.header1 = Header(jwk='foo')
        self.header2 = Header(jwk='bar')
        self.crit = Header(crit=('a', 'b'))
        self.empty = Header()

    def test_add_non_empty(self):
        from josepy.jws import Header
        self.assertEqual(Header(jwk='foo', crit=('a', 'b')),
                         self.header1 + self.crit)

    def test_add_empty(self):
        self.assertEqual(self.header1, self.header1 + self.empty)
        self.assertEqual(self.header1, self.empty + self.header1)

    def test_add_overlapping_error(self):
        self.assertRaises(TypeError, self.header1.__add__, self.header2)

    def test_add_wrong_type_error(self):
        self.assertRaises(TypeError, self.header1.__add__, 'xxx')

    def test_crit_decode_always_errors(self):
        from josepy.jws import Header
        self.assertRaises(errors.DeserializationError, Header.from_json,
                          {'crit': ['a', 'b']})

    def test_x5c_decoding(self):
        from josepy.jws import Header
        header = Header(x5c=(CERT, CERT))
        jobj = header.to_partial_json()
        cert_asn1 = OpenSSL.crypto.dump_certificate(
            OpenSSL.crypto.FILETYPE_ASN1, CERT.wrapped)
        cert_b64 = base64.b64encode(cert_asn1)
        self.assertEqual(jobj, {'x5c': [cert_b64, cert_b64]})
        self.assertEqual(header, Header.from_json(jobj))
        jobj['x5c'][0] = base64.b64encode(b'xxx' + cert_asn1)
        self.assertRaises(errors.DeserializationError, Header.from_json, jobj)

    def test_find_key(self):
        self.assertEqual('foo', self.header1.find_key())
        self.assertEqual('bar', self.header2.find_key())
        self.assertRaises(errors.Error, self.crit.find_key)


class SignatureTest(unittest.TestCase):
    """Tests for josepy.jws.Signature."""

    def test_from_json(self):
        from josepy.jws import Header
        from josepy.jws import Signature
        self.assertEqual(
            Signature(signature=b'foo', header=Header(alg=jwa.RS256)),
            Signature.from_json(
                {'signature': 'Zm9v', 'header': {'alg': 'RS256'}}))

    def test_from_json_no_alg_error(self):
        from josepy.jws import Signature
        self.assertRaises(errors.DeserializationError,
                          Signature.from_json, {'signature': 'foo'})


class JWSTest(unittest.TestCase):
    """Tests for josepy.jws.JWS."""

    def setUp(self):
        self.privkey = KEY
        self.pubkey = self.privkey.public_key()

        from josepy.jws import JWS
        self.unprotected = JWS.sign(
            payload=b'foo', key=self.privkey, alg=jwa.RS256)
        self.protected = JWS.sign(
            payload=b'foo', key=self.privkey, alg=jwa.RS256,
            protect=frozenset(['jwk', 'alg']))
        self.mixed = JWS.sign(
            payload=b'foo', key=self.privkey, alg=jwa.RS256,
            protect=frozenset(['alg']))

    def test_pubkey_jwk(self):
        self.assertEqual(self.unprotected.signature.combined.jwk, self.pu