-
Notifications
You must be signed in to change notification settings - Fork 348
[DRAFT] fix: remove dependency on rsa #1928
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
f357187
575113c
bef613a
15e6e7b
7715f92
ddacaf2
5573db6
07a4f22
6890572
c2ceeb4
d1b3fb6
ad651ed
540f260
a4830fa
68410f1
f89e444
fd429f3
fd1ae50
0895998
69bae96
a803198
716bec3
6191d3b
b7c270b
a1e0389
6b17faa
e88fc1c
d7a3b23
d0f1747
db7037c
556aa32
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -12,19 +12,152 @@ | |
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
|
|
||
| """RSA cryptography signer and verifier.""" | ||
| """ | ||
| RSA cryptography signer and verifier. | ||
|
|
||
| This file provides a shared wrapper, that defers to _python_rsa or _cryptography_rsa | ||
| for implmentations using different third party libraries | ||
| """ | ||
|
|
||
| from google.auth import _helpers | ||
| from google.auth.crypt import base | ||
| from google.auth.exceptions import MissingOptionalDependencyError | ||
|
|
||
| try: | ||
| # Prefer cryptograph-based RSA implementation. | ||
| # Attempt import of module that requires optional `cryptography` dependency | ||
| from google.auth.crypt import _cryptography_rsa | ||
|
|
||
| RSASigner = _cryptography_rsa.RSASigner | ||
| RSAVerifier = _cryptography_rsa.RSAVerifier | ||
| except ImportError: # pragma: NO COVER | ||
| # Fallback to pure-python RSA implementation if cryptography is | ||
| # unavailable. | ||
| _cryptography_rsa = None | ||
|
|
||
| try: | ||
| # Attempt import of module that requires optional (deprecated) `rsa` dependency | ||
| from google.auth.crypt import _python_rsa | ||
| except ImportError: # pragma: NO COVER | ||
| _python_rsa = None | ||
|
|
||
| RSA_NOTE = "(Note: `rsa` is also supported for legacy compatibility, but is deprecated)" | ||
|
|
||
|
|
||
| class RSAVerifier(base.Verifier): | ||
| """Verifies RSA cryptographic signatures using public keys. | ||
|
|
||
| Requires installation of `cryptography` optional dependency. | ||
|
|
||
| .. deprecated:: | ||
| The `rsa` library has been archived. Please migrate to | ||
| `cryptography` for public keys. | ||
|
|
||
| Args: | ||
| public_key (Union[rsa.key.PublicKey, cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey]): | ||
| The public key used to verify signatures. | ||
| Raises: | ||
| ImportError: if neither `cryptograhy` or `rsa` is installed | ||
| ValueError: if an unrecognized public key is provided | ||
| """ | ||
|
|
||
| def __init__(self, public_key): | ||
| module_str = public_key.__class__.__module__ | ||
| if "rsa.key" in module_str: | ||
| impl_lib = _python_rsa | ||
| elif "cryptography." in module_str: | ||
| impl_lib = _cryptography_rsa | ||
| else: | ||
| raise ValueError(f"unrecognized public key type: {public_key}") | ||
| if impl_lib is None: | ||
| raise MissingOptionalDependencyError.create(self, "cryptography", RSA_NOTE) | ||
| else: | ||
| self._impl = impl_lib.RSAVerifier(public_key) | ||
|
|
||
| @_helpers.copy_docstring(base.Verifier) | ||
| def verify(self, message, signature): | ||
| return self._impl.verify(message, signature) | ||
|
|
||
| @classmethod | ||
| def from_string(cls, public_key): | ||
| """Construct an Verifier instance from a public key or public | ||
| certificate string. | ||
|
|
||
| Args: | ||
| public_key (Union[str, bytes]): The public key in PEM format or the | ||
| x509 public key certificate. | ||
|
|
||
| Returns: | ||
| google.auth.crypt.RSAVerifier: The constructed verifier. | ||
|
|
||
| Raises: | ||
| ValueError: If the public_key can't be parsed. | ||
| ImportError: if neither `cryptograhy` or `rsa` is installe | ||
| """ | ||
| if _cryptography_rsa: | ||
| return _cryptography_rsa.RSAVerifier.from_string(public_key) | ||
| elif _python_rsa: | ||
| return _python_rsa.RSAVerifier.from_string(public_key) | ||
| else: | ||
| raise MissingOptionalDependencyError.create(cls, "cryptography", RSA_NOTE) | ||
|
Comment on lines
+76
to
+96
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The The method should create an instance of the wrapper class and set its internal Additionally, there are a few typos in the docstring ( def from_string(cls, public_key):
"""Construct a Verifier instance from a public key or public
certificate string.
Args:
public_key (Union[str, bytes]): The public key in PEM format or the
x509 public key certificate.
Returns:
google.auth.crypt.RSAVerifier: The constructed verifier.
Raises:
ValueError: If the public_key can't be parsed.
ImportError: if neither `cryptography` or `rsa` is installed
"""
if _cryptography_rsa:
impl = _cryptography_rsa.RSAVerifier.from_string(public_key)
verifier = cls.__new__(cls)
verifier._impl = impl
return verifier
elif _python_rsa:
impl = _python_rsa.RSAVerifier.from_string(public_key)
verifier = cls.__new__(cls)
verifier._impl = impl
return verifier
else:
raise MissingOptionalDependencyError.create(cls, "cryptography", RSA_NOTE) |
||
|
|
||
|
|
||
| class RSASigner(base.Signer, base.FromServiceAccountMixin): | ||
| """Signs messages with an RSA private key. | ||
|
|
||
| Requires installation of `cryptography` optional dependency. | ||
|
|
||
| .. deprecated:: | ||
| The `rsa` library has been archived. Please migrate to | ||
| `cryptography` for public keys. | ||
|
|
||
| Args: | ||
| private_key (Union[rsa.key.PrivateKey, cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey]): | ||
| The private key to sign with. | ||
| key_id (str): Optional key ID used to identify this private key. This | ||
| can be useful to associate the private key with its associated | ||
| public key or certificate. | ||
|
|
||
| Raises: | ||
| ImportError: if neither `cryptograhy` or `rsa` is installed | ||
| ValueError: if an unrecognized public key is provided | ||
|
Comment on lines
+115
to
+117
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| """ | ||
|
|
||
| def __init__(self, private_key, key_id=None): | ||
| module_str = private_key.__class__.__module__ | ||
| if "rsa.key" in module_str: | ||
| impl_lib = _python_rsa | ||
| elif "cryptography." in module_str: | ||
| impl_lib = _cryptography_rsa | ||
| else: | ||
| raise ValueError(f"unrecognized private key type: {private_key}") | ||
| if impl_lib is None: | ||
| raise MissingOptionalDependencyError.create(self, "cryptography", RSA_NOTE) | ||
| else: | ||
| self._impl = impl_lib.RSASigner(private_key, key_id=key_id) | ||
|
|
||
| @property # type: ignore | ||
| @_helpers.copy_docstring(base.Signer) | ||
| def key_id(self): | ||
| return self._impl.key_id | ||
|
|
||
| @_helpers.copy_docstring(base.Signer) | ||
| def sign(self, message): | ||
| return self._impl.sign(message) | ||
|
|
||
| @classmethod | ||
| def from_string(cls, key, key_id=None): | ||
| """Construct an Signer instance from a private key in PEM format. | ||
|
|
||
| Args: | ||
| key (str): Private key in PEM format. | ||
| key_id (str): An optional key id used to identify the private key. | ||
|
|
||
| Returns: | ||
| google.auth.crypt.Signer: The constructed signer. | ||
|
|
||
| RSASigner = _python_rsa.RSASigner # type: ignore | ||
| RSAVerifier = _python_rsa.RSAVerifier # type: ignore | ||
| Raises: | ||
| ValueError: If the key cannot be parsed as PKCS#1 or PKCS#8 in | ||
| PEM format. | ||
| ImportError: if neither `cryptograhy` or `rsa` is installe | ||
| """ | ||
| if _cryptography_rsa: | ||
| return _cryptography_rsa.RSASigner.from_string(key, key_id=key_id) | ||
| elif _python_rsa: | ||
| return _python_rsa.RSASigner.from_string(key, key_id=key_id) | ||
| else: | ||
| raise MissingOptionalDependencyError.create(cls, "cryptography", RSA_NOTE) | ||
|
Comment on lines
+143
to
+163
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Similar to Also, there are typos in the docstring ( def from_string(cls, key, key_id=None):
"""Construct an Signer instance from a private key in PEM format.
Args:
key (str): Private key in PEM format.
key_id (str): An optional key id used to identify the private key.
Returns:
google.auth.crypt.Signer: The constructed signer.
Raises:
ValueError: If the key cannot be parsed as PKCS#1 or PKCS#8 in
PEM format.
ImportError: if neither `cryptography` or `rsa` is installed
"""
if _cryptography_rsa:
impl = _cryptography_rsa.RSASigner.from_string(key, key_id=key_id)
signer = cls.__new__(cls)
signer._impl = impl
return signer
elif _python_rsa:
impl = _python_rsa.RSASigner.from_string(key, key_id=key_id)
signer = cls.__new__(cls)
signer._impl = impl
return signer
else:
raise MissingOptionalDependencyError.create(cls, "cryptography", RSA_NOTE) |
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a typo in the
Raisessection of the docstring.cryptograhyshould becryptography.