blob: 945197ca75b9d935dee6714eab1a30a876767c93 [file] [log] [blame]
# Copyright 2020 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.testing.cross_language.util.key_util."""
from absl.testing import absltest
from absl.testing import parameterized
from google.protobuf import text_format
from tink.proto import tink_pb2
from util import key_util
KEY_TEMPLATE_1 = r"""
type_url: "type.googleapis.com/google.crypto.tink.EciesAeadHkdfPrivateKey"
value: "\n@\022>\022<\n0type.googleapis.com/google.crypto.tink.AesEaxKey\022\006\n\002\010\020\020\020\030\001"
output_prefix_type: RAW
"""
# The same template as 1, but here AesEaxKeyFormat is encoded differently
KEY_TEMPLATE_1_NOT_NORMALIZED = r"""
type_url: "type.googleapis.com/google.crypto.tink.EciesAeadHkdfPrivateKey"
value: "\n@\022>\022<\n0type.googleapis.com/google.crypto.tink.AesEaxKey\022\006\020\020\n\002\010\020\030\001"
output_prefix_type: RAW
"""
# The same template as 1, but the inner AesEaxKeyFormat has a different iv_size
KEY_TEMPLATE_2 = r"""
type_url: "type.googleapis.com/google.crypto.tink.EciesAeadHkdfPrivateKey"
value: "\n@\022>\022<\n0type.googleapis.com/google.crypto.tink.AesEaxKey\022\006\n\002\010\020\020\022\030\001"
output_prefix_type: RAW
"""
KEY_TEMPLATE_1_COMMENTED_FORMAT = r"""
type_url: "type.googleapis.com/google.crypto.tink.EciesAeadHkdfPrivateKey"
# value: [type.googleapis.com/google.crypto.tink.EciesAeadHkdfKeyFormat] {
# params {
# kem_params {
# curve_type: UNKNOWN_CURVE
# hkdf_hash_type: UNKNOWN_HASH
# hkdf_salt: ""
# }
# dem_params {
# aead_dem {
# type_url: "type.googleapis.com/google.crypto.tink.AesEaxKey"
# # value: [type.googleapis.com/google.crypto.tink.AesEaxKeyFormat] {
# # params {
# # iv_size: 16
# # }
# # key_size: 16
# # }
# value: "\n\002\010\020\020\020"
# output_prefix_type: TINK
# }
# }
# ec_point_format: UNKNOWN_FORMAT
# }
# }
value: "\n@\022>\022<\n0type.googleapis.com/google.crypto.tink.AesEaxKey\022\006\n\002\010\020\020\020\030\001"
output_prefix_type: RAW
""".strip()
class KeyUtilTest(parameterized.TestCase):
def test_text_format_symmetric_key_template(self):
template = tink_pb2.KeyTemplate(
type_url='type.googleapis.com/google.crypto.tink.AesEaxKey',
value=b'\n\x02\x08\x10\x10\x10',
output_prefix_type=tink_pb2.TINK)
expected = r"""type_url: "type.googleapis.com/google.crypto.tink.AesEaxKey"
# value: [type.googleapis.com/google.crypto.tink.AesEaxKeyFormat] {
# params {
# iv_size: 16
# }
# key_size: 16
# }
value: "\n\002\010\020\020\020"
output_prefix_type: TINK"""
output = key_util.text_format(template)
self.assertEqual(output, expected)
# the output should be in text format, and result in the original template.
self.assertEqual(
text_format.Parse(output, tink_pb2.KeyTemplate()), template)
def test_text_format_asymmetric_key_template(self):
template = tink_pb2.KeyTemplate(
type_url='type.googleapis.com/google.crypto.tink.EcdsaPrivateKey',
value=b'\022\006\010\004\020\003\030\002',
output_prefix_type=tink_pb2.TINK)
expected = r"""type_url: "type.googleapis.com/google.crypto.tink.EcdsaPrivateKey"
# value: [type.googleapis.com/google.crypto.tink.EcdsaKeyFormat] {
# params {
# hash_type: SHA512
# curve: NIST_P384
# encoding: DER
# }
# version: 0
# }
value: "\022\006\010\004\020\003\030\002"
output_prefix_type: TINK"""
output = key_util.text_format(template)
self.assertEqual(output, expected)
# the output should be in text format, and result in the original template.
self.assertEqual(
text_format.Parse(output, tink_pb2.KeyTemplate()), template)
def test_text_format_recursive_template(self):
template = tink_pb2.KeyTemplate()
text_format.Parse(KEY_TEMPLATE_1, template)
output = key_util.text_format(template)
self.assertEqual(output, KEY_TEMPLATE_1_COMMENTED_FORMAT)
def test_text_format_normalizes_recursive_template(self):
template1a = tink_pb2.KeyTemplate()
text_format.Parse(KEY_TEMPLATE_1, template1a)
template = tink_pb2.KeyTemplate()
text_format.Parse(KEY_TEMPLATE_1_NOT_NORMALIZED, template)
# Before the call, the value is different (different serializations)
self.assertNotEqual(template1a.value, template.value)
normalized_template = key_util.text_format(template)
self.assertEqual(normalized_template, KEY_TEMPLATE_1_COMMENTED_FORMAT)
# We explicitly test that the value has not been changed (since this
# requirement needs an explicit copy in the code)
self.assertNotEqual(template1a.value, template.value)
def test_text_format_keyset(self):
key = tink_pb2.Keyset.Key(
key_data=tink_pb2.KeyData(
type_url='type.googleapis.com/google.crypto.tink.AesGcmKey',
value=b'\032\020Z\027\031\027\362\353\020\320\257p\271^\260\022\344\274',
key_material_type=tink_pb2.KeyData.SYMMETRIC),
status=tink_pb2.ENABLED,
key_id=3588418072,
output_prefix_type=tink_pb2.TINK)
keyset = tink_pb2.Keyset(primary_key_id=3588418072)
keyset.key.append(key)
expected = r"""primary_key_id: 3588418072
key {
key_data {
type_url: "type.googleapis.com/google.crypto.tink.AesGcmKey"
# value: [type.googleapis.com/google.crypto.tink.AesGcmKey] {
# version: 0
# key_value: "Z\027\031\027\362\353\020\320\257p\271^\260\022\344\274"
# }
value: "\032\020Z\027\031\027\362\353\020\320\257p\271^\260\022\344\274"
key_material_type: SYMMETRIC
}
status: ENABLED
key_id: 3588418072
output_prefix_type: TINK
}"""
output = key_util.text_format(keyset)
self.assertEqual(output, expected)
# the output should be in text format, and result in the original template.
self.assertEqual(
text_format.Parse(output, tink_pb2.Keyset()), keyset)
def test_compare_tink_messages(self):
"""Tests that all testdata have the expected format, including comments."""
key_template_1 = text_format.Parse(KEY_TEMPLATE_1, tink_pb2.KeyTemplate())
key_template_1_not_normalized = text_format.Parse(
KEY_TEMPLATE_1_NOT_NORMALIZED, tink_pb2.KeyTemplate())
key_util.assert_tink_proto_equal(self, key_template_1,
key_template_1_not_normalized)
key_template_2 = text_format.Parse(KEY_TEMPLATE_2, tink_pb2.KeyTemplate())
with self.assertRaises(AssertionError):
key_util.assert_tink_proto_equal(self, key_template_1, key_template_2)
def test_parse_text_format_symmetric_key_template(self):
serialized = r"""type_url: "type.googleapis.com/google.crypto.tink.AesEaxKey"
# value: [type.googleapis.com/google.crypto.tink.AesEaxKeyFormat] {
# params {
# iv_size: 16
# }
# key_size: 16
# }
value: "\n\002\010\020\020\020"
output_prefix_type: TINK"""
expected = tink_pb2.KeyTemplate(
type_url='type.googleapis.com/google.crypto.tink.AesEaxKey',
value=b'\n\x02\x08\x10\x10\x10',
output_prefix_type=tink_pb2.TINK)
parsed_template = tink_pb2.KeyTemplate()
key_util.parse_text_format(serialized, parsed_template)
self.assertEqual(parsed_template, expected)
def test_parse_text_format_wrong_comment(self):
serialized = r"""type_url: "type.googleapis.com/google.crypto.tink.AesEaxKey"
value: "\n\002\010\020\020\020"
output_prefix_type: TINK"""
parsed_template = tink_pb2.KeyTemplate()
with self.assertRaises(AssertionError):
key_util.parse_text_format(serialized, parsed_template)
def test_parse_text_format_missing_comment(self):
serialized = r"""type_url: "type.googleapis.com/google.crypto.tink.AesEaxKey"
# value: [type.googleapis.com/google.crypto.tink.AesEaxKeyFormat] {
# params {
# iv_size: 16
# }
# key_size: 18
# }
value: "\n\002\010\020\020\020"
output_prefix_type: TINK"""
parsed_template = tink_pb2.KeyTemplate()
with self.assertRaises(AssertionError):
key_util.parse_text_format(serialized, parsed_template)
def test_assert_tink_proto_equal_does_not_modify_messages(self):
"""Tests that assert_tink_proto_equal does not modify the message."""
key_template_1 = text_format.Parse(KEY_TEMPLATE_1, tink_pb2.KeyTemplate())
key_template_1_original = text_format.Parse(
KEY_TEMPLATE_1_NOT_NORMALIZED, tink_pb2.KeyTemplate())
key_template_1_not_normalized = text_format.Parse(
KEY_TEMPLATE_1_NOT_NORMALIZED, tink_pb2.KeyTemplate())
key_util.assert_tink_proto_equal(self, key_template_1,
key_template_1_not_normalized)
self.assertEqual(key_template_1_original.value,
key_template_1_not_normalized.value)
key_util.assert_tink_proto_equal(self, key_template_1_not_normalized,
key_template_1)
self.assertEqual(key_template_1_original.value,
key_template_1_not_normalized.value)
def test_text_format_with_empty_value(self):
expected = r"""type_url: "type.googleapis.com/google.crypto.tink.ChaCha20Poly1305Key"
# value: [type.googleapis.com/google.crypto.tink.ChaCha20Poly1305KeyFormat] {
# }
value: ""
output_prefix_type: RAW"""
template = tink_pb2.KeyTemplate(
type_url='type.googleapis.com/google.crypto.tink.ChaCha20Poly1305Key',
output_prefix_type=tink_pb2.RAW)
formatted = key_util.text_format(template)
self.assertEqual(formatted, expected)
if __name__ == '__main__':
absltest.main()