Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/google/auth/crypt/_cryptography_rsa.py: 52%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

56 statements  

1# Copyright 2017 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"""RSA verifier and signer that use the ``cryptography`` library. 

16 

17This is a much faster implementation than the default (in 

18``google.auth.crypt._python_rsa``), which depends on the pure-Python 

19``rsa`` library. 

20""" 

21 

22import cryptography.exceptions 

23import cryptography.x509 

24from cryptography.hazmat import backends 

25from cryptography.hazmat.primitives import hashes, serialization 

26from cryptography.hazmat.primitives.asymmetric import padding 

27 

28from google.auth import _helpers 

29from google.auth.crypt import base 

30 

31_CERTIFICATE_MARKER = b"-----BEGIN CERTIFICATE-----" 

32_BACKEND = backends.default_backend() 

33_PADDING = padding.PKCS1v15() 

34_SHA256 = hashes.SHA256() 

35 

36 

37class RSAVerifier(base.Verifier): 

38 """Verifies RSA cryptographic signatures using public keys. 

39 

40 Args: 

41 public_key ( 

42 cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey): 

43 The public key used to verify signatures. 

44 """ 

45 

46 def __init__(self, public_key): 

47 self._pubkey = public_key 

48 

49 @_helpers.copy_docstring(base.Verifier) 

50 def verify(self, message, signature): 

51 message = _helpers.to_bytes(message) 

52 try: 

53 self._pubkey.verify(signature, message, _PADDING, _SHA256) 

54 return True 

55 except (ValueError, cryptography.exceptions.InvalidSignature): 

56 return False 

57 

58 @classmethod 

59 def from_string(cls, public_key): 

60 """Construct an Verifier instance from a public key or public 

61 certificate string. 

62 

63 Args: 

64 public_key (Union[str, bytes]): The public key in PEM format or the 

65 x509 public key certificate. 

66 

67 Returns: 

68 Verifier: The constructed verifier. 

69 

70 Raises: 

71 ValueError: If the public key can't be parsed. 

72 """ 

73 public_key_data = _helpers.to_bytes(public_key) 

74 

75 if _CERTIFICATE_MARKER in public_key_data: 

76 cert = cryptography.x509.load_pem_x509_certificate( 

77 public_key_data, _BACKEND 

78 ) 

79 pubkey = cert.public_key() 

80 

81 else: 

82 pubkey = serialization.load_pem_public_key(public_key_data, _BACKEND) 

83 

84 return cls(pubkey) 

85 

86 

87class RSASigner(base.Signer, base.FromServiceAccountMixin): 

88 """Signs messages with an RSA private key. 

89 

90 Args: 

91 private_key ( 

92 cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey): 

93 The private key to sign with. 

94 key_id (str): Optional key ID used to identify this private key. This 

95 can be useful to associate the private key with its associated 

96 public key or certificate. 

97 """ 

98 

99 def __init__(self, private_key, key_id=None): 

100 self._key = private_key 

101 self._key_id = key_id 

102 

103 @property # type: ignore 

104 @_helpers.copy_docstring(base.Signer) 

105 def key_id(self): 

106 return self._key_id 

107 

108 @_helpers.copy_docstring(base.Signer) 

109 def sign(self, message): 

110 message = _helpers.to_bytes(message) 

111 return self._key.sign(message, _PADDING, _SHA256) 

112 

113 @classmethod 

114 def from_string(cls, key, key_id=None): 

115 """Construct a RSASigner from a private key in PEM format. 

116 

117 Args: 

118 key (Union[bytes, str]): Private key in PEM format. 

119 key_id (str): An optional key id used to identify the private key. 

120 

121 Returns: 

122 google.auth.crypt._cryptography_rsa.RSASigner: The 

123 constructed signer. 

124 

125 Raises: 

126 ValueError: If ``key`` is not ``bytes`` or ``str`` (unicode). 

127 UnicodeDecodeError: If ``key`` is ``bytes`` but cannot be decoded 

128 into a UTF-8 ``str``. 

129 ValueError: If ``cryptography`` "Could not deserialize key data." 

130 """ 

131 key = _helpers.to_bytes(key) 

132 private_key = serialization.load_pem_private_key( 

133 key, password=None, backend=_BACKEND 

134 ) 

135 return cls(private_key, key_id=key_id) 

136 

137 def __getstate__(self): 

138 """Pickle helper that serializes the _key attribute.""" 

139 state = self.__dict__.copy() 

140 state["_key"] = self._key.private_bytes( 

141 encoding=serialization.Encoding.PEM, 

142 format=serialization.PrivateFormat.PKCS8, 

143 encryption_algorithm=serialization.NoEncryption(), 

144 ) 

145 return state 

146 

147 def __setstate__(self, state): 

148 """Pickle helper that deserializes the _key attribute.""" 

149 state["_key"] = serialization.load_pem_private_key(state["_key"], None) 

150 self.__dict__.update(state)