""" Java security.cert standard library APIs implemented in Python. java.security.cert package - Certificate, CertPath, CRL, PKIX, etc. """ from __future__ import annotations from .._core import Stub, AndroidOnlyError from .security import GeneralSecurityException, CertificateFactory as _OldCF from .lang import RuntimeException, String import datetime as _datetime import typing as _typing __all__ = [ "Certificate", "CertificateFactory", "X509Certificate", "X509CRL", "X509CRLEntry", "CertPath", "CertPathBuilder", "CertPathValidator", "CertStore", "CertificateNotYetValidException", "CertificateExpiredException", "CertificateEncodingException", "CertificateParsingException", "CertPathValidatorException", "CertPathBuilderException", "CRL", "CRLException", "PolicyQualifierInfo", "TrustAnchor", "Extension", "X509Extension", "CollectionCertStoreParameters", "LDAPCertStoreParameters", "CertStoreParameters", "PKIXParameters", "PKIXBuilderParameters", "PKIXCertPathBuilderResult", "PKIXCertPathValidatorResult", "CertPathBuilderResult", "CertPathValidatorResult", "CertPathParameters", "CRL_REASON_UNSPECIFIED", "CRL_REASON_KEY_COMPROMISE", "CRL_REASON_CA_COMPROMISE", "CRL_REASON_AFFILIATION_CHANGED", "CRL_REASON_SUPERSEDED", "CRL_REASON_CESSATION_OF_OPERATION", "CRL_REASON_CERTIFICATE_HOLD", "CRL_REASON_REMOVE_FROM_CRL", "CRL_REASON_PRIVILEGE_WITHDRAWN", "CRL_REASON_AA_COMPROMISE", ] # ============================================================ # CRL Reason Constants # ============================================================ CRL_REASON_UNSPECIFIED = 0 CRL_REASON_KEY_COMPROMISE = 1 CRL_REASON_CA_COMPROMISE = 2 CRL_REASON_AFFILIATION_CHANGED = 3 CRL_REASON_SUPERSEDED = 4 CRL_REASON_CESSATION_OF_OPERATION = 5 CRL_REASON_CERTIFICATE_HOLD = 6 CRL_REASON_REMOVE_FROM_CRL = 8 CRL_REASON_PRIVILEGE_WITHDRAWN = 9 CRL_REASON_AA_COMPROMISE = 10 # ============================================================ # CertPathParameters # ============================================================ class CertPathParameters(Stub): """java.security.cert.CertPathParameters""" def clone(self): return self.__class__() class CertPathBuilderResult(Stub): """java.security.cert.CertPathBuilderResult""" def getCertPath(self): return CertPath("") def clone(self): return self.__class__() class CertPathValidatorResult(Stub): """java.security.cert.CertPathValidatorResult""" def clone(self): return self.__class__() # ============================================================ # CertStoreParameters # ============================================================ class CertStoreParameters(Stub): """java.security.cert.CertStoreParameters""" def clone(self): return self.__class__() class CollectionCertStoreParameters(CertStoreParameters): """java.security.cert.CollectionCertStoreParameters""" def __init__(self, collection=None): super().__init__() if collection is None: self._collection = [] else: self._collection = list(collection) def getCollection(self): return self._collection def clone(self): return CollectionCertStoreParameters(self._collection) def toString(self): return f"CollectionCertStoreParameters: [collection: {len(self._collection)}]" class LDAPCertStoreParameters(CertStoreParameters): """java.security.cert.LDAPCertStoreParameters""" def __init__(self, server_name="localhost", port=389): super().__init__() self._server_name = server_name self._port = port def getServerName(self): return self._server_name def getPort(self): return self._port def clone(self): return LDAPCertStoreParameters(self._server_name, self._port) def toString(self): return f"LDAPCertStoreParameters: [serverName: {self._server_name}, port: {self._port}]" # ============================================================ # Exception Classes # ============================================================ class CertificateException(GeneralSecurityException): """java.security.cert.CertificateException""" pass class CertificateEncodingException(CertificateException): """java.security.cert.CertificateEncodingException""" pass class CertificateParsingException(CertificateException): """java.security.cert.CertificateParsingException""" pass class CertificateNotYetValidException(CertificateException): """java.security.cert.CertificateNotYetValidException""" pass class CertificateExpiredException(CertificateException): """java.security.cert.CertificateExpiredException""" pass class CRLException(GeneralSecurityException): """java.security.cert.CRLException""" pass class CertPathBuilderException(GeneralSecurityException): """java.security.cert.CertPathBuilderException""" def __init__(self, message=None, cause=None): super().__init__() self._detail = message or "" self._cause = cause def getMessage(self): return self._detail def getCause(self): return self._cause class CertPathValidatorException(GeneralSecurityException): """java.security.cert.CertPathValidatorException""" class Reason(Stub): pass def __init__(self, message=None, cause=None, cert_path=None, index=-1): super().__init__() self._detail = message or "" self._cause = cause self._cert_path = cert_path self._index = index def getMessage(self): return self._detail def getCause(self): return self._cause def getCertPath(self): return self._cert_path def getIndex(self): return self._index # ============================================================ # Certificate # ============================================================ class Certificate(Stub): """java.security.cert.Certificate""" def __init__(self, type_name=""): super().__init__() self._type = type_name def getType(self): return self._type def getEncoded(self): raise CertificateEncodingException("Certificate not encoded") def verify(self, key): raise NotImplementedError def toString(self): return f"Certificate type={self._type}" def getPublicKey(self): from .security import PublicKey return PublicKey() def equals(self, other): if not isinstance(other, Certificate): return False return self._type == other._type def hashCode(self): return hash(self._type) class X509Certificate(Certificate): """java.security.cert.X509Certificate""" def __init__(self): super().__init__("X.509") self._encoded = b"" self._subject = "" self._issuer = "" self._serial = 0 self._not_before = _datetime.datetime.now() self._not_after = _datetime.datetime.now() + _datetime.timedelta(days=365) self._sig_alg = "SHA256withRSA" self._sig_alg_oid = "1.2.840.113549.1.1.11" self._version = 3 self._public_key = None self._extensions = {} def getEncoded(self): if not self._encoded: raise CertificateEncodingException("X509Cert not encoded") return self._encoded def verify(self, key): return True def getPublicKey(self): if self._public_key is None: from .security import PublicKey self._public_key = PublicKey() return self._public_key def getSubjectX500Principal(self): from .security import Principal return Principal(self._subject) def getIssuerX500Principal(self): from .security import Principal return Principal(self._issuer) def getSerialNumber(self): return self._serial def getNotBefore(self): return self._not_before def getNotAfter(self): return self._not_after def getSigAlgName(self): return self._sig_alg def getSigAlgOID(self): return self._sig_alg_oid def getVersion(self): return self._version def checkValidity(self, date=None): if date is None: date = _datetime.datetime.now() if date < self._not_before: raise CertificateNotYetValidException( f"Certificate not valid until {self._not_before}" ) if date > self._not_after: raise CertificateExpiredException( f"Certificate expired at {self._not_after}" ) def getExtendedKeyUsage(self): return None def getBasicConstraints(self): return -1 def getSubjectAlternativeNames(self): return None def getIssuerAlternativeNames(self): return None def getKeyUsage(self): return None def hasUnsupportedCriticalExtension(self): return False def getCriticalExtensionOIDs(self): return list(self._extensions.keys()) def getNonCriticalExtensionOIDs(self): return [] def getExtensionValue(self, oid): return self._extensions.get(oid) def toString(self): return f"X509Certificate [subject={self._subject}, issuer={self._issuer}]" def setEncoded(self, encoded): self._encoded = bytes(encoded) def setSubject(self, subject): self._subject = subject def setIssuer(self, issuer): self._issuer = issuer def setSerialNumber(self, serial): self._serial = serial def setNotBefore(self, dt): self._not_before = dt def setNotAfter(self, dt): self._not_after = dt # ============================================================ # CRL / X509CRL / X509CRLEntry # ============================================================ class CRL(Stub): """java.security.cert.CRL""" def __init__(self, type_name=""): super().__init__() self._type = type_name def getType(self): return self._type def isRevoked(self, cert): return False def toString(self): return f"CRL type={self._type}" class X509CRLEntry(Stub): """java.security.cert.X509CRLEntry""" def __init__(self): super().__init__() self._serial_number = 0 self._revocation_date = _datetime.datetime.now() self._extensions = {} def getSerialNumber(self): return self._serial_number def getRevocationDate(self): return self._revocation_date def hasExtensions(self): return len(self._extensions) > 0 def toString(self): return f"X509CRLEntry serial={self._serial_number}" def getCertificateIssuer(self): return None def getEncoded(self): return b"" def getCriticalExtensionOIDs(self): return list(self._extensions.keys()) def getNonCriticalExtensionOIDs(self): return [] def getExtensionValue(self, oid): return self._extensions.get(oid) class X509CRL(CRL): """java.security.cert.X509CRL""" def __init__(self): super().__init__("X.509") self._encoded = b"" self._issuer = "" self._this_update = _datetime.datetime.now() self._next_update = _datetime.datetime.now() + _datetime.timedelta(days=7) self._sig_alg = "SHA256withRSA" self._version = 2 self._entries = [] def getEncoded(self): return self._encoded def verify(self, key): return True def getIssuerX500Principal(self): from .security import Principal return Principal(self._issuer) def getThisUpdate(self): return self._this_update def getNextUpdate(self): return self._next_update def getSigAlgName(self): return self._sig_alg def getSigAlgOID(self): return "1.2.840.113549.1.1.11" def getVersion(self): return self._version def isRevoked(self, cert): for entry in self._entries: if hasattr(cert, 'getSerialNumber'): if entry.getSerialNumber() == cert.getSerialNumber(): return True return False def getRevokedCertificate(self, cert): for entry in self._entries: if hasattr(cert, 'getSerialNumber'): if entry.getSerialNumber() == cert.getSerialNumber(): return entry return None def getRevokedCertificates(self): return self._entries if self._entries else None def getCriticalExtensionOIDs(self): return [] def getNonCriticalExtensionOIDs(self): return [] def getExtensionValue(self, oid): return None def hasUnsupportedCriticalExtension(self): return False def toString(self): return f"X509CRL issuer={self._issuer}" def addEntry(self, entry): self._entries.append(entry) def setIssuer(self, issuer): self._issuer = issuer # ============================================================ # CertPath # ============================================================ class CertPath(Stub): """java.security.cert.CertPath""" def __init__(self, algorithm): super().__init__() self._algorithm = algorithm self._certs = [] self._encoded = b"" def getType(self): return self._algorithm def getCertificates(self): return self._certs def getEncoded(self, encoding=None): return self._encoded def getEncodings(self): return ["PKCS7"] def toString(self): return f"CertPath: {self._algorithm} [{len(self._certs)} cert(s)]" def equals(self, other): if not isinstance(other, CertPath): return False return self._algorithm == other._algorithm and self._certs == other._certs def hashCode(self): return hash(self._algorithm) ^ hash(tuple(self._certs)) # ============================================================ # CertificateFactory # ============================================================ class CertificateFactory(Stub): """java.security.cert.CertificateFactory""" def __init__(self, algorithm): super().__init__() self._algorithm = algorithm @staticmethod def getInstance(algorithm, provider=None): return CertificateFactory(algorithm) def generateCertificate(self, in_stream): cert = X509Certificate() if hasattr(in_stream, 'read'): data = in_stream.read() cert.setEncoded(data if isinstance(data, bytes) else data.encode()) return cert def generateCertPath(self, in_stream, encoding=None): return CertPath("X.509") def generateCRL(self, in_stream): return X509CRL() def getCertPathEncodings(self): return ["PKCS7"] def getProvider(self): from .security import Provider return Provider("SUN", 1.0, "Default provider") def getType(self): return self._algorithm # ============================================================ # CertPathBuilder / CertPathValidator / CertStore # ============================================================ class CertPathBuilder(Stub): """java.security.cert.CertPathBuilder""" def __init__(self, algorithm): super().__init__() self._algorithm = algorithm @staticmethod def getInstance(algorithm, provider=None): return CertPathBuilder(algorithm) def build(self, params): if not isinstance(params, CertPathParameters): raise CertPathBuilderException("Invalid params") return PKIXCertPathBuilderResult(CertPath("X.509")) def getAlgorithm(self): return self._algorithm def getProvider(self): from .security import Provider return Provider("SUN", 1.0, "Default provider") class CertPathValidator(Stub): """java.security.cert.CertPathValidator""" def __init__(self, algorithm): super().__init__() self._algorithm = algorithm @staticmethod def getInstance(algorithm, provider=None): return CertPathValidator(algorithm) def validate(self, cert_path, params): if not isinstance(cert_path, CertPath): raise CertPathValidatorException("Invalid cert path") return PKIXCertPathValidatorResult() def getAlgorithm(self): return self._algorithm def getProvider(self): from .security import Provider return Provider("SUN", 1.0, "Default provider") class CertStore(Stub): """java.security.cert.CertStore""" def __init__(self, type_name, params): super().__init__() self._type = type_name self._params = params @staticmethod def getInstance(type_name, params, provider=None): return CertStore(type_name, params) def getCertificates(self, selector): return [] def getCRLs(self, selector): return [] def getType(self): return self._type def getCertStoreParameters(self): return self._params # ============================================================ # PolicyQualifierInfo # ============================================================ class PolicyQualifierInfo(Stub): """java.security.cert.PolicyQualifierInfo""" def __init__(self, encoded): super().__init__() self._encoded = encoded def getEncoded(self): return self._encoded def getPolicyQualifierId(self): return "1.3.6.1.5.5.7.2.1" def getPolicyQualifier(self): return self._encoded def toString(self): return f"PolicyQualifierInfo [id={self.getPolicyQualifierId()}]" # ============================================================ # TrustAnchor # ============================================================ class TrustAnchor(Stub): """java.security.cert.TrustAnchor""" def __init__(self, ca_cert, ca_name=None, ca_public_key=None, name_constraints=None): super().__init__() self._ca_cert = ca_cert self._ca_name = ca_name self._ca_public_key = ca_public_key self._name_constraints = name_constraints def getTrustedCert(self): return self._ca_cert def getCAName(self): return self._ca_name def getCAPublicKey(self): return self._ca_public_key def getNameConstraints(self): return self._name_constraints def toString(self): return f"TrustAnchor [CA={self._ca_name}]" # ============================================================ # Extension / X509Extension # ============================================================ class Extension(Stub): """java.security.cert.Extension""" def __init__(self, oid="", critical=False, value=b""): super().__init__() self._oid = oid self._critical = critical self._value = value def getId(self): return self._oid def isCritical(self): return self._critical def getValue(self): return self._value def getEncoded(self): return self._value def toString(self): return f"Extension oid={self._oid} critical={self._critical}" class X509Extension(Stub): """java.security.cert.X509Extension""" def hasUnsupportedCriticalExtension(self): return False def getCriticalExtensionOIDs(self): return [] def getNonCriticalExtensionOIDs(self): return [] def getExtensionValue(self, oid): return None # ============================================================ # PKIXParameters / PKIXBuilderParameters # ============================================================ class PKIXParameters(CertPathParameters): """java.security.cert.PKIXParameters""" def __init__(self, trust_anchors=None): super().__init__() if trust_anchors is not None: if isinstance(trust_anchors, set): self._trust_anchors = trust_anchors else: self._trust_anchors = set(trust_anchors) else: self._trust_anchors = set() self._date = None self._cert_stores = [] self._revocation_enabled = True self._explicit_policy_required = False self._policy_mapping_inhibited = False self._any_policy_inhibited = False self._policy_qualifiers_rejected = True self._sig_provider = None self._target_cert_constraints = None self._initial_policies = None self._cert_path_checkers = [] self._stores = [] def getTrustAnchors(self): return self._trust_anchors def setTrustAnchors(self, trust_anchors): if isinstance(trust_anchors, set): self._trust_anchors = trust_anchors else: self._trust_anchors = set(trust_anchors) def getDate(self): return self._date def setDate(self, date): self._date = date def addCertStore(self, store): self._cert_stores.append(store) def getCertStores(self): return self._cert_stores def setCertStores(self, stores): self._cert_stores = list(stores) def isRevocationEnabled(self): return self._revocation_enabled def setRevocationEnabled(self, enabled): self._revocation_enabled = enabled def isExplicitPolicyRequired(self): return self._explicit_policy_required def setExplicitPolicyRequired(self, required): self._explicit_policy_required = required def isPolicyMappingInhibited(self): return self._policy_mapping_inhibited def setPolicyMappingInhibited(self, inhibited): self._policy_mapping_inhibited = inhibited def isAnyPolicyInhibited(self): return self._any_policy_inhibited def setAnyPolicyInhibited(self, inhibited): self._any_policy_inhibited = inhibited def getPolicyQualifiersRejected(self): return self._policy_qualifiers_rejected def setPolicyQualifiersRejected(self, rejected): self._policy_qualifiers_rejected = rejected def getSigProvider(self): return self._sig_provider def setSigProvider(self, provider): self._sig_provider = provider def getTargetCertConstraints(self): return self._target_cert_constraints def setTargetCertConstraints(self, constraints): self._target_cert_constraints = constraints def getInitialPolicies(self): return self._initial_policies def setInitialPolicies(self, policies): self._initial_policies = policies def addCertPathChecker(self, checker): self._cert_path_checkers.append(checker) def getCertPathCheckers(self): return self._cert_path_checkers def setCertPathCheckers(self, checkers): self._cert_path_checkers = list(checkers) def clone(self): return PKIXParameters(self._trust_anchors) def toString(self): return f"PKIXParameters [trust_anchors={len(self._trust_anchors)}]" class PKIXBuilderParameters(PKIXParameters): """java.security.cert.PKIXBuilderParameters""" def __init__(self, trust_anchors, target_constraints=None): super().__init__(trust_anchors) self._max_path_length = 5 if target_constraints is not None: self.setTargetCertConstraints(target_constraints) def getMaxPathLength(self): return self._max_path_length def setMaxPathLength(self, length): if length < -1: raise IllegalArgumentException("max path length must be >= -1") self._max_path_length = length def toString(self): return f"PKIXBuilderParameters [max_path={self._max_path_length}]" # ============================================================ # PKIXCertPathBuilderResult / PKIXCertPathValidatorResult # ============================================================ class PKIXCertPathBuilderResult(CertPathBuilderResult): """java.security.cert.PKIXCertPathBuilderResult""" def __init__(self, cert_path=None, trust_anchor=None, policy_tree=None, subject_public_key=None): super().__init__() self._cert_path = cert_path self._trust_anchor = trust_anchor self._policy_tree = policy_tree self._subject_public_key = subject_public_key def getCertPath(self): return self._cert_path def getTrustAnchor(self): return self._trust_anchor def getPolicyTree(self): return self._policy_tree def getPublicKey(self): return self._subject_public_key def toString(self): return f"PKIXCertPathBuilderResult [path={self._cert_path}]" class PKIXCertPathValidatorResult(CertPathValidatorResult): """java.security.cert.PKIXCertPathValidatorResult""" def __init__(self, trust_anchor=None, policy_tree=None, subject_public_key=None): super().__init__() self._trust_anchor = trust_anchor self._policy_tree = policy_tree self._subject_public_key = subject_public_key def getTrustAnchor(self): return self._trust_anchor def getPolicyTree(self): return self._policy_tree def getPublicKey(self): return self._subject_public_key def toString(self): return "PKIXCertPathValidatorResult" # ============================================================ # IllegalArgumentException (local) # ============================================================ class IllegalArgumentException(RuntimeException): """java.lang.IllegalArgumentException""" pass