Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/google/auth/crypt/base.py: 72%
36 statements
« prev ^ index » next coverage.py v7.2.2, created at 2023-03-26 07:30 +0000
« prev ^ index » next coverage.py v7.2.2, created at 2023-03-26 07:30 +0000
1# Copyright 2016 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.
15"""Base classes for cryptographic signers and verifiers."""
17import abc
18import io
19import json
21import six
23from google.auth import exceptions
25_JSON_FILE_PRIVATE_KEY = "private_key"
26_JSON_FILE_PRIVATE_KEY_ID = "private_key_id"
29@six.add_metaclass(abc.ABCMeta)
30class Verifier(object):
31 """Abstract base class for crytographic signature verifiers."""
33 @abc.abstractmethod
34 def verify(self, message, signature):
35 """Verifies a message against a cryptographic signature.
37 Args:
38 message (Union[str, bytes]): The message to verify.
39 signature (Union[str, bytes]): The cryptography signature to check.
41 Returns:
42 bool: True if message was signed by the private key associated
43 with the public key that this object was constructed with.
44 """
45 # pylint: disable=missing-raises-doc,redundant-returns-doc
46 # (pylint doesn't recognize that this is abstract)
47 raise NotImplementedError("Verify must be implemented")
50@six.add_metaclass(abc.ABCMeta)
51class Signer(object):
52 """Abstract base class for cryptographic signers."""
54 @abc.abstractproperty
55 def key_id(self):
56 """Optional[str]: The key ID used to identify this private key."""
57 raise NotImplementedError("Key id must be implemented")
59 @abc.abstractmethod
60 def sign(self, message):
61 """Signs a message.
63 Args:
64 message (Union[str, bytes]): The message to be signed.
66 Returns:
67 bytes: The signature of the message.
68 """
69 # pylint: disable=missing-raises-doc,redundant-returns-doc
70 # (pylint doesn't recognize that this is abstract)
71 raise NotImplementedError("Sign must be implemented")
74@six.add_metaclass(abc.ABCMeta)
75class FromServiceAccountMixin(object):
76 """Mix-in to enable factory constructors for a Signer."""
78 @abc.abstractmethod
79 def from_string(cls, key, key_id=None):
80 """Construct an Signer instance from a private key string.
82 Args:
83 key (str): Private key as a string.
84 key_id (str): An optional key id used to identify the private key.
86 Returns:
87 google.auth.crypt.Signer: The constructed signer.
89 Raises:
90 ValueError: If the key cannot be parsed.
91 """
92 raise NotImplementedError("from_string must be implemented")
94 @classmethod
95 def from_service_account_info(cls, info):
96 """Creates a Signer instance instance from a dictionary containing
97 service account info in Google format.
99 Args:
100 info (Mapping[str, str]): The service account info in Google
101 format.
103 Returns:
104 google.auth.crypt.Signer: The constructed signer.
106 Raises:
107 ValueError: If the info is not in the expected format.
108 """
109 if _JSON_FILE_PRIVATE_KEY not in info:
110 raise exceptions.MalformedError(
111 "The private_key field was not found in the service account " "info."
112 )
114 return cls.from_string(
115 info[_JSON_FILE_PRIVATE_KEY], info.get(_JSON_FILE_PRIVATE_KEY_ID)
116 )
118 @classmethod
119 def from_service_account_file(cls, filename):
120 """Creates a Signer instance from a service account .json file
121 in Google format.
123 Args:
124 filename (str): The path to the service account .json file.
126 Returns:
127 google.auth.crypt.Signer: The constructed signer.
128 """
129 with io.open(filename, "r", encoding="utf-8") as json_file:
130 data = json.load(json_file)
132 return cls.from_service_account_info(data)