| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 8dcf91a commit 52558ae
8 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -38,35 +38,14 @@ | |||
| 38 | 38 | """ | |
| 39 | 39 | ||
| 40 | 40 | from google.auth.crypt import base | |
| 41 | + from google.auth.crypt import es | ||
| 42 | + from google.auth.crypt import es256 | ||
| 41 | 43 | from google.auth.crypt import rsa | |
| 42 | 44 | ||
| 43 | - # google.auth.crypt.es depends on the crytpography module which may not be | ||
| 44 | - # successfully imported depending on the system. | ||
| 45 | - try: | ||
| 46 | - from google.auth.crypt import es | ||
| 47 | - from google.auth.crypt import es256 | ||
| 48 | - except ImportError: # pragma: NO COVER | ||
| 49 | - es = None # type: ignore | ||
| 50 | - es256 = None # type: ignore | ||
| 51 | - | ||
| 52 | - if es is not None and es256 is not None: # pragma: NO COVER | ||
| 53 | - __all__ = [ | ||
| 54 | - "EsSigner", | ||
| 55 | - "EsVerifier", | ||
| 56 | - "ES256Signer", | ||
| 57 | - "ES256Verifier", | ||
| 58 | - "RSASigner", | ||
| 59 | - "RSAVerifier", | ||
| 60 | - "Signer", | ||
| 61 | - "Verifier", | ||
| 62 | - ] | ||
| 63 | - | ||
| 64 | - EsSigner = es.EsSigner | ||
| 65 | - EsVerifier = es.EsVerifier | ||
| 66 | - ES256Signer = es256.ES256Signer | ||
| 67 | - ES256Verifier = es256.ES256Verifier | ||
| 68 | - else: # pragma: NO COVER | ||
| 69 | - __all__ = ["RSASigner", "RSAVerifier", "Signer", "Verifier"] | ||
| 45 | + EsSigner = es.EsSigner | ||
| 46 | + EsVerifier = es.EsVerifier | ||
| 47 | + ES256Signer = es256.ES256Signer | ||
| 48 | + ES256Verifier = es256.ES256Verifier | ||
| 70 | 49 | ||
| 71 | 50 | ||
| 72 | 51 | # Aliases to maintain the v1.0.0 interface, as the crypt module was split | |
@@ -103,3 +82,15 @@ class to use for verification. This can be used to select different | |||
| 103 | 82 | if verifier.verify(message, signature): | |
| 104 | 83 | return True | |
| 105 | 84 | return False | |
| 85 | + | ||
| 86 | + | ||
| 87 | + __all__ = [ | ||
| 88 | + "EsSigner", | ||
| 89 | + "EsVerifier", | ||
| 90 | + "ES256Signer", | ||
| 91 | + "ES256Verifier", | ||
| 92 | + "RSASigner", | ||
| 93 | + "RSAVerifier", | ||
| 94 | + "Signer", | ||
| 95 | + "Verifier", | ||
| 96 | + ] | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -40,13 +40,9 @@ | |||
| 40 | 40 | _PKCS8_MARKER = ("-----BEGIN PRIVATE KEY-----", "-----END PRIVATE KEY-----") | |
| 41 | 41 | _PKCS8_SPEC = PrivateKeyInfo() | |
| 42 | 42 | ||
| 43 | - warnings.warn( | ||
| 44 | - ( | ||
| 45 | - "The 'rsa' library is deprecated and will be removed in a future release. " | ||
| 46 | - "Please migrate to 'cryptography'." | ||
| 47 | - ), | ||
| 48 | - category=DeprecationWarning, | ||
| 49 | - stacklevel=2, | ||
| 43 | + _warning_msg = ( | ||
| 44 | + "The 'rsa' library is deprecated and will be removed in a future release. " | ||
| 45 | + "Please migrate to 'cryptography'." | ||
| 50 | 46 | ) | |
| 51 | 47 | ||
| 52 | 48 | ||
@@ -84,6 +80,11 @@ class RSAVerifier(base.Verifier): | |||
| 84 | 80 | """ | |
| 85 | 81 | ||
| 86 | 82 | def __init__(self, public_key): | |
| 83 | + warnings.warn( | ||
| 84 | + _warning_msg, | ||
| 85 | + category=DeprecationWarning, | ||
| 86 | + stacklevel=2, | ||
| 87 | + ) | ||
| 87 | 88 | self._pubkey = public_key | |
| 88 | 89 | ||
| 89 | 90 | @_helpers.copy_docstring(base.Verifier) | |
@@ -142,6 +143,11 @@ class RSASigner(base.Signer, base.FromServiceAccountMixin): | |||
| 142 | 143 | """ | |
| 143 | 144 | ||
| 144 | 145 | def __init__(self, private_key, key_id=None): | |
| 146 | + warnings.warn( | ||
| 147 | + _warning_msg, | ||
| 148 | + category=DeprecationWarning, | ||
| 149 | + stacklevel=2, | ||
| 150 | + ) | ||
| 145 | 151 | self._key = private_key | |
| 146 | 152 | self._key_id = key_id | |
| 147 | 153 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -102,15 +102,15 @@ def verify(self, message: bytes, signature: bytes) -> bool: | |||
| 102 | 102 | ||
| 103 | 103 | @classmethod | |
| 104 | 104 | def from_string(cls, public_key: Union[str, bytes]) -> "EsVerifier": | |
| 105 | - """Construct an Verifier instance from a public key or public | ||
| 105 | + """Construct a Verifier instance from a public key or public | ||
| 106 | 106 | certificate string. | |
| 107 | 107 | ||
| 108 | 108 | Args: | |
| 109 | 109 | public_key (Union[str, bytes]): The public key in PEM format or the | |
| 110 | 110 | x509 public key certificate. | |
| 111 | 111 | ||
| 112 | 112 | Returns: | |
| 113 | - Verifier: The constructed verifier. | ||
| 113 | + google.auth.crypt.Verifier: The constructed verifier. | ||
| 114 | 114 | ||
| 115 | 115 | Raises: | |
| 116 | 116 | ValueError: If the public key can't be parsed. | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -12,19 +12,116 @@ | |||
| 12 | 12 | # See the License for the specific language governing permissions and | |
| 13 | 13 | # limitations under the License. | |
| 14 | 14 | ||
| 15 | - """RSA cryptography signer and verifier.""" | ||
| 15 | + """ | ||
| 16 | + RSA cryptography signer and verifier. | ||
| 16 | 17 | ||
| 18 | + This file provides a shared wrapper, that defers to _python_rsa or _cryptography_rsa | ||
| 19 | + for implmentations using different third party libraries | ||
| 20 | + """ | ||
| 17 | 21 | ||
| 18 | - try: | ||
| 19 | - # Prefer cryptograph-based RSA implementation. | ||
| 20 | - from google.auth.crypt import _cryptography_rsa | ||
| 22 | + from cryptography.hazmat.primitives.asymmetric.rsa import RSAPrivateKey | ||
| 23 | + from cryptography.hazmat.primitives.asymmetric.rsa import RSAPublicKey | ||
| 21 | 24 | ||
| 22 | - RSASigner = _cryptography_rsa.RSASigner | ||
| 23 | - RSAVerifier = _cryptography_rsa.RSAVerifier | ||
| 24 | - except ImportError: # pragma: NO COVER | ||
| 25 | - # Fallback to pure-python RSA implementation if cryptography is | ||
| 26 | - # unavailable. | ||
| 27 | - from google.auth.crypt import _python_rsa | ||
| 25 | + from google.auth import _helpers | ||
| 26 | + from google.auth.crypt import _cryptography_rsa | ||
| 27 | + from google.auth.crypt import _python_rsa | ||
| 28 | + from google.auth.crypt import base | ||
| 28 | 29 | ||
| 29 | - RSASigner = _python_rsa.RSASigner # type: ignore | ||
| 30 | - RSAVerifier = _python_rsa.RSAVerifier # type: ignore | ||
| 30 | + RSA_KEY_MODULE_PREFIX = "rsa.key" | ||
| 31 | + | ||
| 32 | + | ||
| 33 | + class RSAVerifier(base.Verifier): | ||
| 34 | + """Verifies RSA cryptographic signatures using public keys. | ||
| 35 | + | ||
| 36 | + Args: | ||
| 37 | + public_key (Union["rsa.key.PublicKey", cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey]): | ||
| 38 | + The public key used to verify signatures. | ||
| 39 | + Raises: | ||
| 40 | + ValueError: if an unrecognized public key is provided | ||
| 41 | + """ | ||
| 42 | + | ||
| 43 | + def __init__(self, public_key): | ||
| 44 | + module_str = public_key.__class__.__module__ | ||
| 45 | + if isinstance(public_key, RSAPublicKey): | ||
| 46 | + impl_lib = _cryptography_rsa | ||
| 47 | + elif module_str.startswith(RSA_KEY_MODULE_PREFIX): | ||
| 48 | + impl_lib = _python_rsa | ||
| 49 | + else: | ||
| 50 | + raise ValueError(f"unrecognized public key type: {type(public_key)}") | ||
| 51 | + self._impl = impl_lib.RSAVerifier(public_key) | ||
| 52 | + | ||
| 53 | + @_helpers.copy_docstring(base.Verifier) | ||
| 54 | + def verify(self, message, signature): | ||
| 55 | + return self._impl.verify(message, signature) | ||
| 56 | + | ||
| 57 | + @classmethod | ||
| 58 | + def from_string(cls, public_key): | ||
| 59 | + """Construct a Verifier instance from a public key or public | ||
| 60 | + certificate string. | ||
| 61 | + | ||
| 62 | + Args: | ||
| 63 | + public_key (Union[str, bytes]): The public key in PEM format or the | ||
| 64 | + x509 public key certificate. | ||
| 65 | + | ||
| 66 | + Returns: | ||
| 67 | + google.auth.crypt.Verifier: The constructed verifier. | ||
| 68 | + | ||
| 69 | + Raises: | ||
| 70 | + ValueError: If the public_key can't be parsed. | ||
| 71 | + """ | ||
| 72 | + instance = cls.__new__(cls) | ||
| 73 | + instance._impl = _cryptography_rsa.RSAVerifier.from_string(public_key) | ||
| 74 | + return instance | ||
| 75 | + | ||
| 76 | + | ||
| 77 | + class RSASigner(base.Signer, base.FromServiceAccountMixin): | ||
| 78 | + """Signs messages with an RSA private key. | ||
| 79 | + | ||
| 80 | + Args: | ||
| 81 | + private_key (Union["rsa.key.PrivateKey", cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey]): | ||
| 82 | + The private key to sign with. | ||
| 83 | + key_id (str): Optional key ID used to identify this private key. This | ||
| 84 | + can be useful to associate the private key with its associated | ||
| 85 | + public key or certificate. | ||
| 86 | + | ||
| 87 | + Raises: | ||
| 88 | + ValueError: if an unrecognized public key is provided | ||
| 89 | + """ | ||
| 90 | + | ||
| 91 | + def __init__(self, private_key, key_id=None): | ||
| 92 | + module_str = private_key.__class__.__module__ | ||
| 93 | + if isinstance(private_key, RSAPrivateKey): | ||
| 94 | + impl_lib = _cryptography_rsa | ||
| 95 | + elif module_str.startswith(RSA_KEY_MODULE_PREFIX): | ||
| 96 | + impl_lib = _python_rsa | ||
| 97 | + else: | ||
| 98 | + raise ValueError(f"unrecognized private key type: {type(private_key)}") | ||
| 99 | + self._impl = impl_lib.RSASigner(private_key, key_id=key_id) | ||
| 100 | + | ||
| 101 | + @property # type: ignore | ||
| 102 | + @_helpers.copy_docstring(base.Signer) | ||
| 103 | + def key_id(self): | ||
| 104 | + return self._impl.key_id | ||
| 105 | + | ||
| 106 | + @_helpers.copy_docstring(base.Signer) | ||
| 107 | + def sign(self, message): | ||
| 108 | + return self._impl.sign(message) | ||
| 109 | + | ||
| 110 | + @classmethod | ||
| 111 | + def from_string(cls, key, key_id=None): | ||
| 112 | + """Construct a Signer instance from a private key in PEM format. | ||
| 113 | + | ||
| 114 | + Args: | ||
| 115 | + key (str): Private key in PEM format. | ||
| 116 | + key_id (str): An optional key id used to identify the private key. | ||
| 117 | + | ||
| 118 | + Returns: | ||
| 119 | + google.auth.crypt.Signer: The constructed signer. | ||
| 120 | + | ||
| 121 | + Raises: | ||
| 122 | + ValueError: If the key cannot be parsed as PKCS#1 or PKCS#8 in | ||
| 123 | + PEM format. | ||
| 124 | + """ | ||
| 125 | + instance = cls.__new__(cls) | ||
| 126 | + instance._impl = _cryptography_rsa.RSASigner.from_string(key, key_id=key_id) | ||
| 127 | + return instance | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -18,30 +18,30 @@ | |||
| 18 | 18 | from setuptools import find_namespace_packages | |
| 19 | 19 | from setuptools import setup | |
| 20 | 20 | ||
| 21 | + cryptography_base_require = [ | ||
| 22 | + "cryptography >= 38.0.3", | ||
| 23 | + ] | ||
| 21 | 24 | ||
| 22 | 25 | DEPENDENCIES = ( | |
| 23 | 26 | "pyasn1-modules>=0.2.1", | |
| 24 | - # rsa==4.5 is the last version to support 2.7 | ||
| 25 | - # https://github.com/sybrenstuvel/python-rsa/issues/152#issuecomment-643470233 | ||
| 27 | + cryptography_base_require, | ||
| 28 | + # TODO: remove rsa from dependencies in next release (replaced with cryptography)i | ||
| 29 | + # https://github.com/googleapis/google-auth-library-python/issues/1810 | ||
| 26 | 30 | "rsa>=3.1.4,<5", | |
| 27 | 31 | ) | |
| 28 | 32 | ||
| 29 | - cryptography_base_require = [ | ||
| 30 | - "cryptography >= 38.0.3", | ||
| 31 | - ] | ||
| 32 | - | ||
| 33 | 33 | requests_extra_require = ["requests >= 2.20.0, < 3.0.0"] | |
| 34 | 34 | ||
| 35 | 35 | aiohttp_extra_require = ["aiohttp >= 3.6.2, < 4.0.0", *requests_extra_require] | |
| 36 | 36 | ||
| 37 | - pyjwt_extra_require = ["pyjwt>=2.0", *cryptography_base_require] | ||
| 37 | + pyjwt_extra_require = ["pyjwt>=2.0"] | ||
| 38 | 38 | ||
| 39 | 39 | reauth_extra_require = ["pyu2f>=0.1.5"] | |
| 40 | 40 | ||
| 41 | - # TODO(https://github.com/googleapis/google-auth-library-python/issues/1738): Add bounds for cryptography and pyopenssl dependencies. | ||
| 42 | - enterprise_cert_extra_require = ["cryptography", "pyopenssl"] | ||
| 41 | + # TODO(https://github.com/googleapis/google-auth-library-python/issues/1738): Add bounds for pyopenssl dependency. | ||
| 42 | + enterprise_cert_extra_require = ["pyopenssl"] | ||
| 43 | 43 | ||
| 44 | - pyopenssl_extra_require = ["pyopenssl>=20.0.0", cryptography_base_require] | ||
| 44 | + pyopenssl_extra_require = ["pyopenssl>=20.0.0"] | ||
| 45 | 45 | ||
| 46 | 46 | # TODO(https://github.com/googleapis/google-auth-library-python/issues/1739): Add bounds for urllib3 and packaging dependencies. | |
| 47 | 47 | urllib3_extra_require = ["urllib3", "packaging"] | |
@@ -76,6 +76,7 @@ | |||
| 76 | 76 | ] | |
| 77 | 77 | ||
| 78 | 78 | extras = { | |
| 79 | + # Note: cryptography was made into a required dependency. Extra is kept for backwards compatibility | ||
| 79 | 80 | "cryptography": cryptography_base_require, | |
| 80 | 81 | "aiohttp": aiohttp_extra_require, | |
| 81 | 82 | "enterprise_cert": enterprise_cert_extra_require, | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -195,8 +195,9 @@ def test_from_service_account_file(self): | |||
| 195 | 195 | ||
| 196 | 196 | class TestModule(object): | |
| 197 | 197 | def test_import_warning(self): | |
| 198 | - import importlib | ||
| 199 | 198 | from google.auth.crypt import _python_rsa | |
| 200 | 199 | ||
| 201 | 200 | with pytest.warns(DeprecationWarning, match="The 'rsa' library is deprecated"): | |
| 202 | - importlib.reload(_python_rsa) | ||
| 201 | + _python_rsa.RSAVerifier(None) | ||
| 202 | + with pytest.warns(DeprecationWarning, match="The 'rsa' library is deprecated"): | ||
| 203 | + _python_rsa.RSASigner(None) | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments