Update dashboard, memory, root +2 more (+3 ~5)

This commit is contained in:
Echo
2026-02-02 16:21:41 +00:00
parent 2e8d47353b
commit 84701a062e
2212 changed files with 2938184 additions and 37 deletions

View File

@@ -0,0 +1,96 @@
# Copyright 2016 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Cryptography helpers for verifying and signing messages.
The simplest way to verify signatures is using :func:`verify_signature`::
cert = open('certs.pem').read()
valid = crypt.verify_signature(message, signature, cert)
If you're going to verify many messages with the same certificate, you can use
:class:`RSAVerifier`::
cert = open('certs.pem').read()
verifier = crypt.RSAVerifier.from_string(cert)
valid = verifier.verify(message, signature)
To sign messages use :class:`RSASigner` with a private key::
private_key = open('private_key.pem').read()
signer = crypt.RSASigner.from_string(private_key)
signature = signer.sign(message)
The code above also works for :class:`ES256Signer` and :class:`ES256Verifier`.
Note that these two classes are only available if your `cryptography` dependency
version is at least 1.4.0.
"""
from google.auth.crypt import base
from google.auth.crypt import es
from google.auth.crypt import es256
from google.auth.crypt import rsa
EsSigner = es.EsSigner
EsVerifier = es.EsVerifier
ES256Signer = es256.ES256Signer
ES256Verifier = es256.ES256Verifier
# Aliases to maintain the v1.0.0 interface, as the crypt module was split
# into submodules.
Signer = base.Signer
Verifier = base.Verifier
RSASigner = rsa.RSASigner
RSAVerifier = rsa.RSAVerifier
def verify_signature(message, signature, certs, verifier_cls=rsa.RSAVerifier):
"""Verify an RSA or ECDSA cryptographic signature.
Checks that the provided ``signature`` was generated from ``bytes`` using
the private key associated with the ``cert``.
Args:
message (Union[str, bytes]): The plaintext message.
signature (Union[str, bytes]): The cryptographic signature to check.
certs (Union[Sequence, str, bytes]): The certificate or certificates
to use to check the signature.
verifier_cls (Optional[~google.auth.crypt.base.Signer]): Which verifier
class to use for verification. This can be used to select different
algorithms, such as RSA or ECDSA. Default value is :class:`RSAVerifier`.
Returns:
bool: True if the signature is valid, otherwise False.
"""
if isinstance(certs, (str, bytes)):
certs = [certs]
for cert in certs:
verifier = verifier_cls.from_string(cert)
if verifier.verify(message, signature):
return True
return False
__all__ = [
"EsSigner",
"EsVerifier",
"ES256Signer",
"ES256Verifier",
"RSASigner",
"RSAVerifier",
"Signer",
"Verifier",
]

View File

@@ -0,0 +1,151 @@
# Copyright 2017 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""RSA verifier and signer that use the ``cryptography`` library.
This is a much faster implementation than the default (in
``google.auth.crypt._python_rsa``), which depends on the pure-Python
``rsa`` library.
"""
import cryptography.exceptions
from cryptography.hazmat import backends
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import padding
import cryptography.x509
from google.auth import _helpers
from google.auth.crypt import base
_CERTIFICATE_MARKER = b"-----BEGIN CERTIFICATE-----"
_BACKEND = backends.default_backend()
_PADDING = padding.PKCS1v15()
_SHA256 = hashes.SHA256()
class RSAVerifier(base.Verifier):
"""Verifies RSA cryptographic signatures using public keys.
Args:
public_key (
cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey):
The public key used to verify signatures.
"""
def __init__(self, public_key):
self._pubkey = public_key
@_helpers.copy_docstring(base.Verifier)
def verify(self, message, signature):
message = _helpers.to_bytes(message)
try:
self._pubkey.verify(signature, message, _PADDING, _SHA256)
return True
except (ValueError, cryptography.exceptions.InvalidSignature):
return False
@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:
Verifier: The constructed verifier.
Raises:
ValueError: If the public key can't be parsed.
"""
public_key_data = _helpers.to_bytes(public_key)
if _CERTIFICATE_MARKER in public_key_data:
cert = cryptography.x509.load_pem_x509_certificate(
public_key_data, _BACKEND
)
pubkey = cert.public_key()
else:
pubkey = serialization.load_pem_public_key(public_key_data, _BACKEND)
return cls(pubkey)
class RSASigner(base.Signer, base.FromServiceAccountMixin):
"""Signs messages with an RSA private key.
Args:
private_key (
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.
"""
def __init__(self, private_key, key_id=None):
self._key = private_key
self._key_id = key_id
@property # type: ignore
@_helpers.copy_docstring(base.Signer)
def key_id(self):
return self._key_id
@_helpers.copy_docstring(base.Signer)
def sign(self, message):
message = _helpers.to_bytes(message)
return self._key.sign(message, _PADDING, _SHA256)
@classmethod
def from_string(cls, key, key_id=None):
"""Construct a RSASigner from a private key in PEM format.
Args:
key (Union[bytes, str]): Private key in PEM format.
key_id (str): An optional key id used to identify the private key.
Returns:
google.auth.crypt._cryptography_rsa.RSASigner: The
constructed signer.
Raises:
ValueError: If ``key`` is not ``bytes`` or ``str`` (unicode).
UnicodeDecodeError: If ``key`` is ``bytes`` but cannot be decoded
into a UTF-8 ``str``.
ValueError: If ``cryptography`` "Could not deserialize key data."
"""
key = _helpers.to_bytes(key)
private_key = serialization.load_pem_private_key(
key, password=None, backend=_BACKEND
)
return cls(private_key, key_id=key_id)
def __getstate__(self):
"""Pickle helper that serializes the _key attribute."""
state = self.__dict__.copy()
state["_key"] = self._key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.PKCS8,
encryption_algorithm=serialization.NoEncryption(),
)
return state
def __setstate__(self, state):
"""Pickle helper that deserializes the _key attribute."""
state["_key"] = serialization.load_pem_private_key(state["_key"], None)
self.__dict__.update(state)

View File

@@ -0,0 +1,199 @@
# Copyright 2016 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Pure-Python RSA cryptography implementation.
Uses the ``rsa``, ``pyasn1`` and ``pyasn1_modules`` packages
to parse PEM files storing PKCS#1 or PKCS#8 keys as well as
certificates. There is no support for p12 files.
"""
from __future__ import absolute_import
import io
import warnings
from pyasn1.codec.der import decoder # type: ignore
from pyasn1_modules import pem # type: ignore
from pyasn1_modules.rfc2459 import Certificate # type: ignore
from pyasn1_modules.rfc5208 import PrivateKeyInfo # type: ignore
import rsa # type: ignore
from google.auth import _helpers
from google.auth import exceptions
from google.auth.crypt import base
_POW2 = (128, 64, 32, 16, 8, 4, 2, 1)
_CERTIFICATE_MARKER = b"-----BEGIN CERTIFICATE-----"
_PKCS1_MARKER = ("-----BEGIN RSA PRIVATE KEY-----", "-----END RSA PRIVATE KEY-----")
_PKCS8_MARKER = ("-----BEGIN PRIVATE KEY-----", "-----END PRIVATE KEY-----")
_PKCS8_SPEC = PrivateKeyInfo()
_warning_msg = (
"The 'rsa' library is deprecated and will be removed in a future release. "
"Please migrate to 'cryptography'."
)
def _bit_list_to_bytes(bit_list):
"""Converts an iterable of 1s and 0s to bytes.
Combines the list 8 at a time, treating each group of 8 bits
as a single byte.
Args:
bit_list (Sequence): Sequence of 1s and 0s.
Returns:
bytes: The decoded bytes.
"""
num_bits = len(bit_list)
byte_vals = bytearray()
for start in range(0, num_bits, 8):
curr_bits = bit_list[start : start + 8]
char_val = sum(val * digit for val, digit in zip(_POW2, curr_bits))
byte_vals.append(char_val)
return bytes(byte_vals)
class RSAVerifier(base.Verifier):
"""Verifies RSA cryptographic signatures using public keys.
.. deprecated::
The `rsa` library has been archived. Please migrate to
`cryptography`.
Args:
public_key (rsa.key.PublicKey): The public key used to verify
signatures.
"""
def __init__(self, public_key):
warnings.warn(
_warning_msg,
category=DeprecationWarning,
stacklevel=2,
)
self._pubkey = public_key
@_helpers.copy_docstring(base.Verifier)
def verify(self, message, signature):
message = _helpers.to_bytes(message)
try:
return rsa.pkcs1.verify(message, signature, self._pubkey)
except (ValueError, rsa.pkcs1.VerificationError):
return False
@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._python_rsa.RSAVerifier: The constructed verifier.
Raises:
ValueError: If the public_key can't be parsed.
"""
public_key = _helpers.to_bytes(public_key)
is_x509_cert = _CERTIFICATE_MARKER in public_key
# If this is a certificate, extract the public key info.
if is_x509_cert:
der = rsa.pem.load_pem(public_key, "CERTIFICATE")
asn1_cert, remaining = decoder.decode(der, asn1Spec=Certificate())
if remaining != b"":
raise exceptions.InvalidValue("Unused bytes", remaining)
cert_info = asn1_cert["tbsCertificate"]["subjectPublicKeyInfo"]
key_bytes = _bit_list_to_bytes(cert_info["subjectPublicKey"])
pubkey = rsa.PublicKey.load_pkcs1(key_bytes, "DER")
else:
pubkey = rsa.PublicKey.load_pkcs1(public_key, "PEM")
return cls(pubkey)
class RSASigner(base.Signer, base.FromServiceAccountMixin):
"""Signs messages with an RSA private key.
.. deprecated::
The `rsa` library has been archived. Please migrate to
`cryptography`.
Args:
private_key (rsa.key.PrivateKey): 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.
"""
def __init__(self, private_key, key_id=None):
warnings.warn(
_warning_msg,
category=DeprecationWarning,
stacklevel=2,
)
self._key = private_key
self._key_id = key_id
@property # type: ignore
@_helpers.copy_docstring(base.Signer)
def key_id(self):
return self._key_id
@_helpers.copy_docstring(base.Signer)
def sign(self, message):
message = _helpers.to_bytes(message)
return rsa.pkcs1.sign(message, self._key, "SHA-256")
@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.
Raises:
ValueError: If the key cannot be parsed as PKCS#1 or PKCS#8 in
PEM format.
"""
key = _helpers.from_bytes(key) # PEM expects str in Python 3
marker_id, key_bytes = pem.readPemBlocksFromFile(
io.StringIO(key), _PKCS1_MARKER, _PKCS8_MARKER
)
# Key is in pkcs1 format.
if marker_id == 0:
private_key = rsa.key.PrivateKey.load_pkcs1(key_bytes, format="DER")
# Key is in pkcs8.
elif marker_id == 1:
key_info, remaining = decoder.decode(key_bytes, asn1Spec=_PKCS8_SPEC)
if remaining != b"":
raise exceptions.InvalidValue("Unused bytes", remaining)
private_key_info = key_info.getComponentByName("privateKey")
private_key = rsa.key.PrivateKey.load_pkcs1(
private_key_info.asOctets(), format="DER"
)
else:
raise exceptions.MalformedError("No key could be detected.")
return cls(private_key, key_id=key_id)

View File

@@ -0,0 +1,127 @@
# Copyright 2016 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Base classes for cryptographic signers and verifiers."""
import abc
import io
import json
from google.auth import exceptions
_JSON_FILE_PRIVATE_KEY = "private_key"
_JSON_FILE_PRIVATE_KEY_ID = "private_key_id"
class Verifier(metaclass=abc.ABCMeta):
"""Abstract base class for crytographic signature verifiers."""
@abc.abstractmethod
def verify(self, message, signature):
"""Verifies a message against a cryptographic signature.
Args:
message (Union[str, bytes]): The message to verify.
signature (Union[str, bytes]): The cryptography signature to check.
Returns:
bool: True if message was signed by the private key associated
with the public key that this object was constructed with.
"""
# pylint: disable=missing-raises-doc,redundant-returns-doc
# (pylint doesn't recognize that this is abstract)
raise NotImplementedError("Verify must be implemented")
class Signer(metaclass=abc.ABCMeta):
"""Abstract base class for cryptographic signers."""
@abc.abstractproperty
def key_id(self):
"""Optional[str]: The key ID used to identify this private key."""
raise NotImplementedError("Key id must be implemented")
@abc.abstractmethod
def sign(self, message):
"""Signs a message.
Args:
message (Union[str, bytes]): The message to be signed.
Returns:
bytes: The signature of the message.
"""
# pylint: disable=missing-raises-doc,redundant-returns-doc
# (pylint doesn't recognize that this is abstract)
raise NotImplementedError("Sign must be implemented")
class FromServiceAccountMixin(metaclass=abc.ABCMeta):
"""Mix-in to enable factory constructors for a Signer."""
@abc.abstractmethod
def from_string(cls, key, key_id=None):
"""Construct an Signer instance from a private key string.
Args:
key (str): Private key as a string.
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.
"""
raise NotImplementedError("from_string must be implemented")
@classmethod
def from_service_account_info(cls, info):
"""Creates a Signer instance instance from a dictionary containing
service account info in Google format.
Args:
info (Mapping[str, str]): The service account info in Google
format.
Returns:
google.auth.crypt.Signer: The constructed signer.
Raises:
ValueError: If the info is not in the expected format.
"""
if _JSON_FILE_PRIVATE_KEY not in info:
raise exceptions.MalformedError(
"The private_key field was not found in the service account " "info."
)
return cls.from_string(
info[_JSON_FILE_PRIVATE_KEY], info.get(_JSON_FILE_PRIVATE_KEY_ID)
)
@classmethod
def from_service_account_file(cls, filename):
"""Creates a Signer instance from a service account .json file
in Google format.
Args:
filename (str): The path to the service account .json file.
Returns:
google.auth.crypt.Signer: The constructed signer.
"""
with io.open(filename, "r", encoding="utf-8") as json_file:
data = json.load(json_file)
return cls.from_service_account_info(data)

View File

@@ -0,0 +1,221 @@
# Copyright 2017 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""ECDSA verifier and signer that use the ``cryptography`` library.
"""
from dataclasses import dataclass
from typing import Any, Dict, Optional, Union
import cryptography.exceptions
from cryptography.hazmat import backends
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives.asymmetric.utils import decode_dss_signature
from cryptography.hazmat.primitives.asymmetric.utils import encode_dss_signature
import cryptography.x509
from google.auth import _helpers
from google.auth.crypt import base
_CERTIFICATE_MARKER = b"-----BEGIN CERTIFICATE-----"
_BACKEND = backends.default_backend()
_PADDING = padding.PKCS1v15()
@dataclass
class _ESAttributes:
"""A class that models ECDSA attributes.
Attributes:
rs_size (int): Size for ASN.1 r and s size.
sha_algo (hashes.HashAlgorithm): Hash algorithm.
algorithm (str): Algorithm name.
"""
rs_size: int
sha_algo: hashes.HashAlgorithm
algorithm: str
@classmethod
def from_key(
cls, key: Union[ec.EllipticCurvePublicKey, ec.EllipticCurvePrivateKey]
):
return cls.from_curve(key.curve)
@classmethod
def from_curve(cls, curve: ec.EllipticCurve):
# ECDSA raw signature has (r||s) format where r,s are two
# integers of size 32 bytes for P-256 curve and 48 bytes
# for P-384 curve. For P-256 curve, we use SHA256 hash algo,
# and for P-384 curve we use SHA384 algo.
if isinstance(curve, ec.SECP384R1):
return cls(48, hashes.SHA384(), "ES384")
else:
# default to ES256
return cls(32, hashes.SHA256(), "ES256")
class EsVerifier(base.Verifier):
"""Verifies ECDSA cryptographic signatures using public keys.
Args:
public_key (
cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey):
The public key used to verify signatures.
"""
def __init__(self, public_key: ec.EllipticCurvePublicKey) -> None:
self._pubkey = public_key
self._attributes = _ESAttributes.from_key(public_key)
@_helpers.copy_docstring(base.Verifier)
def verify(self, message: bytes, signature: bytes) -> bool:
# First convert (r||s) raw signature to ASN1 encoded signature.
sig_bytes = _helpers.to_bytes(signature)
if len(sig_bytes) != self._attributes.rs_size * 2:
return False
r = int.from_bytes(sig_bytes[: self._attributes.rs_size], byteorder="big")
s = int.from_bytes(sig_bytes[self._attributes.rs_size :], byteorder="big")
asn1_sig = encode_dss_signature(r, s)
message = _helpers.to_bytes(message)
try:
self._pubkey.verify(asn1_sig, message, ec.ECDSA(self._attributes.sha_algo))
return True
except (ValueError, cryptography.exceptions.InvalidSignature):
return False
@classmethod
def from_string(cls, public_key: Union[str, bytes]) -> "EsVerifier":
"""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.Verifier: The constructed verifier.
Raises:
ValueError: If the public key can't be parsed.
"""
public_key_data = _helpers.to_bytes(public_key)
if _CERTIFICATE_MARKER in public_key_data:
cert = cryptography.x509.load_pem_x509_certificate(
public_key_data, _BACKEND
)
pubkey = cert.public_key() # type: Any
else:
pubkey = serialization.load_pem_public_key(public_key_data, _BACKEND)
if not isinstance(pubkey, ec.EllipticCurvePublicKey):
raise TypeError("Expected public key of type EllipticCurvePublicKey")
return cls(pubkey)
class EsSigner(base.Signer, base.FromServiceAccountMixin):
"""Signs messages with an ECDSA private key.
Args:
private_key (
cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKey):
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.
"""
def __init__(
self, private_key: ec.EllipticCurvePrivateKey, key_id: Optional[str] = None
) -> None:
self._key = private_key
self._key_id = key_id
self._attributes = _ESAttributes.from_key(private_key)
@property
def algorithm(self) -> str:
"""Name of the algorithm used to sign messages.
Returns:
str: The algorithm name.
"""
return self._attributes.algorithm
@property # type: ignore
@_helpers.copy_docstring(base.Signer)
def key_id(self) -> Optional[str]:
return self._key_id
@_helpers.copy_docstring(base.Signer)
def sign(self, message: bytes) -> bytes:
message = _helpers.to_bytes(message)
asn1_signature = self._key.sign(message, ec.ECDSA(self._attributes.sha_algo))
# Convert ASN1 encoded signature to (r||s) raw signature.
(r, s) = decode_dss_signature(asn1_signature)
return r.to_bytes(self._attributes.rs_size, byteorder="big") + s.to_bytes(
self._attributes.rs_size, byteorder="big"
)
@classmethod
def from_string(
cls, key: Union[bytes, str], key_id: Optional[str] = None
) -> "EsSigner":
"""Construct a RSASigner from a private key in PEM format.
Args:
key (Union[bytes, str]): Private key in PEM format.
key_id (str): An optional key id used to identify the private key.
Returns:
google.auth.crypt._cryptography_rsa.RSASigner: The
constructed signer.
Raises:
ValueError: If ``key`` is not ``bytes`` or ``str`` (unicode).
UnicodeDecodeError: If ``key`` is ``bytes`` but cannot be decoded
into a UTF-8 ``str``.
ValueError: If ``cryptography`` "Could not deserialize key data."
"""
key_bytes = _helpers.to_bytes(key)
private_key = serialization.load_pem_private_key(
key_bytes, password=None, backend=_BACKEND
)
if not isinstance(private_key, ec.EllipticCurvePrivateKey):
raise TypeError("Expected private key of type EllipticCurvePrivateKey")
return cls(private_key, key_id=key_id)
def __getstate__(self) -> Dict[str, Any]:
"""Pickle helper that serializes the _key attribute."""
state = self.__dict__.copy()
state["_key"] = self._key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.PKCS8,
encryption_algorithm=serialization.NoEncryption(),
)
return state
def __setstate__(self, state: Dict[str, Any]) -> None:
"""Pickle helper that deserializes the _key attribute."""
state["_key"] = serialization.load_pem_private_key(state["_key"], None)
self.__dict__.update(state)

View File

@@ -0,0 +1,45 @@
# Copyright 2017 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""ECDSA (ES256) verifier and signer that use the ``cryptography`` library.
"""
from google.auth.crypt.es import EsSigner
from google.auth.crypt.es import EsVerifier
class ES256Verifier(EsVerifier):
"""Verifies ECDSA cryptographic signatures using public keys.
Args:
public_key (cryptography.hazmat.primitives.asymmetric.ec.ECDSAPublicKey): The public key used to verify
signatures.
"""
pass
class ES256Signer(EsSigner):
"""Signs messages with an ECDSA private key.
Args:
private_key (
cryptography.hazmat.primitives.asymmetric.ec.ECDSAPrivateKey):
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.
"""
pass

View File

@@ -0,0 +1,127 @@
# Copyright 2017 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
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 cryptography.hazmat.primitives.asymmetric.rsa import RSAPrivateKey
from cryptography.hazmat.primitives.asymmetric.rsa import RSAPublicKey
from google.auth import _helpers
from google.auth.crypt import _cryptography_rsa
from google.auth.crypt import _python_rsa
from google.auth.crypt import base
RSA_KEY_MODULE_PREFIX = "rsa.key"
class RSAVerifier(base.Verifier):
"""Verifies RSA cryptographic signatures using public keys.
Args:
public_key (Union["rsa.key.PublicKey", cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey]):
The public key used to verify signatures.
Raises:
ValueError: if an unrecognized public key is provided
"""
def __init__(self, public_key):
module_str = public_key.__class__.__module__
if isinstance(public_key, RSAPublicKey):
impl_lib = _cryptography_rsa
elif module_str.startswith(RSA_KEY_MODULE_PREFIX):
impl_lib = _python_rsa
else:
raise ValueError(f"unrecognized public key type: {type(public_key)}")
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 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.Verifier: The constructed verifier.
Raises:
ValueError: If the public_key can't be parsed.
"""
instance = cls.__new__(cls)
instance._impl = _cryptography_rsa.RSAVerifier.from_string(public_key)
return instance
class RSASigner(base.Signer, base.FromServiceAccountMixin):
"""Signs messages with an RSA private key.
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:
ValueError: if an unrecognized public key is provided
"""
def __init__(self, private_key, key_id=None):
module_str = private_key.__class__.__module__
if isinstance(private_key, RSAPrivateKey):
impl_lib = _cryptography_rsa
elif module_str.startswith(RSA_KEY_MODULE_PREFIX):
impl_lib = _python_rsa
else:
raise ValueError(f"unrecognized private key type: {type(private_key)}")
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 a 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.
"""
instance = cls.__new__(cls)
instance._impl = _cryptography_rsa.RSASigner.from_string(key, key_id=key_id)
return instance