diff --git a/python/daead/__init__.py b/python/daead/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..eed4692505719532df3e960195e03f691487eefa
--- /dev/null
+++ b/python/daead/__init__.py
@@ -0,0 +1,28 @@
+# Copyright 2019 Google LLC.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Deterministic aead package."""
+from __future__ import absolute_import
+from __future__ import division
+from __future__ import google_type_annotations
+from __future__ import print_function
+
+from tink.python.daead import deterministic_aead
+from tink.python.daead import deterministic_aead_key_manager
+from tink.python.daead import deterministic_aead_key_templates
+from tink.python.daead import deterministic_aead_wrapper
+
+
+DeterministicAead = deterministic_aead.DeterministicAead
+DeterministicAeadWrapper = deterministic_aead_wrapper.DeterministicAeadWrapper
diff --git a/python/daead/deterministic_aead.py b/python/daead/deterministic_aead.py
new file mode 100644
index 0000000000000000000000000000000000000000..3ad06678e1e5a2366ee2e172731b6acdf4b4b784
--- /dev/null
+++ b/python/daead/deterministic_aead.py
@@ -0,0 +1,59 @@
+# Copyright 2019 Google LLC.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""This module defines the interface for Deterministic AEAD."""
+
+from __future__ import absolute_import
+from __future__ import division
+from __future__ import google_type_annotations
+from __future__ import print_function
+
+import abc
+
+
+class DeterministicAead(object):
+  """Interface for Deterministic Authenticated Encryption with Associated Data.
+
+  For why this interface is desirable and some of its use cases, see for
+  example https://tools.ietf.org/html/rfc5297#section-1.3.
+
+  Warning!
+
+  Unlike Aead, implementations of this interface are not semantically
+  secure, because encrypting the same plaintex always yields the same
+  ciphertext.
+
+  Security guarantees
+
+  Implementations of this interface provide 128-bit security level against
+  multi-user attacks with up to 2^32 keys. That means if an adversary
+  obtains 2^32 ciphertexts of the same message encrypted under 2^32 keys,
+  they need to do 2^128 computations to obtain a single key.
+
+  Encryption with associated data ensures authenticity (who the sender is)
+  and integrity (the data has not been tampered with) of that data, but not
+  its secrecy. (see https://tools.ietf.org/html/rfc5116)
+  """
+
+  __metaclass__ = abc.ABCMeta
+
+  @abc.abstractmethod
+  def encrypt_deterministically(self, plaintext: bytes,
+                                associated_data: bytes) -> bytes:
+    raise NotImplementedError()
+
+  @abc.abstractmethod
+  def decrypt_deterministically(self, ciphertext: bytes,
+                                associated_data: bytes) -> bytes:
+    raise NotImplementedError()
diff --git a/python/daead/deterministic_aead_key_manager.py b/python/daead/deterministic_aead_key_manager.py
new file mode 100644
index 0000000000000000000000000000000000000000..bb27376b3a9a8272225d336b0f6f2bab39640b31
--- /dev/null
+++ b/python/daead/deterministic_aead_key_manager.py
@@ -0,0 +1,54 @@
+# Copyright 2019 Google LLC.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Python wrapper of the CLIF-wrapped C++ Deterministic AEAD key manager."""
+
+from __future__ import absolute_import
+from __future__ import division
+from __future__ import google_type_annotations
+from __future__ import print_function
+
+from typing import Text
+
+from tink.python.cc.clif import cc_key_manager
+from tink.python.core import key_manager
+from tink.python.core import tink_error
+from tink.python.daead import deterministic_aead
+
+
+class _DeterministicAeadCcToPyWrapper(deterministic_aead.DeterministicAead):
+  """Transforms cliffed C++ DeterministicAead into a Python primitive."""
+
+  def __init__(self, cc_deterministic_aead):
+    self._deterministic_aead = cc_deterministic_aead
+
+  @tink_error.use_tink_errors
+  def encrypt_deterministically(self, plaintext: bytes,
+                                associated_data: bytes) -> bytes:
+    return self._deterministic_aead.encrypt_deterministically(
+        plaintext, associated_data)
+
+  @tink_error.use_tink_errors
+  def decrypt_deterministically(self, ciphertext: bytes,
+                                associated_data: bytes) -> bytes:
+    return self._deterministic_aead.decrypt_deterministically(
+        ciphertext, associated_data)
+
+
+def from_cc_registry(
+    type_url: Text
+) -> key_manager.KeyManager[deterministic_aead.DeterministicAead]:
+  return key_manager.KeyManagerCcToPyWrapper(
+      cc_key_manager.DeterministicAeadKeyManager.from_cc_registry(type_url),
+      deterministic_aead.DeterministicAead, _DeterministicAeadCcToPyWrapper)
diff --git a/python/daead/deterministic_aead_key_manager_test.py b/python/daead/deterministic_aead_key_manager_test.py
new file mode 100644
index 0000000000000000000000000000000000000000..c8ad6e128d2ce8357f9e06d83b662985de9934ed
--- /dev/null
+++ b/python/daead/deterministic_aead_key_manager_test.py
@@ -0,0 +1,81 @@
+# Copyright 2019 Google LLC.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Tests for tink.python.aead_key_manager."""
+
+from __future__ import absolute_import
+from __future__ import division
+from __future__ import print_function
+
+import unittest
+from tink.proto import aes_siv_pb2
+from tink.proto import tink_pb2
+from tink.python.core import tink_config
+from tink.python.core import tink_error
+from tink.python.daead import deterministic_aead
+from tink.python.daead import deterministic_aead_key_manager
+from tink.python.daead import deterministic_aead_key_templates
+
+
+def setUpModule():
+  tink_config.register()
+
+
+class DeterministicAeadKeyManagerTest(googletest.TestCase):
+
+  def setUp(self):
+    super(DeterministicAeadKeyManagerTest, self).setUp()
+    self.key_manager = deterministic_aead_key_manager.from_cc_registry(
+        'type.googleapis.com/google.crypto.tink.AesSivKey')
+
+  def test_primitive_class(self):
+    self.assertEqual(self.key_manager.primitive_class(),
+                     deterministic_aead.DeterministicAead)
+
+  def test_key_type(self):
+    self.assertEqual(self.key_manager.key_type(),
+                     'type.googleapis.com/google.crypto.tink.AesSivKey')
+
+  def test_new_key_data(self):
+    key_template = deterministic_aead_key_templates.AES256_SIV
+    key_data = self.key_manager.new_key_data(key_template)
+    self.assertEqual(key_data.type_url, self.key_manager.key_type())
+    self.assertEqual(key_data.key_material_type, tink_pb2.KeyData.SYMMETRIC)
+    key = aes_siv_pb2.AesSivKey()
+    key.ParseFromString(key_data.value)
+    self.assertEqual(key.version, 0)
+    self.assertLen(key.key_value, 64)
+
+  def test_invalid_params_throw_exception(self):
+    key_template = deterministic_aead_key_templates.create_aes_siv_key_template(
+        63)
+    with self.assertRaisesRegex(tink_error.TinkError,
+                                'Invalid AesSivKeyFormat'):
+      self.key_manager.new_key_data(key_template)
+
+  def test_encrypt_decrypt(self):
+    daead_primitive = self.key_manager.primitive(
+        self.key_manager.new_key_data(
+            deterministic_aead_key_templates.AES256_SIV))
+    plaintext = b'plaintext'
+    associated_data = b'associated_data'
+    ciphertext = daead_primitive.encrypt_deterministically(
+        plaintext, associated_data)
+    self.assertEqual(
+        daead_primitive.decrypt_deterministically(ciphertext, associated_data),
+        plaintext)
+
+
+if __name__ == '__main__':
+  googletest.main()
diff --git a/python/daead/deterministic_aead_key_templates.py b/python/daead/deterministic_aead_key_templates.py
new file mode 100644
index 0000000000000000000000000000000000000000..c80a4bfb834855925fdcaafbc787ac5c718d4d30
--- /dev/null
+++ b/python/daead/deterministic_aead_key_templates.py
@@ -0,0 +1,46 @@
+# Copyright 2019 Google LLC.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Pre-generated KeyTemplate for DeterministicAead.
+
+One can use these templates to generate new tink_pb2.Keyset with
+tink_pb2.KeysetHandle. To generate a new keyset that contains a single
+tink_pb2.HmacKey, one can do:
+handle = keyset_handle.KeysetHandle(aead_key_templates.AES128_EAX).
+"""
+
+from __future__ import absolute_import
+from __future__ import division
+from __future__ import google_type_annotations
+from __future__ import print_function
+
+from tink.proto import aes_siv_pb2
+from tink.proto import tink_pb2
+
+
+_AES_SIV_KEY_TYPE_URL = 'type.googleapis.com/google.crypto.tink.AesSivKey'
+
+
+def create_aes_siv_key_template(key_size: int) -> tink_pb2.KeyTemplate:
+  """Creates an AES EAX KeyTemplate, and fills in its values."""
+  key_format = aes_siv_pb2.AesSivKeyFormat()
+  key_format.key_size = key_size
+  key_template = tink_pb2.KeyTemplate()
+  key_template.type_url = _AES_SIV_KEY_TYPE_URL
+  key_template.output_prefix_type = tink_pb2.TINK
+  key_template.value = key_format.SerializeToString()
+  return key_template
+
+
+AES256_SIV = create_aes_siv_key_template(key_size=64)
diff --git a/python/daead/deterministic_aead_key_templates_test.py b/python/daead/deterministic_aead_key_templates_test.py
new file mode 100644
index 0000000000000000000000000000000000000000..dd45ee9b9997f173a9600d3b20bedf0bac40234d
--- /dev/null
+++ b/python/daead/deterministic_aead_key_templates_test.py
@@ -0,0 +1,51 @@
+# Copyright 2019 Google LLC.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Tests for tink.python.deterministic_aead_key_templates."""
+
+from __future__ import absolute_import
+from __future__ import division
+from __future__ import print_function
+
+import unittest
+from tink.proto import aes_siv_pb2
+from tink.proto import tink_pb2
+from tink.python.daead import deterministic_aead_key_templates
+
+
+class DeterministicAeadKeyTemplatesTest(googletest.TestCase):
+
+  def test_aes256_siv(self):
+    template = deterministic_aead_key_templates.AES256_SIV
+    self.assertEqual('type.googleapis.com/google.crypto.tink.AesSivKey',
+                     template.type_url)
+    self.assertEqual(tink_pb2.TINK, template.output_prefix_type)
+    key_format = aes_siv_pb2.AesSivKeyFormat()
+    key_format.ParseFromString(template.value)
+    self.assertEqual(64, key_format.key_size)
+
+  def test_create_aes_siv_key_template(self):
+    # Intentionally using 'weird' or invalid values for parameters,
+    # to test that the function correctly puts them in the resulting template.
+    template = deterministic_aead_key_templates.create_aes_siv_key_template(
+        key_size=42)
+    self.assertEqual('type.googleapis.com/google.crypto.tink.AesSivKey',
+                     template.type_url)
+    self.assertEqual(tink_pb2.TINK, template.output_prefix_type)
+    key_format = aes_siv_pb2.AesSivKeyFormat()
+    key_format.ParseFromString(template.value)
+    self.assertEqual(42, key_format.key_size)
+
+if __name__ == '__main__':
+  googletest.main()
diff --git a/python/daead/deterministic_aead_wrapper.py b/python/daead/deterministic_aead_wrapper.py
new file mode 100644
index 0000000000000000000000000000000000000000..f1b52e1e002cd03fd0f82a0f284f70b19677a491
--- /dev/null
+++ b/python/daead/deterministic_aead_wrapper.py
@@ -0,0 +1,84 @@
+# Copyright 2019 Google LLC.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Deterministic AEAD wrapper."""
+
+from __future__ import absolute_import
+from __future__ import division
+from __future__ import google_type_annotations
+from __future__ import print_function
+
+from typing import Type
+
+from pyglib import logging
+from tink.python.core import crypto_format
+from tink.python.core import primitive_set
+from tink.python.core import primitive_wrapper
+from tink.python.core import tink_error
+from tink.python.daead import deterministic_aead
+
+
+class _WrappedDeterministicAead(deterministic_aead.DeterministicAead):
+  """Implements DeterministicAead for a set of DeterministicAead primitives."""
+
+  def __init__(self, pset: primitive_set.PrimitiveSet):
+    self._primitive_set = pset
+
+  def encrypt_deterministically(self, plaintext: bytes,
+                                associated_data: bytes) -> bytes:
+    primary = self._primitive_set.primary()
+    return primary.identifier + primary.primitive.encrypt_deterministically(
+        plaintext, associated_data)
+
+  def decrypt_deterministically(self, ciphertext: bytes,
+                                associated_data: bytes) -> bytes:
+    if len(ciphertext) > crypto_format.NON_RAW_PREFIX_SIZE:
+      prefix = ciphertext[:crypto_format.NON_RAW_PREFIX_SIZE]
+      ciphertext_no_prefix = ciphertext[crypto_format.NON_RAW_PREFIX_SIZE:]
+      for entry in self._primitive_set.primitive_from_identifier(prefix):
+        try:
+          return entry.primitive.decrypt_deterministically(ciphertext_no_prefix,
+                                                           associated_data)
+        except tink_error.TinkError as e:
+          logging.info(
+              'ciphertext prefix matches a key, but cannot decrypt: %s', e)
+    # Let's try all RAW keys.
+    for entry in self._primitive_set.raw_primitives():
+      try:
+        return entry.primitive.decrypt_deterministically(ciphertext,
+                                                         associated_data)
+      except tink_error.TinkError as e:
+        pass
+    # nothing works.
+    raise tink_error.TinkError('Decryption failed.')
+
+
+class DeterministicAeadWrapper(
+    primitive_wrapper.PrimitiveWrapper[deterministic_aead.DeterministicAead]):
+  """DeterministicAeadWrapper is a PrimitiveWrapper for DeterministicAead.
+
+  The created primitive works with a keyset (rather than a single key). To
+  encrypt a plaintext, it uses the primary key in the keyset, and prepends to
+  the ciphertext a certain prefix associated with the primary key. To decrypt,
+  the primitive uses the prefix of the ciphertext to efficiently select the
+  right key in the set. If the keys associated with the prefix do not work, the
+  primitive tries all keys with OutputPrefixType RAW.
+  """
+
+  def wrap(self, pset: primitive_set.PrimitiveSet
+          ) -> deterministic_aead.DeterministicAead:
+    return _WrappedDeterministicAead(pset)
+
+  def primitive_class(self) -> Type[deterministic_aead.DeterministicAead]:
+    return deterministic_aead.DeterministicAead
diff --git a/python/daead/deterministic_aead_wrapper_test.py b/python/daead/deterministic_aead_wrapper_test.py
new file mode 100644
index 0000000000000000000000000000000000000000..d112d07c664094756dbdae7b31033835c37ffaf4
--- /dev/null
+++ b/python/daead/deterministic_aead_wrapper_test.py
@@ -0,0 +1,167 @@
+# Copyright 2019 Google LLC.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Tests for tink.python.aead_wrapper."""
+
+from __future__ import absolute_import
+from __future__ import division
+from __future__ import print_function
+
+import unittest
+from tink.proto import tink_pb2
+from tink.python.core import primitive_set
+from tink.python.core import tink_error
+from tink.python.daead import deterministic_aead
+from tink.python.daead import deterministic_aead_wrapper
+from tink.python.testing import helper
+
+
+class AeadWrapperTest(googletest.TestCase):
+
+  def new_primitive_key_pair(self, key_id, output_prefix_type):
+    fake_key = helper.fake_key(
+        key_id=key_id, output_prefix_type=output_prefix_type)
+    fake_aead = helper.FakeDeterministicAead(
+        'fakeDeterministicAead {}'.format(key_id))
+    return fake_aead, fake_key
+
+  def test_encrypt_decrypt(self):
+    primitive, key = self.new_primitive_key_pair(1234, tink_pb2.TINK)
+    pset = primitive_set.new_primitive_set(deterministic_aead.DeterministicAead)
+    entry = pset.add_primitive(primitive, key)
+    pset.set_primary(entry)
+
+    wrapped_daead = deterministic_aead_wrapper.DeterministicAeadWrapper().wrap(
+        pset)
+
+    plaintext = b'plaintext'
+    associated_data = b'associated_data'
+    ciphertext = wrapped_daead.encrypt_deterministically(
+        plaintext, associated_data)
+    self.assertEqual(
+        wrapped_daead.decrypt_deterministically(ciphertext, associated_data),
+        plaintext)
+
+  def test_encrypt_decrypt_with_key_rotation(self):
+    primitive, key = self.new_primitive_key_pair(1234, tink_pb2.TINK)
+    pset = primitive_set.new_primitive_set(deterministic_aead.DeterministicAead)
+    entry = pset.add_primitive(primitive, key)
+    pset.set_primary(entry)
+    wrapped_daead = deterministic_aead_wrapper.DeterministicAeadWrapper().wrap(
+        pset)
+    ciphertext = wrapped_daead.encrypt_deterministically(
+        b'plaintext', b'associated_data')
+
+    new_primitive, new_key = self.new_primitive_key_pair(5678, tink_pb2.TINK)
+    new_entry = pset.add_primitive(new_primitive, new_key)
+    pset.set_primary(new_entry)
+    new_ciphertext = wrapped_daead.encrypt_deterministically(
+        b'new_plaintext', b'new_associated_data')
+
+    self.assertEqual(
+        wrapped_daead.decrypt_deterministically(ciphertext, b'associated_data'),
+        b'plaintext')
+    self.assertEqual(
+        wrapped_daead.decrypt_deterministically(new_ciphertext,
+                                                b'new_associated_data'),
+        b'new_plaintext')
+
+  def test_encrypt_decrypt_with_key_rotation_from_raw(self):
+    primitive, raw_key = self.new_primitive_key_pair(1234, tink_pb2.RAW)
+    old_raw_ciphertext = primitive.encrypt_deterministically(
+        b'plaintext', b'associated_data')
+
+    pset = primitive_set.new_primitive_set(deterministic_aead.DeterministicAead)
+    pset.add_primitive(primitive, raw_key)
+    new_primitive, new_key = self.new_primitive_key_pair(5678, tink_pb2.TINK)
+    new_entry = pset.add_primitive(new_primitive, new_key)
+    pset.set_primary(new_entry)
+    wrapped_daead = deterministic_aead_wrapper.DeterministicAeadWrapper().wrap(
+        pset)
+    new_ciphertext = wrapped_daead.encrypt_deterministically(
+        b'new_plaintext', b'new_associated_data')
+
+    self.assertEqual(
+        wrapped_daead.decrypt_deterministically(old_raw_ciphertext,
+                                                b'associated_data'),
+        b'plaintext')
+    self.assertEqual(
+        wrapped_daead.decrypt_deterministically(new_ciphertext,
+                                                b'new_associated_data'),
+        b'new_plaintext')
+
+  def test_encrypt_decrypt_two_raw_keys(self):
+    primitive1, raw_key1 = self.new_primitive_key_pair(1234, tink_pb2.RAW)
+    primitive2, raw_key2 = self.new_primitive_key_pair(5678, tink_pb2.RAW)
+    raw_ciphertext1 = primitive1.encrypt_deterministically(
+        b'plaintext1', b'associated_data1')
+    raw_ciphertext2 = primitive2.encrypt_deterministically(
+        b'plaintext2', b'associated_data2')
+
+    pset = primitive_set.new_primitive_set(deterministic_aead.DeterministicAead)
+    pset.add_primitive(primitive1, raw_key1)
+    pset.set_primary(pset.add_primitive(primitive2, raw_key2))
+    wrapped_daead = deterministic_aead_wrapper.DeterministicAeadWrapper().wrap(
+        pset)
+
+    self.assertEqual(
+        wrapped_daead.decrypt_deterministically(raw_ciphertext1,
+                                                b'associated_data1'),
+        b'plaintext1')
+    self.assertEqual(
+        wrapped_daead.decrypt_deterministically(raw_ciphertext2,
+                                                b'associated_data2'),
+        b'plaintext2')
+    self.assertEqual(
+        wrapped_daead.decrypt_deterministically(
+            wrapped_daead.encrypt_deterministically(b'plaintext',
+                                                    b'associated_data'),
+            b'associated_data'), b'plaintext')
+
+  def test_decrypt_unknown_ciphertext_fails(self):
+    unknown_primitive = helper.FakeDeterministicAead(
+        'unknownFakeDeterministicAead')
+    unknown_ciphertext = unknown_primitive.encrypt_deterministically(
+        b'plaintext', b'associated_data')
+
+    pset = primitive_set.new_primitive_set(deterministic_aead.DeterministicAead)
+    primitive, raw_key = self.new_primitive_key_pair(1234, tink_pb2.RAW)
+    new_primitive, new_key = self.new_primitive_key_pair(5678, tink_pb2.TINK)
+    pset.add_primitive(primitive, raw_key)
+    new_entry = pset.add_primitive(new_primitive, new_key)
+    pset.set_primary(new_entry)
+    wrapped_daead = deterministic_aead_wrapper.DeterministicAeadWrapper().wrap(
+        pset)
+
+    with self.assertRaisesRegex(tink_error.TinkError, 'Decryption failed'):
+      wrapped_daead.decrypt_deterministically(unknown_ciphertext,
+                                              b'associated_data')
+
+  def test_decrypt_wrong_associated_data_fails(self):
+    primitive, key = self.new_primitive_key_pair(1234, tink_pb2.TINK)
+    pset = primitive_set.new_primitive_set(deterministic_aead.DeterministicAead)
+    entry = pset.add_primitive(primitive, key)
+    pset.set_primary(entry)
+    wrapped_daead = deterministic_aead_wrapper.DeterministicAeadWrapper().wrap(
+        pset)
+
+    ciphertext = wrapped_daead.encrypt_deterministically(
+        b'plaintext', b'associated_data')
+    with self.assertRaisesRegex(tink_error.TinkError, 'Decryption failed'):
+      wrapped_daead.decrypt_deterministically(ciphertext,
+                                              b'wrong_associated_data')
+
+
+if __name__ == '__main__':
+  googletest.main()