mirror of
https://gitlab.sectorq.eu/jaydee/omv_backup.git
synced 2025-07-03 00:23:06 +02:00
added v3
This commit is contained in:
344
venv/lib/python3.11/site-packages/cryptography/x509/ocsp.py
Normal file
344
venv/lib/python3.11/site-packages/cryptography/x509/ocsp.py
Normal file
@ -0,0 +1,344 @@
|
||||
# This file is dual licensed under the terms of the Apache License, Version
|
||||
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
|
||||
# for complete details.
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import datetime
|
||||
import typing
|
||||
|
||||
from cryptography import utils, x509
|
||||
from cryptography.hazmat.bindings._rust import ocsp
|
||||
from cryptography.hazmat.primitives import hashes
|
||||
from cryptography.hazmat.primitives.asymmetric.types import (
|
||||
CertificateIssuerPrivateKeyTypes,
|
||||
)
|
||||
from cryptography.x509.base import (
|
||||
_EARLIEST_UTC_TIME,
|
||||
_convert_to_naive_utc_time,
|
||||
_reject_duplicate_extension,
|
||||
)
|
||||
|
||||
|
||||
class OCSPResponderEncoding(utils.Enum):
|
||||
HASH = "By Hash"
|
||||
NAME = "By Name"
|
||||
|
||||
|
||||
class OCSPResponseStatus(utils.Enum):
|
||||
SUCCESSFUL = 0
|
||||
MALFORMED_REQUEST = 1
|
||||
INTERNAL_ERROR = 2
|
||||
TRY_LATER = 3
|
||||
SIG_REQUIRED = 5
|
||||
UNAUTHORIZED = 6
|
||||
|
||||
|
||||
_ALLOWED_HASHES = (
|
||||
hashes.SHA1,
|
||||
hashes.SHA224,
|
||||
hashes.SHA256,
|
||||
hashes.SHA384,
|
||||
hashes.SHA512,
|
||||
)
|
||||
|
||||
|
||||
def _verify_algorithm(algorithm: hashes.HashAlgorithm) -> None:
|
||||
if not isinstance(algorithm, _ALLOWED_HASHES):
|
||||
raise ValueError(
|
||||
"Algorithm must be SHA1, SHA224, SHA256, SHA384, or SHA512"
|
||||
)
|
||||
|
||||
|
||||
class OCSPCertStatus(utils.Enum):
|
||||
GOOD = 0
|
||||
REVOKED = 1
|
||||
UNKNOWN = 2
|
||||
|
||||
|
||||
class _SingleResponse:
|
||||
def __init__(
|
||||
self,
|
||||
cert: x509.Certificate,
|
||||
issuer: x509.Certificate,
|
||||
algorithm: hashes.HashAlgorithm,
|
||||
cert_status: OCSPCertStatus,
|
||||
this_update: datetime.datetime,
|
||||
next_update: datetime.datetime | None,
|
||||
revocation_time: datetime.datetime | None,
|
||||
revocation_reason: x509.ReasonFlags | None,
|
||||
):
|
||||
if not isinstance(cert, x509.Certificate) or not isinstance(
|
||||
issuer, x509.Certificate
|
||||
):
|
||||
raise TypeError("cert and issuer must be a Certificate")
|
||||
|
||||
_verify_algorithm(algorithm)
|
||||
if not isinstance(this_update, datetime.datetime):
|
||||
raise TypeError("this_update must be a datetime object")
|
||||
if next_update is not None and not isinstance(
|
||||
next_update, datetime.datetime
|
||||
):
|
||||
raise TypeError("next_update must be a datetime object or None")
|
||||
|
||||
self._cert = cert
|
||||
self._issuer = issuer
|
||||
self._algorithm = algorithm
|
||||
self._this_update = this_update
|
||||
self._next_update = next_update
|
||||
|
||||
if not isinstance(cert_status, OCSPCertStatus):
|
||||
raise TypeError(
|
||||
"cert_status must be an item from the OCSPCertStatus enum"
|
||||
)
|
||||
if cert_status is not OCSPCertStatus.REVOKED:
|
||||
if revocation_time is not None:
|
||||
raise ValueError(
|
||||
"revocation_time can only be provided if the certificate "
|
||||
"is revoked"
|
||||
)
|
||||
if revocation_reason is not None:
|
||||
raise ValueError(
|
||||
"revocation_reason can only be provided if the certificate"
|
||||
" is revoked"
|
||||
)
|
||||
else:
|
||||
if not isinstance(revocation_time, datetime.datetime):
|
||||
raise TypeError("revocation_time must be a datetime object")
|
||||
|
||||
revocation_time = _convert_to_naive_utc_time(revocation_time)
|
||||
if revocation_time < _EARLIEST_UTC_TIME:
|
||||
raise ValueError(
|
||||
"The revocation_time must be on or after"
|
||||
" 1950 January 1."
|
||||
)
|
||||
|
||||
if revocation_reason is not None and not isinstance(
|
||||
revocation_reason, x509.ReasonFlags
|
||||
):
|
||||
raise TypeError(
|
||||
"revocation_reason must be an item from the ReasonFlags "
|
||||
"enum or None"
|
||||
)
|
||||
|
||||
self._cert_status = cert_status
|
||||
self._revocation_time = revocation_time
|
||||
self._revocation_reason = revocation_reason
|
||||
|
||||
|
||||
OCSPRequest = ocsp.OCSPRequest
|
||||
OCSPResponse = ocsp.OCSPResponse
|
||||
OCSPSingleResponse = ocsp.OCSPSingleResponse
|
||||
|
||||
|
||||
class OCSPRequestBuilder:
|
||||
def __init__(
|
||||
self,
|
||||
request: tuple[
|
||||
x509.Certificate, x509.Certificate, hashes.HashAlgorithm
|
||||
]
|
||||
| None = None,
|
||||
request_hash: tuple[bytes, bytes, int, hashes.HashAlgorithm]
|
||||
| None = None,
|
||||
extensions: list[x509.Extension[x509.ExtensionType]] = [],
|
||||
) -> None:
|
||||
self._request = request
|
||||
self._request_hash = request_hash
|
||||
self._extensions = extensions
|
||||
|
||||
def add_certificate(
|
||||
self,
|
||||
cert: x509.Certificate,
|
||||
issuer: x509.Certificate,
|
||||
algorithm: hashes.HashAlgorithm,
|
||||
) -> OCSPRequestBuilder:
|
||||
if self._request is not None or self._request_hash is not None:
|
||||
raise ValueError("Only one certificate can be added to a request")
|
||||
|
||||
_verify_algorithm(algorithm)
|
||||
if not isinstance(cert, x509.Certificate) or not isinstance(
|
||||
issuer, x509.Certificate
|
||||
):
|
||||
raise TypeError("cert and issuer must be a Certificate")
|
||||
|
||||
return OCSPRequestBuilder(
|
||||
(cert, issuer, algorithm), self._request_hash, self._extensions
|
||||
)
|
||||
|
||||
def add_certificate_by_hash(
|
||||
self,
|
||||
issuer_name_hash: bytes,
|
||||
issuer_key_hash: bytes,
|
||||
serial_number: int,
|
||||
algorithm: hashes.HashAlgorithm,
|
||||
) -> OCSPRequestBuilder:
|
||||
if self._request is not None or self._request_hash is not None:
|
||||
raise ValueError("Only one certificate can be added to a request")
|
||||
|
||||
if not isinstance(serial_number, int):
|
||||
raise TypeError("serial_number must be an integer")
|
||||
|
||||
_verify_algorithm(algorithm)
|
||||
utils._check_bytes("issuer_name_hash", issuer_name_hash)
|
||||
utils._check_bytes("issuer_key_hash", issuer_key_hash)
|
||||
if algorithm.digest_size != len(
|
||||
issuer_name_hash
|
||||
) or algorithm.digest_size != len(issuer_key_hash):
|
||||
raise ValueError(
|
||||
"issuer_name_hash and issuer_key_hash must be the same length "
|
||||
"as the digest size of the algorithm"
|
||||
)
|
||||
|
||||
return OCSPRequestBuilder(
|
||||
self._request,
|
||||
(issuer_name_hash, issuer_key_hash, serial_number, algorithm),
|
||||
self._extensions,
|
||||
)
|
||||
|
||||
def add_extension(
|
||||
self, extval: x509.ExtensionType, critical: bool
|
||||
) -> OCSPRequestBuilder:
|
||||
if not isinstance(extval, x509.ExtensionType):
|
||||
raise TypeError("extension must be an ExtensionType")
|
||||
|
||||
extension = x509.Extension(extval.oid, critical, extval)
|
||||
_reject_duplicate_extension(extension, self._extensions)
|
||||
|
||||
return OCSPRequestBuilder(
|
||||
self._request, self._request_hash, [*self._extensions, extension]
|
||||
)
|
||||
|
||||
def build(self) -> OCSPRequest:
|
||||
if self._request is None and self._request_hash is None:
|
||||
raise ValueError("You must add a certificate before building")
|
||||
|
||||
return ocsp.create_ocsp_request(self)
|
||||
|
||||
|
||||
class OCSPResponseBuilder:
|
||||
def __init__(
|
||||
self,
|
||||
response: _SingleResponse | None = None,
|
||||
responder_id: tuple[x509.Certificate, OCSPResponderEncoding]
|
||||
| None = None,
|
||||
certs: list[x509.Certificate] | None = None,
|
||||
extensions: list[x509.Extension[x509.ExtensionType]] = [],
|
||||
):
|
||||
self._response = response
|
||||
self._responder_id = responder_id
|
||||
self._certs = certs
|
||||
self._extensions = extensions
|
||||
|
||||
def add_response(
|
||||
self,
|
||||
cert: x509.Certificate,
|
||||
issuer: x509.Certificate,
|
||||
algorithm: hashes.HashAlgorithm,
|
||||
cert_status: OCSPCertStatus,
|
||||
this_update: datetime.datetime,
|
||||
next_update: datetime.datetime | None,
|
||||
revocation_time: datetime.datetime | None,
|
||||
revocation_reason: x509.ReasonFlags | None,
|
||||
) -> OCSPResponseBuilder:
|
||||
if self._response is not None:
|
||||
raise ValueError("Only one response per OCSPResponse.")
|
||||
|
||||
singleresp = _SingleResponse(
|
||||
cert,
|
||||
issuer,
|
||||
algorithm,
|
||||
cert_status,
|
||||
this_update,
|
||||
next_update,
|
||||
revocation_time,
|
||||
revocation_reason,
|
||||
)
|
||||
return OCSPResponseBuilder(
|
||||
singleresp,
|
||||
self._responder_id,
|
||||
self._certs,
|
||||
self._extensions,
|
||||
)
|
||||
|
||||
def responder_id(
|
||||
self, encoding: OCSPResponderEncoding, responder_cert: x509.Certificate
|
||||
) -> OCSPResponseBuilder:
|
||||
if self._responder_id is not None:
|
||||
raise ValueError("responder_id can only be set once")
|
||||
if not isinstance(responder_cert, x509.Certificate):
|
||||
raise TypeError("responder_cert must be a Certificate")
|
||||
if not isinstance(encoding, OCSPResponderEncoding):
|
||||
raise TypeError(
|
||||
"encoding must be an element from OCSPResponderEncoding"
|
||||
)
|
||||
|
||||
return OCSPResponseBuilder(
|
||||
self._response,
|
||||
(responder_cert, encoding),
|
||||
self._certs,
|
||||
self._extensions,
|
||||
)
|
||||
|
||||
def certificates(
|
||||
self, certs: typing.Iterable[x509.Certificate]
|
||||
) -> OCSPResponseBuilder:
|
||||
if self._certs is not None:
|
||||
raise ValueError("certificates may only be set once")
|
||||
certs = list(certs)
|
||||
if len(certs) == 0:
|
||||
raise ValueError("certs must not be an empty list")
|
||||
if not all(isinstance(x, x509.Certificate) for x in certs):
|
||||
raise TypeError("certs must be a list of Certificates")
|
||||
return OCSPResponseBuilder(
|
||||
self._response,
|
||||
self._responder_id,
|
||||
certs,
|
||||
self._extensions,
|
||||
)
|
||||
|
||||
def add_extension(
|
||||
self, extval: x509.ExtensionType, critical: bool
|
||||
) -> OCSPResponseBuilder:
|
||||
if not isinstance(extval, x509.ExtensionType):
|
||||
raise TypeError("extension must be an ExtensionType")
|
||||
|
||||
extension = x509.Extension(extval.oid, critical, extval)
|
||||
_reject_duplicate_extension(extension, self._extensions)
|
||||
|
||||
return OCSPResponseBuilder(
|
||||
self._response,
|
||||
self._responder_id,
|
||||
self._certs,
|
||||
[*self._extensions, extension],
|
||||
)
|
||||
|
||||
def sign(
|
||||
self,
|
||||
private_key: CertificateIssuerPrivateKeyTypes,
|
||||
algorithm: hashes.HashAlgorithm | None,
|
||||
) -> OCSPResponse:
|
||||
if self._response is None:
|
||||
raise ValueError("You must add a response before signing")
|
||||
if self._responder_id is None:
|
||||
raise ValueError("You must add a responder_id before signing")
|
||||
|
||||
return ocsp.create_ocsp_response(
|
||||
OCSPResponseStatus.SUCCESSFUL, self, private_key, algorithm
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def build_unsuccessful(
|
||||
cls, response_status: OCSPResponseStatus
|
||||
) -> OCSPResponse:
|
||||
if not isinstance(response_status, OCSPResponseStatus):
|
||||
raise TypeError(
|
||||
"response_status must be an item from OCSPResponseStatus"
|
||||
)
|
||||
if response_status is OCSPResponseStatus.SUCCESSFUL:
|
||||
raise ValueError("response_status cannot be SUCCESSFUL")
|
||||
|
||||
return ocsp.create_ocsp_response(response_status, None, None, None)
|
||||
|
||||
|
||||
load_der_ocsp_request = ocsp.load_der_ocsp_request
|
||||
load_der_ocsp_response = ocsp.load_der_ocsp_response
|
Reference in New Issue
Block a user