Ejemplo n.º 1
0
    def test_only_tink_output_prefix_type_encodes_a_kid_header(self):
        handle = tink.new_keyset_handle(jwt.raw_jwt_hs256_template())
        jwt_mac = handle.primitive(jwt.JwtMac)

        tink_handle = _change_output_prefix_to_tink(handle)
        tink_jwt_mac = tink_handle.primitive(jwt.JwtMac)

        raw_jwt = jwt.new_raw_jwt(issuer='issuer', without_expiration=True)

        token = jwt_mac.compute_mac_and_encode(raw_jwt)
        token_with_kid = tink_jwt_mac.compute_mac_and_encode(raw_jwt)

        _, header, _, _ = _jwt_format.split_signed_compact(token)
        self.assertNotIn('kid', _json_util.json_loads(header))

        _, header_with_kid, _, _ = _jwt_format.split_signed_compact(
            token_with_kid)
        self.assertIn('kid', _json_util.json_loads(header_with_kid))

        validator = jwt.new_validator(expected_issuer='issuer',
                                      allow_missing_expiration=True)
        jwt_mac.verify_mac_and_decode(token, validator)
        tink_jwt_mac.verify_mac_and_decode(token_with_kid, validator)

        # With output prefix type RAW, a kid header is ignored
        jwt_mac.verify_mac_and_decode(token_with_kid, validator)
        # With output prefix type TINK, a kid header is required.
        with self.assertRaises(tink.TinkError):
            tink_jwt_mac.verify_mac_and_decode(token, validator)

        other_handle = _change_key_id(tink_handle)
        other_jwt_mac = other_handle.primitive(jwt.JwtMac)
        # A token with a wrong kid is rejected, even if the signature is ok.
        with self.assertRaises(tink.TinkError):
            other_jwt_mac.verify_mac_and_decode(token_with_kid, validator)
Ejemplo n.º 2
0
 def test_legacy_key_fails(self):
     template = keyset_builder.legacy_template(jwt.raw_jwt_hs256_template())
     builder = keyset_builder.new_keyset_builder()
     key_id = builder.add_new_key(template)
     builder.set_primary_key(key_id)
     handle = builder.keyset_handle()
     with self.assertRaises(tink.TinkError):
         handle.primitive(jwt.JwtMac)
Ejemplo n.º 3
0
    def test_raw_output_prefix_type_encodes_a_custom_kid_header(self):
        # normal HMAC jwt_mac with output prefix RAW
        handle = tink.new_keyset_handle(jwt.raw_jwt_hs256_template())
        raw_jwt = jwt.new_raw_jwt(issuer='issuer', without_expiration=True)
        validator = jwt.new_validator(expected_issuer='issuer',
                                      allow_missing_expiration=True)

        jwt_mac = handle.primitive(jwt.JwtMac)
        token = jwt_mac.compute_mac_and_encode(raw_jwt)
        jwt_mac.verify_mac_and_decode(token, validator)

        _, json_header, _, _ = _jwt_format.split_signed_compact(token)
        self.assertNotIn('kid', _json_util.json_loads(json_header))

        # HMAC jwt_mac with a custom_kid set
        custom_kid_handle = _set_custom_kid(handle, custom_kid='my kid')
        custom_kid_jwt_mac = custom_kid_handle.primitive(jwt.JwtMac)
        token_with_kid = custom_kid_jwt_mac.compute_mac_and_encode(raw_jwt)
        custom_kid_jwt_mac.verify_mac_and_decode(token_with_kid, validator)

        _, header_with_kid, _, _ = _jwt_format.split_signed_compact(
            token_with_kid)
        self.assertEqual(
            _json_util.json_loads(header_with_kid)['kid'], 'my kid')

        # Even when custom_kid is set, its not required to be set in the header.
        custom_kid_jwt_mac.verify_mac_and_decode(token, validator)
        # An additional kid header is ignored.
        jwt_mac.verify_mac_and_decode(token_with_kid, validator)

        other_handle = _set_custom_kid(handle, custom_kid='other kid')
        other_jwt_mac = other_handle.primitive(jwt.JwtMac)
        with self.assertRaises(tink.TinkError):
            # The custom_kid does not match the kid header.
            other_jwt_mac.verify_mac_and_decode(token_with_kid, validator)

        tink_handle = _change_output_prefix_to_tink(custom_kid_handle)
        tink_jwt_mac = tink_handle.primitive(jwt.JwtMac)
        # having custom_kid set with output prefix TINK is not allowed
        with self.assertRaises(tink.TinkError):
            tink_jwt_mac.compute_mac_and_encode(raw_jwt)
        with self.assertRaises(tink.TinkError):
            tink_jwt_mac.verify_mac_and_decode(token, validator)
        with self.assertRaises(tink.TinkError):
            tink_jwt_mac.verify_mac_and_decode(token_with_kid, validator)
Ejemplo n.º 4
0
    def test_raw_output_prefix_type_encodes_a_custom_kid_header(self):
        keyset_handle = tink.new_keyset_handle(jwt.raw_jwt_hs256_template())

        # Add a custom kid to the key in keyset_handle
        value = keyset_handle._keyset.key[0].key_data.value
        hmac_key = jwt_hmac_pb2.JwtHmacKey.FromString(value)
        hmac_key.custom_kid.value = 'my kid'
        keyset_handle._keyset.key[
            0].key_data.value = hmac_key.SerializeToString()

        jwt_mac = keyset_handle.primitive(jwt.JwtMac)

        raw_jwt = jwt.new_raw_jwt(issuer='issuer', without_expiration=True)
        signed_compact = jwt_mac.compute_mac_and_encode(raw_jwt)

        _, json_header, _, _ = _jwt_format.split_signed_compact(signed_compact)
        header = _jwt_format.json_loads(json_header)
        self.assertEqual(header['kid'], 'my kid')

        # Now, change the output prefix type to TINK. This should fail.
        keyset_handle._keyset.key[0].output_prefix_type = tink_pb2.TINK
        with self.assertRaises(tink.TinkError):
            tink_jwt_mac = keyset_handle.primitive(jwt.JwtMac)
            tink_jwt_mac.compute_mac_and_encode(raw_jwt)
Ejemplo n.º 5
0
 'RSA_SSA_PKCS1_4096_SHA512_F4':
     signature.signature_key_templates.RSA_SSA_PKCS1_4096_SHA512_F4,
 'RSA_SSA_PSS_3072_SHA256_SHA256_32_F4':
     signature.signature_key_templates.RSA_SSA_PSS_3072_SHA256_SHA256_32_F4,
 'RSA_SSA_PSS_4096_SHA512_SHA512_64_F4':
     signature.signature_key_templates.RSA_SSA_PSS_4096_SHA512_SHA512_64_F4,
 'AES_CMAC_PRF':
     prf.prf_key_templates.AES_CMAC,
 'HMAC_PRF_SHA256':
     prf.prf_key_templates.HMAC_SHA256,
 'HMAC_PRF_SHA512':
     prf.prf_key_templates.HMAC_SHA512,
 'HKDF_PRF_SHA256':
     prf.prf_key_templates.HKDF_SHA256,
 'JWT_HS256': jwt.jwt_hs256_template(),
 'JWT_HS256_RAW': jwt.raw_jwt_hs256_template(),
 'JWT_HS384': jwt.jwt_hs384_template(),
 'JWT_HS384_RAW': jwt.raw_jwt_hs384_template(),
 'JWT_HS512': jwt.jwt_hs512_template(),
 'JWT_HS512_RAW': jwt.raw_jwt_hs512_template(),
 'JWT_ES256': jwt.jwt_es256_template(),
 'JWT_ES256_RAW': jwt.raw_jwt_es256_template(),
 'JWT_ES384': jwt.jwt_es384_template(),
 'JWT_ES384_RAW': jwt.raw_jwt_es384_template(),
 'JWT_ES512': jwt.jwt_es512_template(),
 'JWT_ES512_RAW': jwt.raw_jwt_es512_template(),
 'JWT_RS256_2048_F4': jwt.jwt_rs256_2048_f4_template(),
 'JWT_RS256_2048_F4_RAW': jwt.raw_jwt_rs256_2048_f4_template(),
 'JWT_RS256_3072_F4': jwt.jwt_rs256_3072_f4_template(),
 'JWT_RS256_3072_F4_RAW': jwt.raw_jwt_rs256_3072_f4_template(),
 'JWT_RS384_3072_F4': jwt.jwt_rs384_3072_f4_template(),
Ejemplo n.º 6
0
class JwtKeyTemplatesTest(parameterized.TestCase):
    @parameterized.named_parameters([
        ('JWT_HS256', jwt.jwt_hs256_template()),
        ('JWT_HS256_RAW', jwt.raw_jwt_hs256_template()),
        ('JWT_HS384', jwt.jwt_hs384_template()),
        ('JWT_HS384_RAW', jwt.raw_jwt_hs384_template()),
        ('JWT_HS512', jwt.jwt_hs512_template()),
        ('JWT_HS512_RAW', jwt.raw_jwt_hs512_template()),
    ])
    def test_mac_success(self, key_template):
        keyset_handle = tink.new_keyset_handle(key_template)
        jwt_hmac = keyset_handle.primitive(jwt.JwtMac)
        token = jwt.new_raw_jwt(issuer='issuer',
                                subject='subject',
                                without_expiration=True)
        compact = jwt_hmac.compute_mac_and_encode(token)
        output_token = jwt_hmac.verify_mac_and_decode(
            compact,
            jwt.new_validator(expected_issuer='issuer',
                              allow_missing_expiration=True))
        self.assertEqual(output_token.issuer(), token.issuer())
        self.assertEqual(output_token.subject(), token.subject())

    @parameterized.named_parameters([
        ('JWT_ES256', jwt.jwt_es256_template()),
        ('JWT_ES256_RAW', jwt.raw_jwt_es256_template()),
        ('JWT_ES384', jwt.jwt_es384_template()),
        ('JWT_ES384_RAW', jwt.raw_jwt_es384_template()),
        ('JWT_ES512', jwt.jwt_es512_template()),
        ('JWT_ES512_RAW', jwt.raw_jwt_es512_template()),
        ('JWT_RS256_2048_F4', jwt.jwt_rs256_2048_f4_template()),
        ('JWT_RS256_2048_F4_RAW', jwt.raw_jwt_rs256_2048_f4_template()),
        ('JWT_RS256_3072_F4', jwt.jwt_rs256_3072_f4_template()),
        ('JWT_RS256_3072_F4_RAW', jwt.raw_jwt_rs256_3072_f4_template()),
        ('JWT_RS384_3072_F4', jwt.jwt_rs384_3072_f4_template()),
        ('JWT_RS384_3072_F4_RAW', jwt.raw_jwt_rs384_3072_f4_template()),
        ('JWT_RS512_4096_F4', jwt.jwt_rs512_4096_f4_template()),
        ('JWT_RS512_4096_F4_RAW', jwt.raw_jwt_rs512_4096_f4_template()),
        ('JWT_PS256_2048_F4', jwt.jwt_ps256_2048_f4_template()),
        ('JWT_PS256_2048_F4_RAW', jwt.raw_jwt_ps256_2048_f4_template()),
        ('JWT_PS256_3072_F4', jwt.jwt_ps256_3072_f4_template()),
        ('JWT_PS256_3072_F4_RAW', jwt.raw_jwt_ps256_3072_f4_template()),
        ('JWT_PS384_3072_F4', jwt.jwt_ps384_3072_f4_template()),
        ('JWT_PS384_3072_F4_RAW', jwt.raw_jwt_ps384_3072_f4_template()),
        ('JWT_PS512_4096_F4', jwt.jwt_ps512_4096_f4_template()),
        ('JWT_PS512_4096_F4_RAW', jwt.raw_jwt_ps512_4096_f4_template()),
    ])
    def test_new_keydata_primitive_success(self, template):
        private_handle = tink.new_keyset_handle(template)
        sign = private_handle.primitive(jwt.JwtPublicKeySign)
        verify = private_handle.public_keyset_handle().primitive(
            jwt.JwtPublicKeyVerify)
        raw_jwt = jwt.new_raw_jwt(issuer='issuer',
                                  subject='subject',
                                  without_expiration=True)
        compact = sign.sign_and_encode(raw_jwt)
        verified_jwt = verify.verify_and_decode(
            compact,
            jwt.new_validator(expected_issuer='issuer',
                              allow_missing_expiration=True))
        self.assertEqual(verified_jwt.issuer(), 'issuer')
        self.assertEqual(verified_jwt.subject(), 'subject')
Ejemplo n.º 7
0
 'RSA_SSA_PSS_3072_SHA256_SHA256_32_F4':
 signature.signature_key_templates.RSA_SSA_PSS_3072_SHA256_SHA256_32_F4,
 'RSA_SSA_PSS_4096_SHA512_SHA512_64_F4':
 signature.signature_key_templates.RSA_SSA_PSS_4096_SHA512_SHA512_64_F4,
 'AES_CMAC_PRF':
 prf.prf_key_templates.AES_CMAC,
 'HMAC_SHA256_PRF':
 prf.prf_key_templates.HMAC_SHA256,
 'HMAC_SHA512_PRF':
 prf.prf_key_templates.HMAC_SHA512,
 'HKDF_SHA256':
 prf.prf_key_templates.HKDF_SHA256,
 'JWT_HS256':
 jwt.jwt_hs256_template(),
 'JWT_HS256_RAW':
 jwt.raw_jwt_hs256_template(),
 'JWT_HS384':
 jwt.jwt_hs384_template(),
 'JWT_HS384_RAW':
 jwt.raw_jwt_hs384_template(),
 'JWT_HS512':
 jwt.jwt_hs512_template(),
 'JWT_HS512_RAW':
 jwt.raw_jwt_hs512_template(),
 'JWT_ES256':
 jwt.jwt_es256_template(),
 'JWT_ES256_RAW':
 jwt.raw_jwt_es256_template(),
 'JWT_ES384':
 jwt.jwt_es384_template(),
 'JWT_ES384_RAW':
Ejemplo n.º 8
0
class JwtHmacKeyManagerTest(parameterized.TestCase):

  def test_basic(self):
    key_manager = _jwt_hmac_key_manager.MacCcToPyJwtMacKeyManager()
    self.assertEqual(key_manager.primitive_class(), _jwt_mac.JwtMacInternal)
    self.assertEqual(key_manager.key_type(),
                     'type.googleapis.com/google.crypto.tink.JwtHmacKey')

  @parameterized.named_parameters([
      ('JWT_HS256', jwt.raw_jwt_hs256_template()),
      ('JWT_HS384', jwt.raw_jwt_hs384_template()),
      ('JWT_HS512', jwt.raw_jwt_hs512_template()),
  ])
  def test_new_keydata_primitive_success(self, template):
    key_manager = _jwt_hmac_key_manager.MacCcToPyJwtMacKeyManager()
    key_data = key_manager.new_key_data(template)
    jwt_hmac = key_manager.primitive(key_data)

    raw_jwt = jwt.new_raw_jwt(
        type_header='typeHeader', issuer='issuer', without_expiration=True)
    validator = jwt.new_validator(
        expected_type_header='typeHeader',
        expected_issuer='issuer',
        allow_missing_expiration=True,
        fixed_now=DATETIME_1970)

    token_with_kid = jwt_hmac.compute_mac_and_encode_with_kid(
        raw_jwt, kid='kid-123')
    token_without_kid = jwt_hmac.compute_mac_and_encode_with_kid(
        raw_jwt, kid=None)

    # Verification of a token with a kid only fails if the wrong kid is passed.
    verified_jwt = jwt_hmac.verify_mac_and_decode_with_kid(
        token_with_kid, validator, kid='kid-123')
    self.assertEqual(verified_jwt.type_header(), 'typeHeader')
    self.assertEqual(verified_jwt.issuer(), 'issuer')
    jwt_hmac.verify_mac_and_decode_with_kid(token_with_kid, validator, kid=None)
    with self.assertRaises(tink.TinkError):
      jwt_hmac.verify_mac_and_decode_with_kid(
          token_with_kid, validator, kid='other-kid')

    # A token without kid is only valid if no kid is passed.
    jwt_hmac.verify_mac_and_decode_with_kid(
        token_without_kid, validator, kid=None)
    with self.assertRaises(tink.TinkError):
      jwt_hmac.verify_mac_and_decode_with_kid(
          token_without_kid, validator, kid='kid-123')

  def test_fixed_signed_compact(self):
    signed_compact = (
        'eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJqb2UiLA0KICJleH'
        'AiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.'
        'dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk')
    jwt_hmac = create_fixed_jwt_hmac()
    verified_jwt = jwt_hmac.verify_mac_and_decode_with_kid(
        signed_compact,
        jwt.new_validator(
            expected_type_header='JWT',
            expected_issuer='joe',
            fixed_now=DATETIME_1970),
        kid=None)
    self.assertEqual(verified_jwt.issuer(), 'joe')
    self.assertEqual(verified_jwt.expiration().year, 2011)
    self.assertCountEqual(verified_jwt.custom_claim_names(),
                          ['http://example.com/is_root'])
    self.assertTrue(verified_jwt.custom_claim('http://example.com/is_root'))
    self.assertTrue(verified_jwt.type_header(), 'JWT')

    # fails because it is expired
    with self.assertRaises(tink.TinkError):
      jwt_hmac.verify_mac_and_decode_with_kid(
          signed_compact, jwt.new_validator(fixed_now=DATETIME_2020), kid=None)

    # fails with wrong issuer
    with self.assertRaises(tink.TinkError):
      jwt_hmac.verify_mac_and_decode_with_kid(
          signed_compact,
          jwt.new_validator(expected_issuer='jane', fixed_now=DATETIME_1970),
          kid=None)

  def test_weird_tokens_with_valid_macs(self):
    jwt_hmac = create_fixed_jwt_hmac()
    validator = jwt.new_validator(
        expected_issuer='joe', allow_missing_expiration=True)
    cc_mac = _cc_mac()

    # Normal token.
    valid_token = gen_token('{"alg":"HS256"}', '{"iss":"joe"}')
    verified = jwt_hmac.verify_mac_and_decode_with_kid(
        valid_token, validator, kid=None)
    self.assertEqual(verified.issuer(), 'joe')

    # Token with unknown header is valid.
    token_with_unknown_header = gen_token(
        '{"unknown_header":"123","alg":"HS256"}', '{"iss":"joe"}')
    verified2 = jwt_hmac.verify_mac_and_decode_with_kid(
        token_with_unknown_header, validator, kid=None)
    self.assertEqual(verified2.issuer(), 'joe')

    # Token with unknown kid is valid, since primitives with output prefix type
    # RAW ignore kid headers.
    token_with_unknown_kid = gen_token('{"kid":"unknown","alg":"HS256"}',
                                       '{"iss":"joe"}')
    verified2 = jwt_hmac.verify_mac_and_decode_with_kid(
        token_with_unknown_kid, validator, kid=None)
    self.assertEqual(verified2.issuer(), 'joe')

    # Token with invalid alg header
    alg_invalid = gen_token('{"alg":"HS384"}', '{"iss":"joe"}')
    with self.assertRaises(tink.TinkError):
      jwt_hmac.verify_mac_and_decode_with_kid(alg_invalid, validator, kid=None)

    # Token with empty header
    empty_header = gen_token('{}', '{"iss":"joe"}')
    with self.assertRaises(tink.TinkError):
      jwt_hmac.verify_mac_and_decode_with_kid(empty_header, validator, kid=None)

    # Token header is not valid JSON
    header_invalid = gen_token('{"alg":"HS256"', '{"iss":"joe"}')
    with self.assertRaises(tink.TinkError):
      jwt_hmac.verify_mac_and_decode_with_kid(
          header_invalid, validator, kid=None)

    # Token payload is not valid JSON
    payload_invalid = gen_token('{"alg":"HS256"}', '{"iss":"joe"')
    with self.assertRaises(tink.TinkError):
      jwt_hmac.verify_mac_and_decode_with_kid(
          payload_invalid, validator, kid=None)

    # Token with whitespace in header JSON string is valid.
    whitespace_in_header = gen_token(' {"alg":   \n  "HS256"} \n ',
                                     '{"iss":"joe" }')
    verified_jwt = jwt_hmac.verify_mac_and_decode_with_kid(
        whitespace_in_header, validator, kid=None)
    self.assertEqual(verified_jwt.issuer(), 'joe')

    # Token with whitespace in payload JSON string is valid.
    whitespace_in_payload = gen_token('{"alg":"HS256"}',
                                      ' {"iss": \n"joe" } \n')
    verified_jwt = jwt_hmac.verify_mac_and_decode_with_kid(
        whitespace_in_payload, validator, kid=None)
    self.assertEqual(verified_jwt.issuer(), 'joe')

    # Token with whitespace in base64-encoded header is invalid.
    with_whitespace_in_encoding = (
        _jwt_format.encode_header('{"alg":"HS256"}') + b' .' +
        _jwt_format.encode_payload('{"iss":"joe"}'))
    token_with_whitespace_in_encoding = _jwt_format.create_signed_compact(
        with_whitespace_in_encoding,
        cc_mac.compute_mac(with_whitespace_in_encoding))
    with self.assertRaises(tink.TinkError):
      jwt_hmac.verify_mac_and_decode_with_kid(
          token_with_whitespace_in_encoding, validator, kid=None)

    # Token with invalid character is invalid.
    with_invalid_char = (
        _jwt_format.encode_header('{"alg":"HS256"}') + b'.?' +
        _jwt_format.encode_payload('{"iss":"joe"}'))
    token_with_invalid_char = _jwt_format.create_signed_compact(
        with_invalid_char, cc_mac.compute_mac(with_invalid_char))
    with self.assertRaises(tink.TinkError):
      jwt_hmac.verify_mac_and_decode_with_kid(
          token_with_invalid_char, validator, kid=None)

    # Token with additional '.' is invalid.
    with_dot = (
        _jwt_format.encode_header('{"alg":"HS256"}') + b'.' +
        _jwt_format.encode_payload('{"iss":"joe"}') + b'.')
    token_with_dot = _jwt_format.create_signed_compact(
        with_dot, cc_mac.compute_mac(with_dot))
    with self.assertRaises(tink.TinkError):
      jwt_hmac.verify_mac_and_decode_with_kid(
          token_with_dot, validator, kid=None)

    # num_recursions has been chosen such that parsing of this token fails
    # in all languages. We want to make sure that the algorithm does not
    # hang or crash in this case, but only returns a parsing error.
    num_recursions = 10000
    rec_payload = ('{"a":' * num_recursions) + '""' + ('}' * num_recursions)
    rec_token = gen_token('{"alg":"HS256"}', rec_payload)
    with self.assertRaises(tink.TinkError):
      jwt_hmac.verify_mac_and_decode_with_kid(
          rec_token,
          validator=jwt.new_validator(allow_missing_expiration=True),
          kid=None)

    # test wrong types
    with self.assertRaises(tink.TinkError):
      jwt_hmac.verify_mac_and_decode_with_kid(
          cast(str, None), validator, kid=None)
    with self.assertRaises(tink.TinkError):
      jwt_hmac.verify_mac_and_decode_with_kid(
          cast(str, 123), validator, kid=None)
    with self.assertRaises(tink.TinkError):
      valid_token_bytes = valid_token.encode('utf8')
      jwt_hmac.verify_mac_and_decode_with_kid(
          cast(str, valid_token_bytes), validator, kid=None)

  @parameterized.named_parameters([
      ('modified_signature',
       ('eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJqb2UiLA0KICJleH'
        'AiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.'
        'dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXi')),
      ('modified_payload',
       ('eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJqb2UiLCJleHAiOj'
        'EzMDA4MTkzODEsImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.'
        'dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk')),
      ('modified_header',
       ('eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJqb2UiLA0KICJleH'
        'AiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.'
        'dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk')),
      ('extra .', 'eyJhbGciOiJIUzI1NiJ9.e30.abc.'),
      ('invalid_header_encoding', 'eyJhbGciOiJIUzI1NiJ9?.e30.abc'),
      ('invalid_payload_encoding', 'eyJhbGciOiJIUzI1NiJ9.e30?.abc'),
      ('invalid_mac_encoding', 'eyJhbGciOiJIUzI1NiJ9.e30.abc?'),
      ('no_mac', 'eyJhbGciOiJIUzI1NiJ9.e30'),
  ])
  def test_invalid_signed_compact(self, invalid_signed_compact):
    jwt_hmac = create_fixed_jwt_hmac()
    validator = jwt.new_validator(
        expected_issuer='joe',
        allow_missing_expiration=True,
        fixed_now=DATETIME_1970)

    with self.assertRaises(tink.TinkError):
      jwt_hmac.verify_mac_and_decode_with_kid(
          invalid_signed_compact, validator, kid=None)
Ejemplo n.º 9
0
class JwtMacWrapperTest(parameterized.TestCase):
    @parameterized.parameters([
        (jwt.raw_jwt_hs256_template(), jwt.raw_jwt_hs256_template()),
        (jwt.raw_jwt_hs256_template(), jwt.jwt_hs256_template()),
        (jwt.jwt_hs256_template(), jwt.raw_jwt_hs256_template()),
        (jwt.jwt_hs256_template(), jwt.jwt_hs256_template()),
    ])
    def test_key_rotation(self, old_key_tmpl, new_key_tmpl):
        builder = keyset_builder.new_keyset_builder()
        older_key_id = builder.add_new_key(old_key_tmpl)

        builder.set_primary_key(older_key_id)
        jwtmac1 = builder.keyset_handle().primitive(jwt.JwtMac)

        newer_key_id = builder.add_new_key(new_key_tmpl)
        jwtmac2 = builder.keyset_handle().primitive(jwt.JwtMac)

        builder.set_primary_key(newer_key_id)
        jwtmac3 = builder.keyset_handle().primitive(jwt.JwtMac)

        builder.disable_key(older_key_id)
        jwtmac4 = builder.keyset_handle().primitive(jwt.JwtMac)

        raw_jwt = jwt.new_raw_jwt(issuer='a', without_expiration=True)
        validator = jwt.new_validator(expected_issuer='a',
                                      allow_missing_expiration=True)

        self.assertNotEqual(older_key_id, newer_key_id)
        # 1 uses the older key. So 1, 2 and 3 can verify the mac, but not 4.
        compact1 = jwtmac1.compute_mac_and_encode(raw_jwt)
        self.assertEqual(
            jwtmac1.verify_mac_and_decode(compact1, validator).issuer(), 'a')
        self.assertEqual(
            jwtmac2.verify_mac_and_decode(compact1, validator).issuer(), 'a')
        self.assertEqual(
            jwtmac3.verify_mac_and_decode(compact1, validator).issuer(), 'a')
        with self.assertRaises(tink.TinkError):
            jwtmac4.verify_mac_and_decode(compact1, validator)

        # 2 uses the older key. So 1, 2 and 3 can verify the mac, but not 4.
        compact2 = jwtmac2.compute_mac_and_encode(raw_jwt)
        self.assertEqual(
            jwtmac1.verify_mac_and_decode(compact2, validator).issuer(), 'a')
        self.assertEqual(
            jwtmac2.verify_mac_and_decode(compact2, validator).issuer(), 'a')
        self.assertEqual(
            jwtmac3.verify_mac_and_decode(compact2, validator).issuer(), 'a')
        with self.assertRaises(tink.TinkError):
            jwtmac4.verify_mac_and_decode(compact2, validator)

        # 3 uses the newer key. So 2, 3 and 4 can verify the mac, but not 1.
        compact3 = jwtmac3.compute_mac_and_encode(raw_jwt)
        with self.assertRaises(tink.TinkError):
            jwtmac1.verify_mac_and_decode(compact3, validator)
        self.assertEqual(
            jwtmac2.verify_mac_and_decode(compact3, validator).issuer(), 'a')
        self.assertEqual(
            jwtmac3.verify_mac_and_decode(compact3, validator).issuer(), 'a')
        self.assertEqual(
            jwtmac4.verify_mac_and_decode(compact3, validator).issuer(), 'a')

        # 4 uses the newer key. So 2, 3 and 4 can verify the mac, but not 1.
        compact4 = jwtmac4.compute_mac_and_encode(raw_jwt)
        with self.assertRaises(tink.TinkError):
            jwtmac1.verify_mac_and_decode(compact4, validator)
        self.assertEqual(
            jwtmac2.verify_mac_and_decode(compact4, validator).issuer(), 'a')
        self.assertEqual(
            jwtmac3.verify_mac_and_decode(compact4, validator).issuer(), 'a')
        self.assertEqual(
            jwtmac4.verify_mac_and_decode(compact4, validator).issuer(), 'a')

    def test_only_tink_output_prefix_type_encodes_a_kid_header(self):
        handle = tink.new_keyset_handle(jwt.raw_jwt_hs256_template())
        jwt_mac = handle.primitive(jwt.JwtMac)

        tink_handle = _change_output_prefix_to_tink(handle)
        tink_jwt_mac = tink_handle.primitive(jwt.JwtMac)

        raw_jwt = jwt.new_raw_jwt(issuer='issuer', without_expiration=True)

        token = jwt_mac.compute_mac_and_encode(raw_jwt)
        token_with_kid = tink_jwt_mac.compute_mac_and_encode(raw_jwt)

        _, header, _, _ = _jwt_format.split_signed_compact(token)
        self.assertNotIn('kid', _json_util.json_loads(header))

        _, header_with_kid, _, _ = _jwt_format.split_signed_compact(
            token_with_kid)
        self.assertIn('kid', _json_util.json_loads(header_with_kid))

        validator = jwt.new_validator(expected_issuer='issuer',
                                      allow_missing_expiration=True)
        jwt_mac.verify_mac_and_decode(token, validator)
        tink_jwt_mac.verify_mac_and_decode(token_with_kid, validator)

        # With output prefix type RAW, a kid header is ignored
        jwt_mac.verify_mac_and_decode(token_with_kid, validator)
        # With output prefix type TINK, a kid header is required.
        with self.assertRaises(tink.TinkError):
            tink_jwt_mac.verify_mac_and_decode(token, validator)

        other_handle = _change_key_id(tink_handle)
        other_jwt_mac = other_handle.primitive(jwt.JwtMac)
        # A token with a wrong kid is rejected, even if the signature is ok.
        with self.assertRaises(tink.TinkError):
            other_jwt_mac.verify_mac_and_decode(token_with_kid, validator)

    def test_raw_output_prefix_type_encodes_a_custom_kid_header(self):
        # normal HMAC jwt_mac with output prefix RAW
        handle = tink.new_keyset_handle(jwt.raw_jwt_hs256_template())
        raw_jwt = jwt.new_raw_jwt(issuer='issuer', without_expiration=True)
        validator = jwt.new_validator(expected_issuer='issuer',
                                      allow_missing_expiration=True)

        jwt_mac = handle.primitive(jwt.JwtMac)
        token = jwt_mac.compute_mac_and_encode(raw_jwt)
        jwt_mac.verify_mac_and_decode(token, validator)

        _, json_header, _, _ = _jwt_format.split_signed_compact(token)
        self.assertNotIn('kid', _json_util.json_loads(json_header))

        # HMAC jwt_mac with a custom_kid set
        custom_kid_handle = _set_custom_kid(handle, custom_kid='my kid')
        custom_kid_jwt_mac = custom_kid_handle.primitive(jwt.JwtMac)
        token_with_kid = custom_kid_jwt_mac.compute_mac_and_encode(raw_jwt)
        custom_kid_jwt_mac.verify_mac_and_decode(token_with_kid, validator)

        _, header_with_kid, _, _ = _jwt_format.split_signed_compact(
            token_with_kid)
        self.assertEqual(
            _json_util.json_loads(header_with_kid)['kid'], 'my kid')

        # Even when custom_kid is set, its not required to be set in the header.
        custom_kid_jwt_mac.verify_mac_and_decode(token, validator)
        # An additional kid header is ignored.
        jwt_mac.verify_mac_and_decode(token_with_kid, validator)

        other_handle = _set_custom_kid(handle, custom_kid='other kid')
        other_jwt_mac = other_handle.primitive(jwt.JwtMac)
        with self.assertRaises(tink.TinkError):
            # The custom_kid does not match the kid header.
            other_jwt_mac.verify_mac_and_decode(token_with_kid, validator)

        tink_handle = _change_output_prefix_to_tink(custom_kid_handle)
        tink_jwt_mac = tink_handle.primitive(jwt.JwtMac)
        # having custom_kid set with output prefix TINK is not allowed
        with self.assertRaises(tink.TinkError):
            tink_jwt_mac.compute_mac_and_encode(raw_jwt)
        with self.assertRaises(tink.TinkError):
            tink_jwt_mac.verify_mac_and_decode(token, validator)
        with self.assertRaises(tink.TinkError):
            tink_jwt_mac.verify_mac_and_decode(token_with_kid, validator)

    def test_legacy_key_fails(self):
        template = keyset_builder.legacy_template(jwt.raw_jwt_hs256_template())
        builder = keyset_builder.new_keyset_builder()
        key_id = builder.add_new_key(template)
        builder.set_primary_key(key_id)
        handle = builder.keyset_handle()
        with self.assertRaises(tink.TinkError):
            handle.primitive(jwt.JwtMac)

    def test_legacy_non_primary_key_fails(self):
        builder = keyset_builder.new_keyset_builder()
        old_template = keyset_builder.legacy_template(
            jwt.raw_jwt_hs256_template())
        _ = builder.add_new_key(old_template)
        current_key_id = builder.add_new_key(jwt.jwt_hs256_template())
        builder.set_primary_key(current_key_id)
        handle = builder.keyset_handle()
        with self.assertRaises(tink.TinkError):
            handle.primitive(jwt.JwtMac)

    def test_jwt_mac_from_keyset_without_primary_fails(self):
        builder = keyset_builder.new_keyset_builder()
        builder.add_new_key(jwt.raw_jwt_hs256_template())
        with self.assertRaises(tink.TinkError):
            builder.keyset_handle()
Ejemplo n.º 10
0
 def test_jwt_mac_from_keyset_without_primary_fails(self):
     builder = keyset_builder.new_keyset_builder()
     builder.add_new_key(jwt.raw_jwt_hs256_template())
     with self.assertRaises(tink.TinkError):
         builder.keyset_handle()