CertificateExtract
Extract fields from a certificate file and return the standard context.
python · Common Scripts
Source
from typing import Any, cast import demistomock as demisto from CommonServerPython import * # noqa # pylint: disable=unused-wildcard-import from cryptography import x509 # mypy: ignore-errors from cryptography.hazmat import backends from cryptography.hazmat.primitives import asymmetric, hashes, serialization from cryptography.x509 import certificate_transparency, extensions, general_name, oid from CommonServerUserPython import * # noqa # pylint: disable=unused-wildcard-import _INSTANCE_TO_TYPE = { general_name.OtherName: "otherName", general_name.RFC822Name: "rfc822Name", general_name.DNSName: "dNSName", general_name.DirectoryName: "directoryName", general_name.UniformResourceIdentifier: "uniformResourceIdentifier", general_name.IPAddress: "iPAddress", general_name.RegisteredID: "registeredID", } _SCT_LOG_ENTRY_TYPE_NAME = { certificate_transparency.LogEntryType.PRE_CERTIFICATE: "PreCertificate", certificate_transparency.LogEntryType.X509_CERTIFICATE: "X509Certificate", } """ STANDALONE FUNCTION """ def get_indicator_from_value(indicator_value: str) -> Any: """ get_indicator_from_value function Finds an indicator in XSOAR store given a value :type value: ``str`` :param value: Indicator value :return: Indicator :rtype: ``Any`` """ try: res = demisto.executeCommand("findIndicators", {"query": f'value:"{indicator_value}" and type:Certificate'}) indicator = res[0]["Contents"][0] return indicator except BaseException: return None def oid_name(oid: oid.ObjectIdentifier) -> str: """ oid_name function Translates an oid.ObjectIdentifier into a string representation :type oid: ``oid.ObjectIdentifier`` :param oid: OID as oid.ObjectIdentifier :return: OID in dotted string format :rtype: ``str`` """ n = oid._name if n.startswith("Unknown"): return oid.dotted_string return n def repr_or_str(o: Any) -> str: """ repr_or_str function Returns a string representation of the input: - If input is bytes returns the hex representation - If input is str returns the string - If input is None returns empty string :type o: ``Any`` :param o: Input data (str or bytes) :return: String representation of the input :rtype: ``str`` """ if isinstance(o, str): return o elif isinstance(o, bytes): return o.hex() elif o is None: return "" return repr(o) def load_certificate(path: str) -> x509.Certificate: """ load_certificate function Loads a certificate from a file :type path: ``str`` :param path: File path :return: X509 Certificate parsed by cryptography.x509 :rtype: ``x509.Certificate`` """ with open(path, "rb") as f: contents = f.read() try: certificate = x509.load_pem_x509_certificate(contents, backends.default_backend()) except Exception as e: demisto.debug(f"Error loading certificate as PEM, trying with DER. Error was: {e!r}") certificate = x509.load_der_x509_certificate(contents, backends.default_backend()) return certificate def int_to_comma_hex(n: int, blength: int | None = None) -> str: """ int_to_comma_hex Translates an integer in its corresponding hex string :type n: ``int`` :param n: Input integer :type blength: ``Optional[int]`` :param blength: Add padding to reach length :return: Translated hex string :rtype: ``str`` """ bhex = f"{n:x}" if len(bhex) % 2 == 1: bhex = "0" + bhex if blength is not None: bhex = "00" * max(blength - len(bhex), 0) + bhex return ":".join([bhex[i : i + 2] for i in range(0, len(bhex), 2)]) def public_key_context( pkey: asymmetric.dsa.DSAPublicKey | asymmetric.rsa.RSAPublicKey | asymmetric.ec.EllipticCurvePublicKey | asymmetric.ed25519.Ed25519PublicKey | asymmetric.ed448.Ed448PublicKey, ) -> Common.CertificatePublicKey: """ public_key_context function Translates an X509 certificate Public Key into a Common.CertificatePublicKey object :type pkey: ``Union[asymmetric.dsa.DSAPublicKey, asymmetric.rsa.RSAPublicKey, asymmetric.ec.EllipticCurvePublicKey, \ asymmetric.ed25519.Ed25519PublicKey, asymmetric.ed448.Ed448PublicKey]`` :param pkey: Certificate Public Key :return: Certificate Public Key represented as a Common.CertificatePublicKey object :rtype: ``Common.CertificatePublicKey`` """ if isinstance(pkey, asymmetric.dsa.DSAPublicKey): return Common.CertificatePublicKey( algorithm=Common.CertificatePublicKey.Algorithm.DSA, length=pkey.key_size, publickey=int_to_comma_hex(pkey.public_numbers().y), p=int_to_comma_hex(pkey.public_numbers().parameter_numbers.p), q=int_to_comma_hex(pkey.public_numbers().parameter_numbers.q), g=int_to_comma_hex(pkey.public_numbers().parameter_numbers.g), ) elif isinstance(pkey, asymmetric.rsa.RSAPublicKey): return Common.CertificatePublicKey( algorithm=Common.CertificatePublicKey.Algorithm.RSA, length=pkey.key_size, modulus=int_to_comma_hex(pkey.public_numbers().n), exponent=pkey.public_numbers().e, ) elif isinstance(pkey, asymmetric.ec.EllipticCurvePublicKey): return Common.CertificatePublicKey( algorithm=Common.CertificatePublicKey.Algorithm.EC, length=pkey.key_size, x=int_to_comma_hex(pkey.public_numbers().x), y=int_to_comma_hex(pkey.public_numbers().y), curve=pkey.curve.name, ) return Common.CertificatePublicKey( algorithm=Common.CertificatePublicKey.Algorithm.UNKNOWN, length=0, publickey=pkey.public_bytes(encoding=serialization.Encoding.Raw, format=serialization.PublicFormat.Raw).hex(), ) def map_gn(gn: Any) -> Common.GeneralName: """ map_gn function Check whether the provided General Name is a compatible type and maps it to a Common.GeneralName class :type gn: ``Any`` :param gn: General name to be checked :return: General Name mapped to a Common.GeneralName class :rtype: ``Common.GeneralName`` """ if gn is None: raise ValueError("gn cannot be None") itype = next((t for t in _INSTANCE_TO_TYPE if isinstance(gn, t)), None) if itype is not None: return Common.GeneralName(gn_type=_INSTANCE_TO_TYPE[itype], gn_value=str(gn.value)) raise ValueError("general name must be a valid type") def extension_context(oid: str, extension_name: str, critical: bool, extension_value: Any) -> Common.CertificateExtension: """ extension_context function Translates an X509 certificate extension into a Common.CertificateExtension object :type oid: ``str`` :param oid: Certificate Extension OID :type extension_name: ``str`` :param extension_name: Name of the Extension :type critical: ``bool`` :param critical: Whether the Extension is marked as critical :type extension_value: ``Any`` :param extension_value: Value of the extension (parsed from cryptograph module) :return: Extension represented as a Common.CertificateExtension object :rtype: ``Common.CertificateExtension`` """ if isinstance(extension_value, extensions.SubjectAlternativeName): return Common.CertificateExtension( extension_type=Common.CertificateExtension.ExtensionType.SUBJECTALTERNATIVENAME, oid=oid, extension_name=extension_name, critical=critical, subject_alternative_names=[ Common.CertificateExtension.SubjectAlternativeName(gn=map_gn(gn)) for gn in extension_value._general_names if gn is not None ], ) elif isinstance(extension_value, extensions.AuthorityKeyIdentifier): authority_key_identifier = Common.CertificateExtension.AuthorityKeyIdentifier( issuer=[map_gn(n) for n in list(extension_value.authority_cert_issuer)] if (extension_value.authority_cert_issuer) else None, serial_number=extension_value.authority_cert_serial_number, # type: ignore key_identifier=extension_value.key_identifier.hex(), # type: ignore ) return Common.CertificateExtension( extension_type=Common.CertificateExtension.ExtensionType.AUTHORITYKEYIDENTIFIER, oid=oid, extension_name=extension_name, critical=critical, authority_key_identifier=authority_key_identifier, ) elif isinstance(extension_value, extensions.SubjectKeyIdentifier): return Common.CertificateExtension( extension_type=Common.CertificateExtension.ExtensionType.SUBJECTKEYIDENTIFIER, oid=oid, extension_name=extension_name, critical=critical, digest=extension_value.digest.hex(), ) elif isinstance(extension_value, extensions.KeyUsage): return Common.CertificateExtension( extension_type=Common.CertificateExtension.ExtensionType.KEYUSAGE, oid=oid, extension_name=extension_name, critical=critical, digital_signature=extension_value.digital_signature, content_commitment=extension_value.content_commitment, key_encipherment=extension_value.key_encipherment, data_encipherment=extension_value.data_encipherment, key_agreement=extension_value.key_agreement, key_cert_sign=extension_value.key_cert_sign, crl_sign=extension_value.crl_sign, ) elif isinstance(extension_value, extensions.ExtendedKeyUsage): return Common.CertificateExtension( extension_type=Common.CertificateExtension.ExtensionType.EXTENDEDKEYUSAGE, oid=oid, extension_name=extension_name, critical=critical, usages=[oid_name(o) for o in extension_value], ) elif isinstance(extension_value, extensions.CRLDistributionPoints): distribution_points: list[Common.CertificateExtension.DistributionPoint] = [] dp: extensions.DistributionPoint for dp in extension_value: distribution_points.append( Common.CertificateExtension.DistributionPoint( full_name=None if dp.full_name is None else [map_gn(fn) for fn in list(dp.full_name)], relative_name=None if dp.relative_name is None else dp.relative_name.rfc4514_string(), crl_issuer=None if dp.crl_issuer is None else [map_gn(ci) for ci in list(dp.crl_issuer)], reasons=None if dp.reasons is None else [repr_or_str(r) for r in dp.reasons], ) ) return Common.CertificateExtension( extension_type=Common.CertificateExtension.ExtensionType.CRLDISTRIBUTIONPOINTS, oid=oid, extension_name=extension_name, critical=critical, distribution_points=distribution_points, ) elif isinstance(extension_value, extensions.CertificatePolicies): policies: list[Common.CertificateExtension.CertificatePolicy] = [] p: extensions.PolicyInformation for p in extension_value: policies.append( Common.CertificateExtension.CertificatePolicy( policy_identifier=oid_name(p.policy_identifier), policy_qualifiers=None if not p.policy_qualifiers else [repr_or_str(pq) for pq in p.policy_qualifiers], ) ) return Common.CertificateExtension( extension_type=Common.CertificateExtension.ExtensionType.CERTIFICATEPOLICIES, oid=oid, extension_name=extension_name, critical=critical, certificate_policies=policies, ) elif isinstance(extension_value, extensions.AuthorityInformationAccess): descriptions: list[Common.CertificateExtension.AuthorityInformationAccess] = [] d: extensions.AccessDescription for d in extension_value: descriptions.append( Common.CertificateExtension.AuthorityInformationAccess( access_method=oid_name(d.access_method), access_location=map_gn(d.access_location) ) ) return Common.CertificateExtension( extension_type=Common.CertificateExtension.ExtensionType.AUTHORITYINFORMATIONACCESS, oid=oid, extension_name=extension_name, critical=critical, authority_information_access=descriptions, ) elif isinstance(extension_value, extensions.BasicConstraints): return Common.CertificateExtension( extension_type=Common.CertificateExtension.ExtensionType.BASICCONSTRAINTS, oid=oid, extension_name=extension_name, critical=critical, basic_constraints=Common.CertificateExtension.BasicConstraints( ca=extension_value.ca, path_length=None if extension_value.path_length is None else extension_value.path_length ), ) elif isinstance(extension_value, extensions.PrecertificateSignedCertificateTimestamps): presigcerttimestamps: list[Common.CertificateExtension.SignedCertificateTimestamp] = [] presct: extensions.SignedCertificateTimestamp for presct in extension_value: presigcerttimestamps.append( Common.CertificateExtension.SignedCertificateTimestamp( entry_type=_SCT_LOG_ENTRY_TYPE_NAME.get(presct.entry_type, presct.entry_type.value), # type: ignore version=presct.version.value, log_id=presct.log_id.hex(), timestamp=presct.timestamp.strftime("%Y-%m-%dT%H:%M:%S.000Z"), ) ) return Common.CertificateExtension( extension_type=Common.CertificateExtension.ExtensionType.PRESIGNEDCERTIFICATETIMESTAMPS, oid=oid, extension_name=extension_name, critical=critical, signed_certificate_timestamps=presigcerttimestamps, ) elif isinstance(extension_value, extensions.SignedCertificateTimestamps): sigcerttimestamps: list[Common.CertificateExtension.SignedCertificateTimestamp] = [] sct: extensions.SignedCertificateTimestamp for sct in extension_value: sigcerttimestamps.append( Common.CertificateExtension.SignedCertificateTimestamp( entry_type=_SCT_LOG_ENTRY_TYPE_NAME.get(sct.entry_type, sct.entry_type.value), # type: ignore version=sct.version.value, log_id=sct.log_id.hex(), timestamp=sct.timestamp.strftime("%Y-%m-%dT%H:%M:%S.000Z"), ) ) return Common.CertificateExtension( extension_type=Common.CertificateExtension.ExtensionType.SIGNEDCERTIFICATETIMESTAMPS, oid=oid, extension_name=extension_name, critical=critical, signed_certificate_timestamps=sigcerttimestamps, ) return Common.CertificateExtension( extension_type=Common.CertificateExtension.ExtensionType.OTHER, oid=oid, extension_name=extension_name, critical=critical, value=repr(extension_value), ) def certificate_to_context(certificate: x509.Certificate) -> Common.Certificate: """ certificate_to_context function Translates an X509 certificate into a Common.Certificate object :type certificate: ``x509.Certificate`` :param oid: Certificate Extension OID :return: Certificate represented as a Common.Certificate object :rtype: ``Common.Certificate`` """ spkisha256 = hashes.Hash(hashes.SHA256(), backends.default_backend()) spkisha256.update( certificate.public_key().public_bytes( encoding=serialization.Encoding.DER, format=serialization.PublicFormat.SubjectPublicKeyInfo ) ) extensions_contexts: list[Common.CertificateExtension] = [] for extension in certificate.extensions: extension_oid = cast(oid.ObjectIdentifier, extension.oid) extensions_contexts.append( extension_context( oid=extension_oid.dotted_string, extension_name=extension_oid._name, critical=extension.critical, extension_value=extension.value, ) ) indicator = certificate.fingerprint(hashes.SHA256()).hex() cert = Common.Certificate( subject_dn=certificate.subject.rfc4514_string(), issuer_dn=certificate.issuer.rfc4514_string(), serial_number=str(certificate.serial_number), validity_not_before=certificate.not_valid_before.strftime("%Y-%m-%dT%H:%M:%S.000Z"), validity_not_after=certificate.not_valid_after.strftime("%Y-%m-%dT%H:%M:%S.000Z"), sha256=certificate.fingerprint(hashes.SHA256()).hex(), sha1=certificate.fingerprint(hashes.SHA1()).hex(), md5=certificate.fingerprint(hashes.MD5()).hex(), spki_sha256=spkisha256.finalize().hex(), extensions=extensions_contexts, signature_algorithm=certificate.signature_hash_algorithm.name, # type: ignore[union-attr] signature=certificate.signature.hex(), publickey=public_key_context(certificate.public_key()), # type: ignore dbot_score=Common.DBotScore( indicator=indicator, indicator_type=DBotScoreType.CERTIFICATE, integration_name="X509Certificate", score=Common.DBotScore.NONE, ), pem=certificate.public_bytes(serialization.Encoding.PEM).decode("ascii"), ) return cert """ COMMAND FUNCTION """ def certificate_extract_command(args: dict[str, Any]) -> CommandResults: pem: str | None = args.get("pem") entry_id: str | None = args.get("entry_id") if pem is None and entry_id is None: raise ValueError("You should specify pem or entry_id") if pem is not None and entry_id is not None: raise ValueError("Only one of pem and entry_id should be specified") certificate: x509.Certificate if entry_id is not None: res_path = demisto.getFilePath(entry_id) if not res_path: raise ValueError("Invalid entry_id - not found") entry_id_path = res_path["path"] certificate = load_certificate(entry_id_path) if pem is not None: certificate = x509.load_pem_x509_certificate(pem.encode("ascii"), backends.default_backend()) standard_context = certificate_to_context(certificate) readable_output = "Certificate decoded" return CommandResults(readable_output=readable_output, outputs=None, indicator=standard_context, ignore_auto_extract=True) """ MAIN FUNCTION """ def main(): try: return_results(certificate_extract_command(demisto.args())) except Exception as ex: return_error(f"Failed to execute CertificateExtract. Error: {ex!s}") """ ENTRY POINT """ if __name__ in ("__main__", "__builtin__", "builtins"): main()
README
Extract fields from a certificate file and return the standard context
Script Data
| Name | Description |
|---|---|
| Script Type | python3 |
| Tags | |
| Cortex XSOAR Version | 6.0.0 |
Inputs
| Argument Name | Description |
|---|---|
| pem | Certificate in PEM format |
| entry_id | Certificate entry ID (in DER or PEM format) |
Outputs
| Path | Description | Type |
|---|---|---|
| Certificate.Name | Name (CN or SAN) appearing in the certificate. | String |
| Certificate.SubjectDN | The Subject Distinguished Name of the certificate. This field includes the Common Name of the certificate. |
String |
| Certificate.PEM | Certificate in PEM format. | String |
| Certificate.IssuerDN | The Issuer Distinguished Name of the certificate. | String |
| Certificate.SerialNumber | The Serial Number of the certificate. | String |
| Certificate.ValidityNotAfter | End of certificate validity period. | Date |
| Certificate.ValidityNotBefore | Start of certificate validity period. | Date |
| Certificate.SubjectAlternativeName.Type | Type of the SAN. | String |
| Certificate.SubjectAlternativeName.Value | Name of the SAN. | String |
| Certificate.SHA512 | SHA512 Fingerprint of the certificate in DER format. | String |
| Certificate.SHA256 | SHA256 Fingerprint of the certificate in DER format. | String |
| Certificate.SHA1 | SHA1 Fingerprint of the certificate in DER format. | String |
| Certificate.MD5 | MD5 Fingerprint of the certificate in DER format. | String |
| Certificate.PublicKey.Algorithm | Algorithm used for public key of the certificate. | String |
| Certificate.PublicKey.Length | Length in bits of the public key of the certificate. | Number |
| Certificate.PublicKey.Modulus | Modulus of the public key for RSA keys. | String |
| Certificate.PublicKey.Exponent | Exponent of the public key for RSA keys. | Number |
| Certificate.PublicKey.PublicKey | The public key for DSA/Unknown keys. | String |
| Certificate.PublicKey.P | The P parameter for DSA keys. | String |
| Certificate.PublicKey.Q | The Q parameter for DSA keys. | String |
| Certificate.PublicKey.G | The G parameter for DSA keys. | String |
| Certificate.PublicKey.X | The X parameter for EC keys. | String |
| Certificate.PublicKey.Y | The Y parameter for EC keys. | String |
| Certificate.PublicKey.Curve | Curve of the Public Key for EC keys. | String |
| Certificate.SPKISHA256 | SHA256 fingerprint of the certificate Subject Public Key Info. | String |
| Certificate.Signature.Algorithm | Algorithm used in the signature of the certificate. | String |
| Certificate.Signature.Signature | Signature of the certificate. | String |
| Certificate.Extension.Critical | Critical flag of the certificate extension. | Bool |
| Certificate.Extension.OID | OID of the certificate extension. | String |
| Certificate.Extension.Name | Name of the certificate extension. | String |
| Certificate.Extension.Value | Value of the certificate extension. | Unknown |
| Certificate.Malicious.Vendor | The vendor that reported the file as malicious. | String |
| Certificate.Malicious.Description | A description explaining why the file was determined to be malicious. | String |
| DBotScore.Indicator | The indicator that was tested. | String |
| DBotScore.Type | The indicator type. | String |
| DBotScore.Vendor | The vendor used to calculate the score. | String |
| DBotScore.Score | The actual score. | Number |
Script Example
!CertificateExtract entry_id="978@5b925e3c-6ab8-4209-86bf-10f4ed6a9dc0"
Context Example
{
"Certificate": {
"Extension": [
{
"Critical": true,
"Name": "basicConstraints",
"OID": "2.5.29.19",
"Value": {
"CA": false
}
},
{
"Critical": false,
"Name": "subjectKeyIdentifier",
"OID": "2.5.29.14",
"Value": {
"Digest": "3fe12ea63b9cf8414f0b001f2efa8ac5bd0fc73c"
}
},
{
"Critical": false,
"Name": "keyUsage",
"OID": "2.5.29.15",
"Value": {
"DataEncipherment": true,
"DigitalSignature": true,
"KeyAgreement": true,
"KeyEncipherment": true
}
},
{
"Critical": false,
"Name": "extendedKeyUsage",
"OID": "2.5.29.37",
"Value": {
"Usages": [
"clientAuth"
]
}
},
{
"Critical": false,
"Name": "subjectAltName",
"OID": "2.5.29.17",
"Value": [
{
"Type": "dNSName",
"Value": "*.example.com"
}
]
}
],
"IssuerDN": "CN=TestCA,OU=CA,O=Example.com,L=Casacca,ST=PR,C=IT",
"MD5": "ac2fead0b8ac25a3633194b38ad91ca9",
"Name": [
"*.example.com",
"IAmADVCertificate"
],
"PEM": "-----BEGIN CERTIFICATE-----\nMIIDzjCCAbagAwIBAgIIXAVHw/CcpwowDQYJKoZIhvcNAQELBQAwYDELMAkGA1UE\nBhMCSVQxCzAJBgNVBAgTAlBSMRAwDgYDVQQHEwdDYXNhY2NhMRQwEgYDVQQKEwtF\neGFtcGxlLmNvbTELMAkGA1UECxMCQ0ExDzANBgNVBAMTBlRlc3RDQTAeFw0yNjEy\nMDIxNDQxMDBaFw0yMTEyMDIxNDQxMDBaMBwxGjAYBgNVBAMTEUlBbUFEVkNlcnRp\nZmljYXRlMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEfWq17YxZZuf/jPU/to3HRumn\nv8/LgZQSwkKUNdXs6niQYplCHTGQW1g062EtrhDhrWXYDIR1wxxt139y+z3hs9KP\ngThaIkJNjFx8dVklvIWx16c6t4cujZSVr6/08TLOo34wfDAMBgNVHRMBAf8EAjAA\nMB0GA1UdDgQWBBQ/4S6mO5z4QU8LAB8u+orFvQ/HPDALBgNVHQ8EBAMCA7gwEwYD\nVR0lBAwwCgYIKwYBBQUHAwIwGAYDVR0RBBEwD4INKi5leGFtcGxlLmNvbTARBglg\nhkgBhvhCAQEEBAMCBaAwDQYJKoZIhvcNAQELBQADggIBAAEhwtW+srmNaTs1krrt\nxybcF23jDNzRv/2G91PHf0CxFq7BjHYYzF3CvvwaQfTXMKog6j5arenuKgLEPpO9\navXiAcPt7vy3bxqX8WP4xgjoaRcEglS0cwW7bc+wtQT2NzqCsiXqNeRSiHXanNLY\nBGOayOnulnWP9vuAHNhgTDgxvMphxNDYtY9MA1Qj+Bs0jIuRHdFWBTVXvPYaMr4/\nbtzhrJY7VeS47IXDyp9KZbczy+5LUSh7AdKjXOI/kG8MUlKvfw/Vy23rDIOwb/dM\n/PWnqkbTFZI6cBl5FxWh2i/MaYUvjaynS/6A1fZIsgnq9mcCO/Auzaw8pa4Zx55w\nnf5hHBtp/Ksc+0ayPgYmfYKNGYvu/DQW3gvMAigYYaLAIrykYbkDl7mmQgL9lBIT\nBpBN72+ho1oZWb7F8YrbPa4odu2PBxO8kuleQKMfW73rQVF9BWUoxk8oDdHFkeye\nA+saBni5EZyYyLDMJRB2R9h/6mC02JkCRceHf7STNxiTvHwew8eP7mTNfmyTJDND\nEsGgwQpK6w0ki3/kQ3pD8rFUtpnA3AqjB0BON6j+lSpyPx/2HvGSvSx3aT2B6apC\nnoZV/cVfp9txXt1CkRt3zLpdzbQWTrRUiL+L2EaLeHPd901NZG0voxVUP64TuouB\nSIzBSFl5/q4tqkY4D2Gv4gPX\n-----END CERTIFICATE-----\n",
"PublicKey": {
"Algorithm": "EC",
"Curve": "secp384r1",
"Length": 384,
"X": "7d:6a:b5:ed:8c:59:66:e7:ff:8c:f5:3f:b6:8d:c7:46:e9:a7:bf:cf:cb:81:94:12:c2:42:94:35:d5:ec:ea:78:90:62:99:42:1d:31:90:5b:58:34:eb:61:2d:ae:10:e1",
"Y": "ad:65:d8:0c:84:75:c3:1c:6d:d7:7f:72:fb:3d:e1:b3:d2:8f:81:38:5a:22:42:4d:8c:5c:7c:75:59:25:bc:85:b1:d7:a7:3a:b7:87:2e:8d:94:95:af:af:f4:f1:32:ce"
},
"SHA1": "18ac1daece43f5b769260adbabf763046ebda80e",
"SHA256": "869c151a7174f95a35b58c7aa900da5daed3723b63a31f08b89edd788653e402",
"SPKISHA256": "f2d670d5c0e7e3ba2fb928dc2533c0191a679170acd7dc9387130173492e4b18",
"SerialNumber": "6630784933253916426",
"Signature": {
"Algorithm": "sha256",
"Signature": "0121c2d5beb2b98d693b3592baedc726dc176de30cdcd1bffd86f753c77f40b116aec18c7618cc5dc2befc1a41f4d730aa20ea3e5aade9ee2a02c43e93bd6af5e201c3edeefcb76f1a97f163f8c608e86917048254b47305bb6dcfb0b504f6373a82b225ea35e4528875da9cd2d804639ac8e9ee96758ff6fb801cd8604c3831bcca61c4d0d8b58f4c035423f81b348c8b911dd156053557bcf61a32be3f6edce1ac963b55e4b8ec85c3ca9f4a65b733cbee4b51287b01d2a35ce23f906f0c5252af7f0fd5cb6deb0c83b06ff74cfcf5a7aa46d315923a7019791715a1da2fcc69852f8daca74bfe80d5f648b209eaf667023bf02ecdac3ca5ae19c79e709dfe611c1b69fcab1cfb46b23e06267d828d198beefc3416de0bcc02281861a2c022bca461b90397b9a64202fd94121306904def6fa1a35a1959bec5f18adb3dae2876ed8f0713bc92e95e40a31f5bbdeb41517d056528c64f280dd1c591ec9e03eb1a0678b9119c98c8b0cc25107647d87fea60b4d8990245c7877fb493371893bc7c1ec3c78fee64cd7e6c9324334312c1a0c10a4aeb0d248b7fe4437a43f2b154b699c0dc0aa307404e37a8fe952a723f1ff61ef192bd2c77693d81e9aa429e8655fdc55fa7db715edd42911b77ccba5dcdb4164eb45488bf8bd8468b7873ddf74d4d646d2fa315543fae13ba8b81488cc1485979feae2daa46380f61afe203d7"
},
"SubjectAlternativeName": [
{
"Type": "dNSName",
"Value": "*.example.com"
}
],
"SubjectDN": "CN=IAmADVCertificate",
"ValidityNotAfter": "2021-12-02T14:41:00.000Z",
"ValidityNotBefore": "2026-12-02T14:41:00.000Z"
},
"DBotScore": {
"Indicator": "869c151a7174f95a35b58c7aa900da5daed3723b63a31f08b89edd788653e402",
"Score": 0,
"Type": "certificate",
"Vendor": "X509Certificate"
}
}
Human Readable Output
Certificate decoded