• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2022 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"""Helper functions to access the information in this module.
15"""
16
17from typing import Any, Iterable, List
18
19from tink.proto import tink_pb2
20from tink_config import _key_types
21
22_TYPE_URL_PREFIX = 'type.googleapis.com/google.crypto.tink.'
23
24
25def all_key_types() -> List[str]:
26  """Returns all key types which Tink currently knows in short format.
27
28  The related TypeUrl equals the short format returned here, but prefixed with
29  type.googleapis.com/google.crypto.tink.
30  """
31  result = []
32  for key_types_for_single_primitive in _key_types.KEY_TYPES.values():
33    result += key_types_for_single_primitive
34  return result
35
36
37def key_types_for_primitive(p: Any) -> List[str]:
38  """Returns all key types for the given primitive which Tink currently has.
39
40  The related TypeUrl equals the short format returned here, but prefixed with
41  type.googleapis.com/google.crypto.tink.
42  Args:
43    p: The class of the primitive (e.g. tink.Aead)
44  Returns:
45    The list of key types (e.g. ['AesGcmKey', 'AesEaxKey'])
46  """
47  return list(_key_types.KEY_TYPES[p])
48
49
50def key_type_from_type_url(type_url: str) -> str:
51  """Returns the key type from a given TypeUrl.
52
53  If the TypeUrl is invalid throws an exception.
54  Args:
55    type_url: For example 'type.googleapis.com/google.crypto.tink.AesGcmKey'
56  Returns:
57    The stripped version (e.g. AesGcmKey)
58  Raises:
59    ValueError if the type url is unknown or in a bad format.
60  """
61  if not type_url.startswith(_TYPE_URL_PREFIX):
62    raise ValueError('Invalid type_url: ' + type_url)
63  # removeprefix does not yet exist in all our supported python versions.
64  key_type = type_url[len(_TYPE_URL_PREFIX):]
65  if key_type not in all_key_types():
66    raise ValueError('key type unknown: ' + key_type)
67  return key_type
68
69
70def supported_languages_for_key_type(key_type: str) -> List[str]:
71  """Returns the list of supported languages for a given KeyType.
72
73    Throws an except if the key type is unkonwn.
74  Args:
75    key_type: The shortened type URL (e.g. 'AesGcmKey')
76  Returns:
77    The list of languages which this key type supportes.
78  Raises:
79    ValueError if the key type is unknown.
80  """
81  if key_type not in all_key_types():
82    raise ValueError('key_type unknown: ' + key_type)
83  return _key_types.SUPPORTED_LANGUAGES[key_type]
84
85
86def supported_languages_for_primitive(p: Any) -> List[str]:
87  """Returns the list of languages which support a primitive.
88
89    Throws an except if the key type is unkonwn.
90  Args:
91    p: The Primitive
92  Returns:
93    The list of languages which this primitive supportes.
94  Raises:
95    ValueError if the key type is unknown.
96  """
97  result = set()
98  for key_type in key_types_for_primitive(p):
99    result.update(set(supported_languages_for_key_type(key_type)))
100  return list(result)
101
102
103def all_primitives() -> Iterable[Any]:
104  """Returns all the primitive types (such as tink.aead.Aead)."""
105  return [p for p, _ in _key_types.KEY_TYPES.items()]
106
107
108def primitive_for_keytype(key_type: str) -> Any:
109  """Returns the primitive for the given key type."""
110
111  for p, key_types in _key_types.KEY_TYPES.items():
112    if key_type in key_types:
113      return p
114  raise ValueError('Unknown key type: ' + key_type)
115
116
117def is_asymmetric_public_key_primitive(p: Any) -> bool:
118  """Returns true iff this p is the public part of an asymmetric scheme."""
119  return p in _key_types.PRIVATE_TO_PUBLIC_PRIMITIVE.values()
120
121
122def get_private_key_primitive(p: Any) -> Any:
123  """Returns the private primitive corresponding to this public part."""
124  inverted = {v: k for (k, v) in _key_types.PRIVATE_TO_PUBLIC_PRIMITIVE.items()}
125  return inverted[p]
126
127
128def _key_types_in_keyset(keyset: bytes) -> List[str]:
129  parsed_keyset = tink_pb2.Keyset.FromString(keyset)
130  type_urls = [k.key_data.type_url for k in parsed_keyset.key]
131  return [key_type_from_type_url(t) for t in type_urls]
132
133
134def keyset_supported(keyset: bytes, p: Any, lang: str) -> bool:
135  """Checks if the given keyset can be instantiated as 'p' in the 'lang'.
136
137  Returns true if it is expected that the keyset can be instantiated in language
138  'lang', according to the current configuration stored in tink_config. This
139  only looks at the key types in the keyset, and does not check if the keys
140  themselves are valid. It also does not check that the keyset is valid.
141
142  Args:
143    keyset: The serialized keyset
144    p: The primitive class, e.g. aead.Aead
145    lang: The language, e.g. 'python' or 'java'.
146
147  Returns:
148    True iff all key types are for this primitive and supported in the given
149    language.
150  """
151
152  key_types = _key_types_in_keyset(keyset)
153  for key_type in key_types:
154    if primitive_for_keytype(key_type) != p:
155      return False
156    if lang not in supported_languages_for_key_type(key_type):
157      return False
158  return True
159