1*e7b1675dSTing-Kang Chang# Copyright 2020 Google LLC 2*e7b1675dSTing-Kang Chang# 3*e7b1675dSTing-Kang Chang# Licensed under the Apache License, Version 2.0 (the "License"); 4*e7b1675dSTing-Kang Chang# you may not use this file except in compliance with the License. 5*e7b1675dSTing-Kang Chang# You may obtain a copy of the License at 6*e7b1675dSTing-Kang Chang# 7*e7b1675dSTing-Kang Chang# http://www.apache.org/licenses/LICENSE-2.0 8*e7b1675dSTing-Kang Chang# 9*e7b1675dSTing-Kang Chang# Unless required by applicable law or agreed to in writing, software 10*e7b1675dSTing-Kang Chang# distributed under the License is distributed on an "AS IS" BASIS, 11*e7b1675dSTing-Kang Chang# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*e7b1675dSTing-Kang Chang# See the License for the specific language governing permissions and 13*e7b1675dSTing-Kang Chang# limitations under the License. 14*e7b1675dSTing-Kang Chang"""Cross-language tests for the Aead primitive. 15*e7b1675dSTing-Kang Chang 16*e7b1675dSTing-Kang ChangThese tests check some basic AEAD properties, and that all implementations can 17*e7b1675dSTing-Kang Changinteroperate with each other. 18*e7b1675dSTing-Kang Chang""" 19*e7b1675dSTing-Kang Chang 20*e7b1675dSTing-Kang Changfrom typing import Iterable, List, Tuple 21*e7b1675dSTing-Kang Chang 22*e7b1675dSTing-Kang Changfrom absl.testing import absltest 23*e7b1675dSTing-Kang Changfrom absl.testing import parameterized 24*e7b1675dSTing-Kang Changimport tink 25*e7b1675dSTing-Kang Changfrom tink import aead 26*e7b1675dSTing-Kang Chang 27*e7b1675dSTing-Kang Changfrom tink.proto import tink_pb2 28*e7b1675dSTing-Kang Changfrom tink.testing import keyset_builder 29*e7b1675dSTing-Kang Changimport tink_config 30*e7b1675dSTing-Kang Changfrom util import testing_servers 31*e7b1675dSTing-Kang Changfrom util import utilities 32*e7b1675dSTing-Kang Chang 33*e7b1675dSTing-Kang ChangSUPPORTED_LANGUAGES = testing_servers.SUPPORTED_LANGUAGES_BY_PRIMITIVE['aead'] 34*e7b1675dSTing-Kang Chang 35*e7b1675dSTing-Kang Chang 36*e7b1675dSTing-Kang Changdef setUpModule(): 37*e7b1675dSTing-Kang Chang aead.register() 38*e7b1675dSTing-Kang Chang testing_servers.start('aead') 39*e7b1675dSTing-Kang Chang 40*e7b1675dSTing-Kang Chang 41*e7b1675dSTing-Kang Changdef tearDownModule(): 42*e7b1675dSTing-Kang Chang testing_servers.stop() 43*e7b1675dSTing-Kang Chang 44*e7b1675dSTing-Kang Chang 45*e7b1675dSTing-Kang Chang# Fake KMS keys are base64-encoded keysets. Each server must register a 46*e7b1675dSTing-Kang Chang# fake KmsClient that can handle these keys. 47*e7b1675dSTing-Kang Chang_FAKE_KMS_KEY_URI = ( 48*e7b1675dSTing-Kang Chang 'fake-kms://CM2b3_MDElQKSAowdHlwZS5nb29nbGVhcGlzLmNvbS9nb29nbGUuY3J5cHRv' 49*e7b1675dSTing-Kang Chang 'LnRpbmsuQWVzR2NtS2V5EhIaEIK75t5L-adlUwVhWvRuWUwYARABGM2b3_MDIAE') 50*e7b1675dSTing-Kang Chang 51*e7b1675dSTing-Kang Chang 52*e7b1675dSTing-Kang Chang# maps from key_template_name to (key_template, supported_langs). Contains all 53*e7b1675dSTing-Kang Chang# templates we want to test which do not have a name in Tinkey. 54*e7b1675dSTing-Kang Chang_ADDITIONAL_KEY_TEMPLATES = { 55*e7b1675dSTing-Kang Chang '_FAKE_KMS_AEAD': ( 56*e7b1675dSTing-Kang Chang aead.aead_key_templates.create_kms_aead_key_template(_FAKE_KMS_KEY_URI), 57*e7b1675dSTing-Kang Chang tink_config.supported_languages_for_key_type('KmsAeadKey'), 58*e7b1675dSTing-Kang Chang ), 59*e7b1675dSTing-Kang Chang # Since the key type KmsEnvelopeAeadKey is supported by all languages, the 60*e7b1675dSTing-Kang Chang # following templates should be supported if the DEK Template is supported 61*e7b1675dSTing-Kang Chang # by the language. 62*e7b1675dSTing-Kang Chang '_FAKE_KMS_ENVELOPE_AEAD_WITH_AES128_GCM': ( 63*e7b1675dSTing-Kang Chang aead.aead_key_templates.create_kms_envelope_aead_key_template( 64*e7b1675dSTing-Kang Chang _FAKE_KMS_KEY_URI, aead.aead_key_templates.AES128_GCM 65*e7b1675dSTing-Kang Chang ), 66*e7b1675dSTing-Kang Chang utilities.SUPPORTED_LANGUAGES_BY_TEMPLATE_NAME['AES128_GCM'], 67*e7b1675dSTing-Kang Chang ), 68*e7b1675dSTing-Kang Chang '_FAKE_KMS_ENVELOPE_AEAD_WITH_AES256_GCM': ( 69*e7b1675dSTing-Kang Chang aead.aead_key_templates.create_kms_envelope_aead_key_template( 70*e7b1675dSTing-Kang Chang _FAKE_KMS_KEY_URI, aead.aead_key_templates.AES256_GCM 71*e7b1675dSTing-Kang Chang ), 72*e7b1675dSTing-Kang Chang utilities.SUPPORTED_LANGUAGES_BY_TEMPLATE_NAME['AES256_GCM'], 73*e7b1675dSTing-Kang Chang ), 74*e7b1675dSTing-Kang Chang '_FAKE_KMS_ENVELOPE_AEAD_WITH_AES128_EAX': ( 75*e7b1675dSTing-Kang Chang aead.aead_key_templates.create_kms_envelope_aead_key_template( 76*e7b1675dSTing-Kang Chang _FAKE_KMS_KEY_URI, aead.aead_key_templates.AES128_EAX 77*e7b1675dSTing-Kang Chang ), 78*e7b1675dSTing-Kang Chang utilities.SUPPORTED_LANGUAGES_BY_TEMPLATE_NAME['AES128_EAX'], 79*e7b1675dSTing-Kang Chang ), 80*e7b1675dSTing-Kang Chang '_FAKE_KMS_ENVELOPE_AEAD_WITH_AES256_EAX': ( 81*e7b1675dSTing-Kang Chang aead.aead_key_templates.create_kms_envelope_aead_key_template( 82*e7b1675dSTing-Kang Chang _FAKE_KMS_KEY_URI, aead.aead_key_templates.AES256_EAX 83*e7b1675dSTing-Kang Chang ), 84*e7b1675dSTing-Kang Chang utilities.SUPPORTED_LANGUAGES_BY_TEMPLATE_NAME['AES256_EAX'], 85*e7b1675dSTing-Kang Chang ), 86*e7b1675dSTing-Kang Chang '_FAKE_KMS_ENVELOPE_AEAD_WITH_AES128_GCM_SIV': ( 87*e7b1675dSTing-Kang Chang aead.aead_key_templates.create_kms_envelope_aead_key_template( 88*e7b1675dSTing-Kang Chang _FAKE_KMS_KEY_URI, aead.aead_key_templates.AES128_GCM_SIV 89*e7b1675dSTing-Kang Chang ), 90*e7b1675dSTing-Kang Chang utilities.SUPPORTED_LANGUAGES_BY_TEMPLATE_NAME['AES128_GCM_SIV'], 91*e7b1675dSTing-Kang Chang ), 92*e7b1675dSTing-Kang Chang '_FAKE_KMS_ENVELOPE_AEAD_WITH_AES256_GCM_SIV': ( 93*e7b1675dSTing-Kang Chang aead.aead_key_templates.create_kms_envelope_aead_key_template( 94*e7b1675dSTing-Kang Chang _FAKE_KMS_KEY_URI, aead.aead_key_templates.AES256_GCM_SIV 95*e7b1675dSTing-Kang Chang ), 96*e7b1675dSTing-Kang Chang utilities.SUPPORTED_LANGUAGES_BY_TEMPLATE_NAME['AES256_GCM_SIV'], 97*e7b1675dSTing-Kang Chang ), 98*e7b1675dSTing-Kang Chang '_FAKE_KMS_ENVELOPE_AEAD_WITH_AES128_CTR_HMAC_SHA256': ( 99*e7b1675dSTing-Kang Chang aead.aead_key_templates.create_kms_envelope_aead_key_template( 100*e7b1675dSTing-Kang Chang _FAKE_KMS_KEY_URI, aead.aead_key_templates.AES128_CTR_HMAC_SHA256 101*e7b1675dSTing-Kang Chang ), 102*e7b1675dSTing-Kang Chang utilities.SUPPORTED_LANGUAGES_BY_TEMPLATE_NAME[ 103*e7b1675dSTing-Kang Chang 'AES128_CTR_HMAC_SHA256' 104*e7b1675dSTing-Kang Chang ], 105*e7b1675dSTing-Kang Chang ), 106*e7b1675dSTing-Kang Chang '_FAKE_KMS_ENVELOPE_AEAD_WITH_AES256_CTR_HMAC_SHA256': ( 107*e7b1675dSTing-Kang Chang aead.aead_key_templates.create_kms_envelope_aead_key_template( 108*e7b1675dSTing-Kang Chang _FAKE_KMS_KEY_URI, aead.aead_key_templates.AES256_CTR_HMAC_SHA256 109*e7b1675dSTing-Kang Chang ), 110*e7b1675dSTing-Kang Chang utilities.SUPPORTED_LANGUAGES_BY_TEMPLATE_NAME[ 111*e7b1675dSTing-Kang Chang 'AES256_CTR_HMAC_SHA256' 112*e7b1675dSTing-Kang Chang ], 113*e7b1675dSTing-Kang Chang ), 114*e7b1675dSTing-Kang Chang '_FAKE_KMS_ENVELOPE_AEAD_WITH_CHACHA20_POLY1305': ( 115*e7b1675dSTing-Kang Chang aead.aead_key_templates.create_kms_envelope_aead_key_template( 116*e7b1675dSTing-Kang Chang _FAKE_KMS_KEY_URI, utilities.KEY_TEMPLATE['CHACHA20_POLY1305'] 117*e7b1675dSTing-Kang Chang ), 118*e7b1675dSTing-Kang Chang utilities.SUPPORTED_LANGUAGES_BY_TEMPLATE_NAME['CHACHA20_POLY1305'], 119*e7b1675dSTing-Kang Chang ), 120*e7b1675dSTing-Kang Chang '_FAKE_KMS_ENVELOPE_AEAD_WITH_XCHACHA20_POLY1305': ( 121*e7b1675dSTing-Kang Chang aead.aead_key_templates.create_kms_envelope_aead_key_template( 122*e7b1675dSTing-Kang Chang _FAKE_KMS_KEY_URI, aead.aead_key_templates.XCHACHA20_POLY1305 123*e7b1675dSTing-Kang Chang ), 124*e7b1675dSTing-Kang Chang utilities.SUPPORTED_LANGUAGES_BY_TEMPLATE_NAME['XCHACHA20_POLY1305'], 125*e7b1675dSTing-Kang Chang ), 126*e7b1675dSTing-Kang Chang} 127*e7b1675dSTing-Kang Chang 128*e7b1675dSTing-Kang Chang 129*e7b1675dSTing-Kang Changclass AeadPythonTest(parameterized.TestCase): 130*e7b1675dSTing-Kang Chang 131*e7b1675dSTing-Kang Chang def _create_aeads_ignore_errors(self, 132*e7b1675dSTing-Kang Chang keyset: bytes) -> List[Tuple[aead.Aead, str]]: 133*e7b1675dSTing-Kang Chang """Creates AEADs for the given keyset in each language. 134*e7b1675dSTing-Kang Chang 135*e7b1675dSTing-Kang Chang Args: 136*e7b1675dSTing-Kang Chang keyset: A keyset as a serialized 'keyset' proto. 137*e7b1675dSTing-Kang Chang 138*e7b1675dSTing-Kang Chang Returns: 139*e7b1675dSTing-Kang Chang A list of pairs (aead, language) 140*e7b1675dSTing-Kang Chang """ 141*e7b1675dSTing-Kang Chang 142*e7b1675dSTing-Kang Chang result = [] 143*e7b1675dSTing-Kang Chang for lang in utilities.ALL_LANGUAGES: 144*e7b1675dSTing-Kang Chang try: 145*e7b1675dSTing-Kang Chang aead_p = testing_servers.remote_primitive(lang, keyset, aead.Aead) 146*e7b1675dSTing-Kang Chang result.append((aead_p, lang)) 147*e7b1675dSTing-Kang Chang except tink.TinkError: 148*e7b1675dSTing-Kang Chang pass 149*e7b1675dSTing-Kang Chang return result 150*e7b1675dSTing-Kang Chang 151*e7b1675dSTing-Kang Chang def _langs_from_key_template_name(self, key_template_name: str) -> List[str]: 152*e7b1675dSTing-Kang Chang if key_template_name in _ADDITIONAL_KEY_TEMPLATES: 153*e7b1675dSTing-Kang Chang _, supported_langs = _ADDITIONAL_KEY_TEMPLATES[key_template_name] 154*e7b1675dSTing-Kang Chang return supported_langs 155*e7b1675dSTing-Kang Chang else: 156*e7b1675dSTing-Kang Chang return utilities.SUPPORTED_LANGUAGES_BY_TEMPLATE_NAME[key_template_name] 157*e7b1675dSTing-Kang Chang 158*e7b1675dSTing-Kang Chang def _as_proto_template(self, key_template_name: str) -> tink_pb2.KeyTemplate: 159*e7b1675dSTing-Kang Chang if key_template_name in _ADDITIONAL_KEY_TEMPLATES: 160*e7b1675dSTing-Kang Chang key_template, _ = _ADDITIONAL_KEY_TEMPLATES[key_template_name] 161*e7b1675dSTing-Kang Chang return key_template 162*e7b1675dSTing-Kang Chang else: 163*e7b1675dSTing-Kang Chang return utilities.KEY_TEMPLATE[key_template_name] 164*e7b1675dSTing-Kang Chang 165*e7b1675dSTing-Kang Chang @parameterized.parameters([ 166*e7b1675dSTing-Kang Chang *utilities.tinkey_template_names_for(aead.Aead), 167*e7b1675dSTing-Kang Chang *_ADDITIONAL_KEY_TEMPLATES.keys() 168*e7b1675dSTing-Kang Chang ]) 169*e7b1675dSTing-Kang Chang def test_encrypt_decrypt(self, key_template_name): 170*e7b1675dSTing-Kang Chang langs = self._langs_from_key_template_name(key_template_name) 171*e7b1675dSTing-Kang Chang self.assertNotEmpty(langs) 172*e7b1675dSTing-Kang Chang proto_template = self._as_proto_template(key_template_name) 173*e7b1675dSTing-Kang Chang # Take the first supported language to generate the keyset. 174*e7b1675dSTing-Kang Chang keyset = testing_servers.new_keyset(langs[0], proto_template) 175*e7b1675dSTing-Kang Chang 176*e7b1675dSTing-Kang Chang supported_aeads = self._create_aeads_ignore_errors(keyset) 177*e7b1675dSTing-Kang Chang self.assertEqual(set([lang for (_, lang) in supported_aeads]), set(langs)) 178*e7b1675dSTing-Kang Chang for (p, lang) in supported_aeads: 179*e7b1675dSTing-Kang Chang plaintext = ( 180*e7b1675dSTing-Kang Chang b'This is some plaintext message to be encrypted using key_template ' 181*e7b1675dSTing-Kang Chang b'%s using %s for encryption.' % 182*e7b1675dSTing-Kang Chang (key_template_name.encode('utf8'), lang.encode('utf8'))) 183*e7b1675dSTing-Kang Chang associated_data = ( 184*e7b1675dSTing-Kang Chang b'Some associated data for %s using %s for encryption.' % 185*e7b1675dSTing-Kang Chang (key_template_name.encode('utf8'), lang.encode('utf8'))) 186*e7b1675dSTing-Kang Chang ciphertext = p.encrypt(plaintext, associated_data) 187*e7b1675dSTing-Kang Chang for (p2, lang2) in supported_aeads: 188*e7b1675dSTing-Kang Chang output = p2.decrypt(ciphertext, associated_data) 189*e7b1675dSTing-Kang Chang self.assertEqual( 190*e7b1675dSTing-Kang Chang output, plaintext, 191*e7b1675dSTing-Kang Chang 'While encrypting in %s an decrypting in %s' % (lang, lang2)) 192*e7b1675dSTing-Kang Chang 193*e7b1675dSTing-Kang Chang @parameterized.parameters( 194*e7b1675dSTing-Kang Chang tink_config.supported_languages_for_key_type('KmsEnvelopeAeadKey') 195*e7b1675dSTing-Kang Chang ) 196*e7b1675dSTing-Kang Chang def test_envelope_encryption_rejects_envelope_templates_as_dek(self, lang): 197*e7b1675dSTing-Kang Chang dek_template = ( 198*e7b1675dSTing-Kang Chang aead.aead_key_templates.create_kms_envelope_aead_key_template( 199*e7b1675dSTing-Kang Chang kek_uri=_FAKE_KMS_KEY_URI, 200*e7b1675dSTing-Kang Chang dek_template=aead.aead_key_templates.AES128_GCM, 201*e7b1675dSTing-Kang Chang ) 202*e7b1675dSTing-Kang Chang ) 203*e7b1675dSTing-Kang Chang template = aead.aead_key_templates.create_kms_envelope_aead_key_template( 204*e7b1675dSTing-Kang Chang kek_uri=_FAKE_KMS_KEY_URI, dek_template=dek_template 205*e7b1675dSTing-Kang Chang ) 206*e7b1675dSTing-Kang Chang with self.assertRaises(tink.TinkError): 207*e7b1675dSTing-Kang Chang _ = testing_servers.new_keyset(lang, template) 208*e7b1675dSTing-Kang Chang 209*e7b1675dSTing-Kang Chang @parameterized.parameters( 210*e7b1675dSTing-Kang Chang tink_config.supported_languages_for_key_type('KmsAeadKey') 211*e7b1675dSTing-Kang Chang ) 212*e7b1675dSTing-Kang Chang def test_envelope_encryption_rejects_kms_templates_as_dek(self, lang): 213*e7b1675dSTing-Kang Chang dek_template = aead.aead_key_templates.create_kms_aead_key_template( 214*e7b1675dSTing-Kang Chang key_uri=_FAKE_KMS_KEY_URI 215*e7b1675dSTing-Kang Chang ) 216*e7b1675dSTing-Kang Chang template = aead.aead_key_templates.create_kms_envelope_aead_key_template( 217*e7b1675dSTing-Kang Chang kek_uri=_FAKE_KMS_KEY_URI, dek_template=dek_template 218*e7b1675dSTing-Kang Chang ) 219*e7b1675dSTing-Kang Chang with self.assertRaises(tink.TinkError): 220*e7b1675dSTing-Kang Chang _ = testing_servers.new_keyset(lang, template) 221*e7b1675dSTing-Kang Chang 222*e7b1675dSTing-Kang Chang 223*e7b1675dSTing-Kang Chang# If the implementations work fine for keysets with single keys, then key 224*e7b1675dSTing-Kang Chang# rotation should work if the primitive wrapper is implemented correctly. 225*e7b1675dSTing-Kang Chang# These wrappers do not depend on the key type, so it should be fine to always 226*e7b1675dSTing-Kang Chang# test with the same key type. Since the AEAD wrapper needs to treat keys 227*e7b1675dSTing-Kang Chang# with output prefix RAW differently, we also include such a template for that. 228*e7b1675dSTing-Kang ChangKEY_ROTATION_TEMPLATES = [ 229*e7b1675dSTing-Kang Chang aead.aead_key_templates.AES128_CTR_HMAC_SHA256, 230*e7b1675dSTing-Kang Chang keyset_builder.raw_template(aead.aead_key_templates.AES128_CTR_HMAC_SHA256) 231*e7b1675dSTing-Kang Chang] 232*e7b1675dSTing-Kang Chang 233*e7b1675dSTing-Kang Chang 234*e7b1675dSTing-Kang Changdef key_rotation_test_cases( 235*e7b1675dSTing-Kang Chang) -> Iterable[Tuple[str, str, tink_pb2.KeyTemplate, tink_pb2.KeyTemplate]]: 236*e7b1675dSTing-Kang Chang for enc_lang in SUPPORTED_LANGUAGES: 237*e7b1675dSTing-Kang Chang for dec_lang in SUPPORTED_LANGUAGES: 238*e7b1675dSTing-Kang Chang for old_key_tmpl in KEY_ROTATION_TEMPLATES: 239*e7b1675dSTing-Kang Chang for new_key_tmpl in KEY_ROTATION_TEMPLATES: 240*e7b1675dSTing-Kang Chang yield (enc_lang, dec_lang, old_key_tmpl, new_key_tmpl) 241*e7b1675dSTing-Kang Chang 242*e7b1675dSTing-Kang Chang 243*e7b1675dSTing-Kang Changclass AeadKeyRotationTest(parameterized.TestCase): 244*e7b1675dSTing-Kang Chang 245*e7b1675dSTing-Kang Chang @parameterized.parameters(key_rotation_test_cases()) 246*e7b1675dSTing-Kang Chang def test_key_rotation(self, enc_lang, dec_lang, old_key_tmpl, new_key_tmpl): 247*e7b1675dSTing-Kang Chang # Do a key rotation from an old key generated from old_key_tmpl to a new 248*e7b1675dSTing-Kang Chang # key generated from new_key_tmpl. Encryption and decryption are done 249*e7b1675dSTing-Kang Chang # in languages enc_lang and dec_lang. 250*e7b1675dSTing-Kang Chang builder = keyset_builder.new_keyset_builder() 251*e7b1675dSTing-Kang Chang older_key_id = builder.add_new_key(old_key_tmpl) 252*e7b1675dSTing-Kang Chang builder.set_primary_key(older_key_id) 253*e7b1675dSTing-Kang Chang enc_aead1 = testing_servers.remote_primitive(enc_lang, builder.keyset(), 254*e7b1675dSTing-Kang Chang aead.Aead) 255*e7b1675dSTing-Kang Chang dec_aead1 = testing_servers.remote_primitive(dec_lang, builder.keyset(), 256*e7b1675dSTing-Kang Chang aead.Aead) 257*e7b1675dSTing-Kang Chang newer_key_id = builder.add_new_key(new_key_tmpl) 258*e7b1675dSTing-Kang Chang enc_aead2 = testing_servers.remote_primitive(enc_lang, builder.keyset(), 259*e7b1675dSTing-Kang Chang aead.Aead) 260*e7b1675dSTing-Kang Chang dec_aead2 = testing_servers.remote_primitive(dec_lang, builder.keyset(), 261*e7b1675dSTing-Kang Chang aead.Aead) 262*e7b1675dSTing-Kang Chang 263*e7b1675dSTing-Kang Chang builder.set_primary_key(newer_key_id) 264*e7b1675dSTing-Kang Chang enc_aead3 = testing_servers.remote_primitive(enc_lang, builder.keyset(), 265*e7b1675dSTing-Kang Chang aead.Aead) 266*e7b1675dSTing-Kang Chang dec_aead3 = testing_servers.remote_primitive(dec_lang, builder.keyset(), 267*e7b1675dSTing-Kang Chang aead.Aead) 268*e7b1675dSTing-Kang Chang 269*e7b1675dSTing-Kang Chang builder.disable_key(older_key_id) 270*e7b1675dSTing-Kang Chang enc_aead4 = testing_servers.remote_primitive(enc_lang, builder.keyset(), 271*e7b1675dSTing-Kang Chang aead.Aead) 272*e7b1675dSTing-Kang Chang dec_aead4 = testing_servers.remote_primitive(dec_lang, builder.keyset(), 273*e7b1675dSTing-Kang Chang aead.Aead) 274*e7b1675dSTing-Kang Chang 275*e7b1675dSTing-Kang Chang self.assertNotEqual(older_key_id, newer_key_id) 276*e7b1675dSTing-Kang Chang # 1 encrypts with the older key. So 1, 2 and 3 can decrypt it, but not 4. 277*e7b1675dSTing-Kang Chang ciphertext1 = enc_aead1.encrypt(b'plaintext', b'ad') 278*e7b1675dSTing-Kang Chang self.assertEqual(dec_aead1.decrypt(ciphertext1, b'ad'), b'plaintext') 279*e7b1675dSTing-Kang Chang self.assertEqual(dec_aead2.decrypt(ciphertext1, b'ad'), b'plaintext') 280*e7b1675dSTing-Kang Chang self.assertEqual(dec_aead3.decrypt(ciphertext1, b'ad'), b'plaintext') 281*e7b1675dSTing-Kang Chang with self.assertRaises(tink.TinkError): 282*e7b1675dSTing-Kang Chang _ = dec_aead4.decrypt(ciphertext1, b'ad') 283*e7b1675dSTing-Kang Chang 284*e7b1675dSTing-Kang Chang # 2 encrypts with the older key. So 1, 2 and 3 can decrypt it, but not 4. 285*e7b1675dSTing-Kang Chang ciphertext2 = enc_aead2.encrypt(b'plaintext', b'ad') 286*e7b1675dSTing-Kang Chang self.assertEqual(dec_aead1.decrypt(ciphertext2, b'ad'), b'plaintext') 287*e7b1675dSTing-Kang Chang self.assertEqual(dec_aead2.decrypt(ciphertext2, b'ad'), b'plaintext') 288*e7b1675dSTing-Kang Chang self.assertEqual(dec_aead3.decrypt(ciphertext2, b'ad'), b'plaintext') 289*e7b1675dSTing-Kang Chang with self.assertRaises(tink.TinkError): 290*e7b1675dSTing-Kang Chang _ = dec_aead4.decrypt(ciphertext2, b'ad') 291*e7b1675dSTing-Kang Chang 292*e7b1675dSTing-Kang Chang # 3 encrypts with the newer key. So 2, 3 and 4 can decrypt it, but not 1. 293*e7b1675dSTing-Kang Chang ciphertext3 = enc_aead3.encrypt(b'plaintext', b'ad') 294*e7b1675dSTing-Kang Chang with self.assertRaises(tink.TinkError): 295*e7b1675dSTing-Kang Chang _ = dec_aead1.decrypt(ciphertext3, b'ad') 296*e7b1675dSTing-Kang Chang self.assertEqual(dec_aead2.decrypt(ciphertext3, b'ad'), b'plaintext') 297*e7b1675dSTing-Kang Chang self.assertEqual(dec_aead3.decrypt(ciphertext3, b'ad'), b'plaintext') 298*e7b1675dSTing-Kang Chang self.assertEqual(dec_aead4.decrypt(ciphertext3, b'ad'), b'plaintext') 299*e7b1675dSTing-Kang Chang 300*e7b1675dSTing-Kang Chang # 4 encrypts with the newer key. So 2, 3 and 4 can decrypt it, but not 1. 301*e7b1675dSTing-Kang Chang ciphertext4 = enc_aead4.encrypt(b'plaintext', b'ad') 302*e7b1675dSTing-Kang Chang with self.assertRaises(tink.TinkError): 303*e7b1675dSTing-Kang Chang _ = dec_aead1.decrypt(ciphertext4, b'ad') 304*e7b1675dSTing-Kang Chang self.assertEqual(dec_aead2.decrypt(ciphertext4, b'ad'), b'plaintext') 305*e7b1675dSTing-Kang Chang self.assertEqual(dec_aead3.decrypt(ciphertext4, b'ad'), b'plaintext') 306*e7b1675dSTing-Kang Chang self.assertEqual(dec_aead4.decrypt(ciphertext4, b'ad'), b'plaintext') 307*e7b1675dSTing-Kang Chang 308*e7b1675dSTing-Kang Changif __name__ == '__main__': 309*e7b1675dSTing-Kang Chang absltest.main() 310