xref: /aosp_15_r20/external/tink/testing/cross_language/aead_test.py (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
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