updates
This commit is contained in:
@@ -8,10 +8,12 @@ import abc
|
||||
import datetime
|
||||
import os
|
||||
import typing
|
||||
import warnings
|
||||
from collections.abc import Iterable
|
||||
|
||||
from cryptography import utils
|
||||
from cryptography.hazmat.bindings._rust import x509 as rust_x509
|
||||
from cryptography.hazmat.primitives import hashes, serialization
|
||||
from cryptography.hazmat.primitives import hashes
|
||||
from cryptography.hazmat.primitives.asymmetric import (
|
||||
dsa,
|
||||
ec,
|
||||
@@ -24,7 +26,6 @@ from cryptography.hazmat.primitives.asymmetric import (
|
||||
)
|
||||
from cryptography.hazmat.primitives.asymmetric.types import (
|
||||
CertificateIssuerPrivateKeyTypes,
|
||||
CertificateIssuerPublicKeyTypes,
|
||||
CertificatePublicKeyTypes,
|
||||
)
|
||||
from cryptography.x509.extensions import (
|
||||
@@ -60,7 +61,7 @@ class AttributeNotFound(Exception):
|
||||
|
||||
def _reject_duplicate_extension(
|
||||
extension: Extension[ExtensionType],
|
||||
extensions: typing.List[Extension[ExtensionType]],
|
||||
extensions: list[Extension[ExtensionType]],
|
||||
) -> None:
|
||||
# This is quadratic in the number of extensions
|
||||
for e in extensions:
|
||||
@@ -70,9 +71,7 @@ def _reject_duplicate_extension(
|
||||
|
||||
def _reject_duplicate_attribute(
|
||||
oid: ObjectIdentifier,
|
||||
attributes: typing.List[
|
||||
typing.Tuple[ObjectIdentifier, bytes, typing.Optional[int]]
|
||||
],
|
||||
attributes: list[tuple[ObjectIdentifier, bytes, int | None]],
|
||||
) -> None:
|
||||
# This is quadratic in the number of attributes
|
||||
for attr_oid, _, _ in attributes:
|
||||
@@ -133,7 +132,7 @@ class Attribute:
|
||||
class Attributes:
|
||||
def __init__(
|
||||
self,
|
||||
attributes: typing.Iterable[Attribute],
|
||||
attributes: Iterable[Attribute],
|
||||
) -> None:
|
||||
self._attributes = list(attributes)
|
||||
|
||||
@@ -161,145 +160,7 @@ class InvalidVersion(Exception):
|
||||
self.parsed_version = parsed_version
|
||||
|
||||
|
||||
class Certificate(metaclass=abc.ABCMeta):
|
||||
@abc.abstractmethod
|
||||
def fingerprint(self, algorithm: hashes.HashAlgorithm) -> bytes:
|
||||
"""
|
||||
Returns bytes using digest passed.
|
||||
"""
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def serial_number(self) -> int:
|
||||
"""
|
||||
Returns certificate serial number
|
||||
"""
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def version(self) -> Version:
|
||||
"""
|
||||
Returns the certificate version
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def public_key(self) -> CertificatePublicKeyTypes:
|
||||
"""
|
||||
Returns the public key
|
||||
"""
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def not_valid_before(self) -> datetime.datetime:
|
||||
"""
|
||||
Not before time (represented as UTC datetime)
|
||||
"""
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def not_valid_after(self) -> datetime.datetime:
|
||||
"""
|
||||
Not after time (represented as UTC datetime)
|
||||
"""
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def issuer(self) -> Name:
|
||||
"""
|
||||
Returns the issuer name object.
|
||||
"""
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def subject(self) -> Name:
|
||||
"""
|
||||
Returns the subject name object.
|
||||
"""
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def signature_hash_algorithm(
|
||||
self,
|
||||
) -> typing.Optional[hashes.HashAlgorithm]:
|
||||
"""
|
||||
Returns a HashAlgorithm corresponding to the type of the digest signed
|
||||
in the certificate.
|
||||
"""
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def signature_algorithm_oid(self) -> ObjectIdentifier:
|
||||
"""
|
||||
Returns the ObjectIdentifier of the signature algorithm.
|
||||
"""
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def signature_algorithm_parameters(
|
||||
self,
|
||||
) -> typing.Union[None, padding.PSS, padding.PKCS1v15, ec.ECDSA]:
|
||||
"""
|
||||
Returns the signature algorithm parameters.
|
||||
"""
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def extensions(self) -> Extensions:
|
||||
"""
|
||||
Returns an Extensions object.
|
||||
"""
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def signature(self) -> bytes:
|
||||
"""
|
||||
Returns the signature bytes.
|
||||
"""
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def tbs_certificate_bytes(self) -> bytes:
|
||||
"""
|
||||
Returns the tbsCertificate payload bytes as defined in RFC 5280.
|
||||
"""
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def tbs_precertificate_bytes(self) -> bytes:
|
||||
"""
|
||||
Returns the tbsCertificate payload bytes with the SCT list extension
|
||||
stripped.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def __eq__(self, other: object) -> bool:
|
||||
"""
|
||||
Checks equality.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def __hash__(self) -> int:
|
||||
"""
|
||||
Computes a hash.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def public_bytes(self, encoding: serialization.Encoding) -> bytes:
|
||||
"""
|
||||
Serializes the certificate to PEM or DER format.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def verify_directly_issued_by(self, issuer: Certificate) -> None:
|
||||
"""
|
||||
This method verifies that certificate issuer name matches the
|
||||
issuer subject name and that the certificate is signed by the
|
||||
issuer's private key. No other validation is performed.
|
||||
"""
|
||||
|
||||
|
||||
# Runtime isinstance checks need this since the rust class is not a subclass.
|
||||
Certificate.register(rust_x509.Certificate)
|
||||
Certificate = rust_x509.Certificate
|
||||
|
||||
|
||||
class RevokedCertificate(metaclass=abc.ABCMeta):
|
||||
@@ -317,6 +178,14 @@ class RevokedCertificate(metaclass=abc.ABCMeta):
|
||||
Returns the date of when this certificate was revoked.
|
||||
"""
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def revocation_date_utc(self) -> datetime.datetime:
|
||||
"""
|
||||
Returns the date of when this certificate was revoked as a non-naive
|
||||
UTC datetime.
|
||||
"""
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def extensions(self) -> Extensions:
|
||||
@@ -346,290 +215,45 @@ class _RawRevokedCertificate(RevokedCertificate):
|
||||
|
||||
@property
|
||||
def revocation_date(self) -> datetime.datetime:
|
||||
warnings.warn(
|
||||
"Properties that return a naïve datetime object have been "
|
||||
"deprecated. Please switch to revocation_date_utc.",
|
||||
utils.DeprecatedIn42,
|
||||
stacklevel=2,
|
||||
)
|
||||
return self._revocation_date
|
||||
|
||||
@property
|
||||
def revocation_date_utc(self) -> datetime.datetime:
|
||||
return self._revocation_date.replace(tzinfo=datetime.timezone.utc)
|
||||
|
||||
@property
|
||||
def extensions(self) -> Extensions:
|
||||
return self._extensions
|
||||
|
||||
|
||||
class CertificateRevocationList(metaclass=abc.ABCMeta):
|
||||
@abc.abstractmethod
|
||||
def public_bytes(self, encoding: serialization.Encoding) -> bytes:
|
||||
"""
|
||||
Serializes the CRL to PEM or DER format.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def fingerprint(self, algorithm: hashes.HashAlgorithm) -> bytes:
|
||||
"""
|
||||
Returns bytes using digest passed.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_revoked_certificate_by_serial_number(
|
||||
self, serial_number: int
|
||||
) -> typing.Optional[RevokedCertificate]:
|
||||
"""
|
||||
Returns an instance of RevokedCertificate or None if the serial_number
|
||||
is not in the CRL.
|
||||
"""
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def signature_hash_algorithm(
|
||||
self,
|
||||
) -> typing.Optional[hashes.HashAlgorithm]:
|
||||
"""
|
||||
Returns a HashAlgorithm corresponding to the type of the digest signed
|
||||
in the certificate.
|
||||
"""
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def signature_algorithm_oid(self) -> ObjectIdentifier:
|
||||
"""
|
||||
Returns the ObjectIdentifier of the signature algorithm.
|
||||
"""
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def issuer(self) -> Name:
|
||||
"""
|
||||
Returns the X509Name with the issuer of this CRL.
|
||||
"""
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def next_update(self) -> typing.Optional[datetime.datetime]:
|
||||
"""
|
||||
Returns the date of next update for this CRL.
|
||||
"""
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def last_update(self) -> datetime.datetime:
|
||||
"""
|
||||
Returns the date of last update for this CRL.
|
||||
"""
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def extensions(self) -> Extensions:
|
||||
"""
|
||||
Returns an Extensions object containing a list of CRL extensions.
|
||||
"""
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def signature(self) -> bytes:
|
||||
"""
|
||||
Returns the signature bytes.
|
||||
"""
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def tbs_certlist_bytes(self) -> bytes:
|
||||
"""
|
||||
Returns the tbsCertList payload bytes as defined in RFC 5280.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def __eq__(self, other: object) -> bool:
|
||||
"""
|
||||
Checks equality.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def __len__(self) -> int:
|
||||
"""
|
||||
Number of revoked certificates in the CRL.
|
||||
"""
|
||||
|
||||
@typing.overload
|
||||
def __getitem__(self, idx: int) -> RevokedCertificate:
|
||||
...
|
||||
|
||||
@typing.overload
|
||||
def __getitem__(self, idx: slice) -> typing.List[RevokedCertificate]:
|
||||
...
|
||||
|
||||
@abc.abstractmethod
|
||||
def __getitem__(
|
||||
self, idx: typing.Union[int, slice]
|
||||
) -> typing.Union[RevokedCertificate, typing.List[RevokedCertificate]]:
|
||||
"""
|
||||
Returns a revoked certificate (or slice of revoked certificates).
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def __iter__(self) -> typing.Iterator[RevokedCertificate]:
|
||||
"""
|
||||
Iterator over the revoked certificates
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def is_signature_valid(
|
||||
self, public_key: CertificateIssuerPublicKeyTypes
|
||||
) -> bool:
|
||||
"""
|
||||
Verifies signature of revocation list against given public key.
|
||||
"""
|
||||
CertificateRevocationList = rust_x509.CertificateRevocationList
|
||||
CertificateSigningRequest = rust_x509.CertificateSigningRequest
|
||||
|
||||
|
||||
CertificateRevocationList.register(rust_x509.CertificateRevocationList)
|
||||
load_pem_x509_certificate = rust_x509.load_pem_x509_certificate
|
||||
load_der_x509_certificate = rust_x509.load_der_x509_certificate
|
||||
|
||||
load_pem_x509_certificates = rust_x509.load_pem_x509_certificates
|
||||
|
||||
class CertificateSigningRequest(metaclass=abc.ABCMeta):
|
||||
@abc.abstractmethod
|
||||
def __eq__(self, other: object) -> bool:
|
||||
"""
|
||||
Checks equality.
|
||||
"""
|
||||
load_pem_x509_csr = rust_x509.load_pem_x509_csr
|
||||
load_der_x509_csr = rust_x509.load_der_x509_csr
|
||||
|
||||
@abc.abstractmethod
|
||||
def __hash__(self) -> int:
|
||||
"""
|
||||
Computes a hash.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def public_key(self) -> CertificatePublicKeyTypes:
|
||||
"""
|
||||
Returns the public key
|
||||
"""
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def subject(self) -> Name:
|
||||
"""
|
||||
Returns the subject name object.
|
||||
"""
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def signature_hash_algorithm(
|
||||
self,
|
||||
) -> typing.Optional[hashes.HashAlgorithm]:
|
||||
"""
|
||||
Returns a HashAlgorithm corresponding to the type of the digest signed
|
||||
in the certificate.
|
||||
"""
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def signature_algorithm_oid(self) -> ObjectIdentifier:
|
||||
"""
|
||||
Returns the ObjectIdentifier of the signature algorithm.
|
||||
"""
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def extensions(self) -> Extensions:
|
||||
"""
|
||||
Returns the extensions in the signing request.
|
||||
"""
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def attributes(self) -> Attributes:
|
||||
"""
|
||||
Returns an Attributes object.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def public_bytes(self, encoding: serialization.Encoding) -> bytes:
|
||||
"""
|
||||
Encodes the request to PEM or DER format.
|
||||
"""
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def signature(self) -> bytes:
|
||||
"""
|
||||
Returns the signature bytes.
|
||||
"""
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def tbs_certrequest_bytes(self) -> bytes:
|
||||
"""
|
||||
Returns the PKCS#10 CertificationRequestInfo bytes as defined in RFC
|
||||
2986.
|
||||
"""
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def is_signature_valid(self) -> bool:
|
||||
"""
|
||||
Verifies signature of signing request.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_attribute_for_oid(self, oid: ObjectIdentifier) -> bytes:
|
||||
"""
|
||||
Get the attribute value for a given OID.
|
||||
"""
|
||||
|
||||
|
||||
# Runtime isinstance checks need this since the rust class is not a subclass.
|
||||
CertificateSigningRequest.register(rust_x509.CertificateSigningRequest)
|
||||
|
||||
|
||||
# Backend argument preserved for API compatibility, but ignored.
|
||||
def load_pem_x509_certificate(
|
||||
data: bytes, backend: typing.Any = None
|
||||
) -> Certificate:
|
||||
return rust_x509.load_pem_x509_certificate(data)
|
||||
|
||||
|
||||
def load_pem_x509_certificates(data: bytes) -> typing.List[Certificate]:
|
||||
return rust_x509.load_pem_x509_certificates(data)
|
||||
|
||||
|
||||
# Backend argument preserved for API compatibility, but ignored.
|
||||
def load_der_x509_certificate(
|
||||
data: bytes, backend: typing.Any = None
|
||||
) -> Certificate:
|
||||
return rust_x509.load_der_x509_certificate(data)
|
||||
|
||||
|
||||
# Backend argument preserved for API compatibility, but ignored.
|
||||
def load_pem_x509_csr(
|
||||
data: bytes, backend: typing.Any = None
|
||||
) -> CertificateSigningRequest:
|
||||
return rust_x509.load_pem_x509_csr(data)
|
||||
|
||||
|
||||
# Backend argument preserved for API compatibility, but ignored.
|
||||
def load_der_x509_csr(
|
||||
data: bytes, backend: typing.Any = None
|
||||
) -> CertificateSigningRequest:
|
||||
return rust_x509.load_der_x509_csr(data)
|
||||
|
||||
|
||||
# Backend argument preserved for API compatibility, but ignored.
|
||||
def load_pem_x509_crl(
|
||||
data: bytes, backend: typing.Any = None
|
||||
) -> CertificateRevocationList:
|
||||
return rust_x509.load_pem_x509_crl(data)
|
||||
|
||||
|
||||
# Backend argument preserved for API compatibility, but ignored.
|
||||
def load_der_x509_crl(
|
||||
data: bytes, backend: typing.Any = None
|
||||
) -> CertificateRevocationList:
|
||||
return rust_x509.load_der_x509_crl(data)
|
||||
load_pem_x509_crl = rust_x509.load_pem_x509_crl
|
||||
load_der_x509_crl = rust_x509.load_der_x509_crl
|
||||
|
||||
|
||||
class CertificateSigningRequestBuilder:
|
||||
def __init__(
|
||||
self,
|
||||
subject_name: typing.Optional[Name] = None,
|
||||
extensions: typing.List[Extension[ExtensionType]] = [],
|
||||
attributes: typing.List[
|
||||
typing.Tuple[ObjectIdentifier, bytes, typing.Optional[int]]
|
||||
] = [],
|
||||
subject_name: Name | None = None,
|
||||
extensions: list[Extension[ExtensionType]] = [],
|
||||
attributes: list[tuple[ObjectIdentifier, bytes, int | None]] = [],
|
||||
):
|
||||
"""
|
||||
Creates an empty X.509 certificate request (v1).
|
||||
@@ -664,7 +288,7 @@ class CertificateSigningRequestBuilder:
|
||||
|
||||
return CertificateSigningRequestBuilder(
|
||||
self._subject_name,
|
||||
self._extensions + [extension],
|
||||
[*self._extensions, extension],
|
||||
self._attributes,
|
||||
)
|
||||
|
||||
@@ -673,7 +297,7 @@ class CertificateSigningRequestBuilder:
|
||||
oid: ObjectIdentifier,
|
||||
value: bytes,
|
||||
*,
|
||||
_tag: typing.Optional[_ASN1Type] = None,
|
||||
_tag: _ASN1Type | None = None,
|
||||
) -> CertificateSigningRequestBuilder:
|
||||
"""
|
||||
Adds an X.509 attribute with an OID and associated value.
|
||||
@@ -697,35 +321,57 @@ class CertificateSigningRequestBuilder:
|
||||
return CertificateSigningRequestBuilder(
|
||||
self._subject_name,
|
||||
self._extensions,
|
||||
self._attributes + [(oid, value, tag)],
|
||||
[*self._attributes, (oid, value, tag)],
|
||||
)
|
||||
|
||||
def sign(
|
||||
self,
|
||||
private_key: CertificateIssuerPrivateKeyTypes,
|
||||
algorithm: typing.Optional[_AllowedHashTypes],
|
||||
algorithm: _AllowedHashTypes | None,
|
||||
backend: typing.Any = None,
|
||||
*,
|
||||
rsa_padding: padding.PSS | padding.PKCS1v15 | None = None,
|
||||
ecdsa_deterministic: bool | None = None,
|
||||
) -> CertificateSigningRequest:
|
||||
"""
|
||||
Signs the request using the requestor's private key.
|
||||
"""
|
||||
if self._subject_name is None:
|
||||
raise ValueError("A CertificateSigningRequest must have a subject")
|
||||
return rust_x509.create_x509_csr(self, private_key, algorithm)
|
||||
|
||||
if rsa_padding is not None:
|
||||
if not isinstance(rsa_padding, (padding.PSS, padding.PKCS1v15)):
|
||||
raise TypeError("Padding must be PSS or PKCS1v15")
|
||||
if not isinstance(private_key, rsa.RSAPrivateKey):
|
||||
raise TypeError("Padding is only supported for RSA keys")
|
||||
|
||||
if ecdsa_deterministic is not None:
|
||||
if not isinstance(private_key, ec.EllipticCurvePrivateKey):
|
||||
raise TypeError(
|
||||
"Deterministic ECDSA is only supported for EC keys"
|
||||
)
|
||||
|
||||
return rust_x509.create_x509_csr(
|
||||
self,
|
||||
private_key,
|
||||
algorithm,
|
||||
rsa_padding,
|
||||
ecdsa_deterministic,
|
||||
)
|
||||
|
||||
|
||||
class CertificateBuilder:
|
||||
_extensions: typing.List[Extension[ExtensionType]]
|
||||
_extensions: list[Extension[ExtensionType]]
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
issuer_name: typing.Optional[Name] = None,
|
||||
subject_name: typing.Optional[Name] = None,
|
||||
public_key: typing.Optional[CertificatePublicKeyTypes] = None,
|
||||
serial_number: typing.Optional[int] = None,
|
||||
not_valid_before: typing.Optional[datetime.datetime] = None,
|
||||
not_valid_after: typing.Optional[datetime.datetime] = None,
|
||||
extensions: typing.List[Extension[ExtensionType]] = [],
|
||||
issuer_name: Name | None = None,
|
||||
subject_name: Name | None = None,
|
||||
public_key: CertificatePublicKeyTypes | None = None,
|
||||
serial_number: int | None = None,
|
||||
not_valid_before: datetime.datetime | None = None,
|
||||
not_valid_after: datetime.datetime | None = None,
|
||||
extensions: list[Extension[ExtensionType]] = [],
|
||||
) -> None:
|
||||
self._version = Version.v3
|
||||
self._issuer_name = issuer_name
|
||||
@@ -824,7 +470,7 @@ class CertificateBuilder:
|
||||
# zero.
|
||||
if number.bit_length() >= 160: # As defined in RFC 5280
|
||||
raise ValueError(
|
||||
"The serial number should not be more than 159 " "bits."
|
||||
"The serial number should not be more than 159 bits."
|
||||
)
|
||||
return CertificateBuilder(
|
||||
self._issuer_name,
|
||||
@@ -876,8 +522,7 @@ class CertificateBuilder:
|
||||
time = _convert_to_naive_utc_time(time)
|
||||
if time < _EARLIEST_UTC_TIME:
|
||||
raise ValueError(
|
||||
"The not valid after date must be on or after"
|
||||
" 1950 January 1."
|
||||
"The not valid after date must be on or after 1950 January 1."
|
||||
)
|
||||
if (
|
||||
self._not_valid_before is not None
|
||||
@@ -916,18 +561,17 @@ class CertificateBuilder:
|
||||
self._serial_number,
|
||||
self._not_valid_before,
|
||||
self._not_valid_after,
|
||||
self._extensions + [extension],
|
||||
[*self._extensions, extension],
|
||||
)
|
||||
|
||||
def sign(
|
||||
self,
|
||||
private_key: CertificateIssuerPrivateKeyTypes,
|
||||
algorithm: typing.Optional[_AllowedHashTypes],
|
||||
algorithm: _AllowedHashTypes | None,
|
||||
backend: typing.Any = None,
|
||||
*,
|
||||
rsa_padding: typing.Optional[
|
||||
typing.Union[padding.PSS, padding.PKCS1v15]
|
||||
] = None,
|
||||
rsa_padding: padding.PSS | padding.PKCS1v15 | None = None,
|
||||
ecdsa_deterministic: bool | None = None,
|
||||
) -> Certificate:
|
||||
"""
|
||||
Signs the certificate using the CA's private key.
|
||||
@@ -956,22 +600,32 @@ class CertificateBuilder:
|
||||
if not isinstance(private_key, rsa.RSAPrivateKey):
|
||||
raise TypeError("Padding is only supported for RSA keys")
|
||||
|
||||
if ecdsa_deterministic is not None:
|
||||
if not isinstance(private_key, ec.EllipticCurvePrivateKey):
|
||||
raise TypeError(
|
||||
"Deterministic ECDSA is only supported for EC keys"
|
||||
)
|
||||
|
||||
return rust_x509.create_x509_certificate(
|
||||
self, private_key, algorithm, rsa_padding
|
||||
self,
|
||||
private_key,
|
||||
algorithm,
|
||||
rsa_padding,
|
||||
ecdsa_deterministic,
|
||||
)
|
||||
|
||||
|
||||
class CertificateRevocationListBuilder:
|
||||
_extensions: typing.List[Extension[ExtensionType]]
|
||||
_revoked_certificates: typing.List[RevokedCertificate]
|
||||
_extensions: list[Extension[ExtensionType]]
|
||||
_revoked_certificates: list[RevokedCertificate]
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
issuer_name: typing.Optional[Name] = None,
|
||||
last_update: typing.Optional[datetime.datetime] = None,
|
||||
next_update: typing.Optional[datetime.datetime] = None,
|
||||
extensions: typing.List[Extension[ExtensionType]] = [],
|
||||
revoked_certificates: typing.List[RevokedCertificate] = [],
|
||||
issuer_name: Name | None = None,
|
||||
last_update: datetime.datetime | None = None,
|
||||
next_update: datetime.datetime | None = None,
|
||||
extensions: list[Extension[ExtensionType]] = [],
|
||||
revoked_certificates: list[RevokedCertificate] = [],
|
||||
):
|
||||
self._issuer_name = issuer_name
|
||||
self._last_update = last_update
|
||||
@@ -1004,7 +658,7 @@ class CertificateRevocationListBuilder:
|
||||
last_update = _convert_to_naive_utc_time(last_update)
|
||||
if last_update < _EARLIEST_UTC_TIME:
|
||||
raise ValueError(
|
||||
"The last update date must be on or after" " 1950 January 1."
|
||||
"The last update date must be on or after 1950 January 1."
|
||||
)
|
||||
if self._next_update is not None and last_update > self._next_update:
|
||||
raise ValueError(
|
||||
@@ -1028,7 +682,7 @@ class CertificateRevocationListBuilder:
|
||||
next_update = _convert_to_naive_utc_time(next_update)
|
||||
if next_update < _EARLIEST_UTC_TIME:
|
||||
raise ValueError(
|
||||
"The last update date must be on or after" " 1950 January 1."
|
||||
"The last update date must be on or after 1950 January 1."
|
||||
)
|
||||
if self._last_update is not None and next_update < self._last_update:
|
||||
raise ValueError(
|
||||
@@ -1057,7 +711,7 @@ class CertificateRevocationListBuilder:
|
||||
self._issuer_name,
|
||||
self._last_update,
|
||||
self._next_update,
|
||||
self._extensions + [extension],
|
||||
[*self._extensions, extension],
|
||||
self._revoked_certificates,
|
||||
)
|
||||
|
||||
@@ -1075,14 +729,17 @@ class CertificateRevocationListBuilder:
|
||||
self._last_update,
|
||||
self._next_update,
|
||||
self._extensions,
|
||||
self._revoked_certificates + [revoked_certificate],
|
||||
[*self._revoked_certificates, revoked_certificate],
|
||||
)
|
||||
|
||||
def sign(
|
||||
self,
|
||||
private_key: CertificateIssuerPrivateKeyTypes,
|
||||
algorithm: typing.Optional[_AllowedHashTypes],
|
||||
algorithm: _AllowedHashTypes | None,
|
||||
backend: typing.Any = None,
|
||||
*,
|
||||
rsa_padding: padding.PSS | padding.PKCS1v15 | None = None,
|
||||
ecdsa_deterministic: bool | None = None,
|
||||
) -> CertificateRevocationList:
|
||||
if self._issuer_name is None:
|
||||
raise ValueError("A CRL must have an issuer name")
|
||||
@@ -1093,15 +750,33 @@ class CertificateRevocationListBuilder:
|
||||
if self._next_update is None:
|
||||
raise ValueError("A CRL must have a next update time")
|
||||
|
||||
return rust_x509.create_x509_crl(self, private_key, algorithm)
|
||||
if rsa_padding is not None:
|
||||
if not isinstance(rsa_padding, (padding.PSS, padding.PKCS1v15)):
|
||||
raise TypeError("Padding must be PSS or PKCS1v15")
|
||||
if not isinstance(private_key, rsa.RSAPrivateKey):
|
||||
raise TypeError("Padding is only supported for RSA keys")
|
||||
|
||||
if ecdsa_deterministic is not None:
|
||||
if not isinstance(private_key, ec.EllipticCurvePrivateKey):
|
||||
raise TypeError(
|
||||
"Deterministic ECDSA is only supported for EC keys"
|
||||
)
|
||||
|
||||
return rust_x509.create_x509_crl(
|
||||
self,
|
||||
private_key,
|
||||
algorithm,
|
||||
rsa_padding,
|
||||
ecdsa_deterministic,
|
||||
)
|
||||
|
||||
|
||||
class RevokedCertificateBuilder:
|
||||
def __init__(
|
||||
self,
|
||||
serial_number: typing.Optional[int] = None,
|
||||
revocation_date: typing.Optional[datetime.datetime] = None,
|
||||
extensions: typing.List[Extension[ExtensionType]] = [],
|
||||
serial_number: int | None = None,
|
||||
revocation_date: datetime.datetime | None = None,
|
||||
extensions: list[Extension[ExtensionType]] = [],
|
||||
):
|
||||
self._serial_number = serial_number
|
||||
self._revocation_date = revocation_date
|
||||
@@ -1119,7 +794,7 @@ class RevokedCertificateBuilder:
|
||||
# zero.
|
||||
if number.bit_length() >= 160: # As defined in RFC 5280
|
||||
raise ValueError(
|
||||
"The serial number should not be more than 159 " "bits."
|
||||
"The serial number should not be more than 159 bits."
|
||||
)
|
||||
return RevokedCertificateBuilder(
|
||||
number, self._revocation_date, self._extensions
|
||||
@@ -1135,7 +810,7 @@ class RevokedCertificateBuilder:
|
||||
time = _convert_to_naive_utc_time(time)
|
||||
if time < _EARLIEST_UTC_TIME:
|
||||
raise ValueError(
|
||||
"The revocation date must be on or after" " 1950 January 1."
|
||||
"The revocation date must be on or after 1950 January 1."
|
||||
)
|
||||
return RevokedCertificateBuilder(
|
||||
self._serial_number, time, self._extensions
|
||||
@@ -1152,7 +827,7 @@ class RevokedCertificateBuilder:
|
||||
return RevokedCertificateBuilder(
|
||||
self._serial_number,
|
||||
self._revocation_date,
|
||||
self._extensions + [extension],
|
||||
[*self._extensions, extension],
|
||||
)
|
||||
|
||||
def build(self, backend: typing.Any = None) -> RevokedCertificate:
|
||||
|
||||
Reference in New Issue
Block a user