• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2019 Google LLC
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#      http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15"""Tests for tink.python.tink.hybrid_key_manager."""
16
17from typing import cast
18from absl.testing import absltest
19from absl.testing import parameterized
20from tink.proto import common_pb2
21from tink.proto import ecies_aead_hkdf_pb2
22from tink.proto import hpke_pb2
23from tink.proto import tink_pb2
24import tink
25from tink import aead
26from tink import core
27from tink import hybrid
28
29
30def setUpModule():
31  hybrid.register()
32
33
34class HybridKeyManagerTest(parameterized.TestCase):
35
36  def test_new_key_data(self):
37    tmpl = hybrid.hybrid_key_templates.ECIES_P256_HKDF_HMAC_SHA256_AES128_GCM
38    key_manager = core.Registry.key_manager(tmpl.type_url)
39    key_data = key_manager.new_key_data(tmpl)
40    self.assertEqual(key_data.type_url, key_manager.key_type())
41    self.assertEqual(key_data.key_material_type,
42                     tink_pb2.KeyData.ASYMMETRIC_PRIVATE)
43    key = ecies_aead_hkdf_pb2.EciesAeadHkdfPrivateKey.FromString(key_data.value)
44    self.assertLen(key.key_value, 32)
45    self.assertEqual(key.public_key.params.kem_params.curve_type,
46                     common_pb2.NIST_P256)
47
48  def test_new_keyset_handle_invalid_params_throw_exception(self):
49    templates = hybrid.hybrid_key_templates
50    key_template = templates.create_ecies_aead_hkdf_key_template(
51        curve_type=cast(common_pb2.EllipticCurveType, 100),
52        ec_point_format=common_pb2.UNCOMPRESSED,
53        hash_type=common_pb2.SHA256,
54        dem_key_template=aead.aead_key_templates.AES128_GCM)
55    with self.assertRaises(core.TinkError):
56      tink.new_keyset_handle(key_template)
57
58  def test_new_keyset_handle_on_public_key_fails(self):
59    key_format = ecies_aead_hkdf_pb2.EciesAeadHkdfKeyFormat()
60    key_template = tink_pb2.KeyTemplate()
61    key_template.type_url = (
62        'type.googleapis.com/google.crypto.tink.EciesAeadHkdfPublicKey')
63    key_template.value = key_format.SerializeToString()
64    key_template.output_prefix_type = tink_pb2.TINK
65    with self.assertRaises(core.TinkError):
66      tink.new_keyset_handle(key_template)
67
68  @parameterized.parameters([
69      hybrid.hybrid_key_templates.ECIES_P256_HKDF_HMAC_SHA256_AES128_GCM, hybrid
70      .hybrid_key_templates.ECIES_P256_HKDF_HMAC_SHA256_AES128_CTR_HMAC_SHA256
71  ])
72  def test_encrypt_decrypt(self, template):
73    private_handle = tink.new_keyset_handle(template)
74    public_handle = private_handle.public_keyset_handle()
75    hybrid_enc = public_handle.primitive(hybrid.HybridEncrypt)
76    ciphertext = hybrid_enc.encrypt(b'some plaintext', b'some context info')
77    hybrid_dec = private_handle.primitive(hybrid.HybridDecrypt)
78    self.assertEqual(hybrid_dec.decrypt(ciphertext, b'some context info'),
79                     b'some plaintext')
80
81  @parameterized.parameters([
82      hybrid.hybrid_key_templates.ECIES_P256_HKDF_HMAC_SHA256_AES128_GCM, hybrid
83      .hybrid_key_templates.ECIES_P256_HKDF_HMAC_SHA256_AES128_CTR_HMAC_SHA256
84  ])
85  def test_decrypt_fails(self, template):
86    private_handle = tink.new_keyset_handle(template)
87    hybrid_dec = private_handle.primitive(hybrid.HybridDecrypt)
88    with self.assertRaises(core.TinkError):
89      hybrid_dec.decrypt(b'bad ciphertext', b'some context info')
90
91
92class HpkeKeyManagerTest(parameterized.TestCase):
93
94  def test_new_key_data(self):
95    tmpl = hybrid.hybrid_key_templates.DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_128_GCM
96    key_manager = core.Registry.key_manager(tmpl.type_url)
97    key_data = key_manager.new_key_data(tmpl)
98    self.assertEqual(key_data.type_url, key_manager.key_type())
99    self.assertEqual(key_data.key_material_type,
100                     tink_pb2.KeyData.ASYMMETRIC_PRIVATE)
101    key = hpke_pb2.HpkePrivateKey.FromString(key_data.value)
102    self.assertLen(key.private_key, 32)  # HPKE 'Nsk' parameter length  = 32
103    self.assertEqual(key.public_key.params.kem,
104                     hpke_pb2.DHKEM_X25519_HKDF_SHA256)
105    self.assertEqual(key.public_key.params.kdf, hpke_pb2.HKDF_SHA256)
106    self.assertEqual(key.public_key.params.aead, hpke_pb2.AES_128_GCM)
107
108  def test_new_keyset_handle_invalid_kem_raises_exception(self):
109    templates = hybrid.hybrid_key_templates
110    key_template = templates._create_hpke_key_template(
111        hpke_kem=hpke_pb2.KEM_UNKNOWN,
112        hpke_kdf=hpke_pb2.HKDF_SHA256,
113        hpke_aead=hpke_pb2.AES_128_GCM,
114        output_prefix_type=tink_pb2.TINK)
115    with self.assertRaises(core.TinkError):
116      tink.new_keyset_handle(key_template)
117
118  def test_new_keyset_handle_invalid_kdf_raises_exception(self):
119    templates = hybrid.hybrid_key_templates
120    key_template = templates._create_hpke_key_template(
121        hpke_kem=hpke_pb2.DHKEM_X25519_HKDF_SHA256,
122        hpke_kdf=hpke_pb2.KDF_UNKNOWN,
123        hpke_aead=hpke_pb2.AES_128_GCM,
124        output_prefix_type=tink_pb2.TINK)
125    with self.assertRaises(core.TinkError):
126      tink.new_keyset_handle(key_template)
127
128  def test_new_keyset_handle_invalid_aead_raises_exception(self):
129    templates = hybrid.hybrid_key_templates
130    key_template = templates._create_hpke_key_template(
131        hpke_kem=hpke_pb2.DHKEM_X25519_HKDF_SHA256,
132        hpke_kdf=hpke_pb2.HKDF_SHA256,
133        hpke_aead=hpke_pb2.AEAD_UNKNOWN,
134        output_prefix_type=tink_pb2.TINK)
135    with self.assertRaises(core.TinkError):
136      tink.new_keyset_handle(key_template)
137
138  def test_new_keyset_handle_on_public_key_fails(self):
139    key_format = hpke_pb2.HpkeKeyFormat()
140    key_template = tink_pb2.KeyTemplate()
141    key_template.type_url = (
142        'type.googleapis.com/google.crypto.tink.HpkePublicKey')
143    key_template.value = key_format.SerializeToString()
144    key_template.output_prefix_type = tink_pb2.TINK
145    with self.assertRaises(core.TinkError):
146      tink.new_keyset_handle(key_template)
147
148  @parameterized.parameters([
149      hybrid.hybrid_key_templates
150      .DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_128_GCM,
151      hybrid.hybrid_key_templates
152      .DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_128_GCM_RAW, hybrid
153      .hybrid_key_templates.DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_256_GCM,
154      hybrid.hybrid_key_templates
155      .DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_256_GCM_RAW,
156      hybrid.hybrid_key_templates
157      .DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_CHACHA20_POLY1305,
158      hybrid.hybrid_key_templates
159      .DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_CHACHA20_POLY1305_RAW
160  ])
161  def test_encrypt_decrypt(self, template):
162    private_handle = tink.new_keyset_handle(template)
163    public_handle = private_handle.public_keyset_handle()
164    hybrid_encrypt = public_handle.primitive(hybrid.HybridEncrypt)
165    ciphertext = hybrid_encrypt.encrypt(b'some plaintext', b'some context info')
166    hybrid_decrypt = private_handle.primitive(hybrid.HybridDecrypt)
167    self.assertEqual(
168        hybrid_decrypt.decrypt(ciphertext, b'some context info'),
169        b'some plaintext')
170
171  @parameterized.parameters([
172      hybrid.hybrid_key_templates
173      .DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_128_GCM,
174      hybrid.hybrid_key_templates
175      .DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_128_GCM_RAW, hybrid
176      .hybrid_key_templates.DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_256_GCM,
177      hybrid.hybrid_key_templates
178      .DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_256_GCM_RAW,
179      hybrid.hybrid_key_templates
180      .DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_CHACHA20_POLY1305,
181      hybrid.hybrid_key_templates
182      .DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_CHACHA20_POLY1305_RAW
183  ])
184  def test_decrypt_fails(self, template):
185    private_handle = tink.new_keyset_handle(template)
186    hybrid_decrypt = private_handle.primitive(hybrid.HybridDecrypt)
187    with self.assertRaises(core.TinkError):
188      hybrid_decrypt.decrypt(b'bad ciphertext', b'some context info')
189
190if __name__ == '__main__':
191  absltest.main()
192