Authenticode

The Authenticode support of Signify allows you to easily verify a PE or MSI File’s Authenticode signature:

with open("file.exe", "rb") as f:
    signed_file = AuthenticodeFile.detect(f)
    signed_file.verify()

This method will raise an error if it is invalid. A simpler API is also available, allowing you to interpret the error if one happens:

with open("file.exe", "rb") as f:
    signed_file = AuthenticodeFile.detect(f)
    status, err = signed_file.explain_verify()

if status != AuthenticodeVerificationResult.OK:
    print(f"Invalid: {err}")

If you need to get more information about the signature, you can use this:

with open("file.exe", "rb") as f:
    pefile = SignedPEFile(f)
    for signed_data in pefile.signed_datas:
        print(signed_data.signer_info.program_name)
        if signed_data.signer_info.countersigner is not None:
            print(signed_data.signer_info.countersigner.signing_time)

A more thorough example is available in the examples directory of the Signify repository.

Note that the file must remain open as long as not all SignedData objects have been parsed or verified.

Authenticode overview

Most of the specification of Authenticode is properly documented in a 2008 paper Windows Authenticode Portable Executable Signature Format and still available to download. The specification mostly follows the PKCS#7: SignedData and SignerInfo specification, although most structures have since been updated in more recent RFCs. Of particular note is that the specification defines various “must” and “must not” phrases, which has not been adhered to in more recent uses.

At its core, it defines how the certificate table of a PE file (a normal Windows executable) contains PKCS#7 SignedData objects. Note that the specification allows for multiple of such objects, perhaps including other signers or signatures.

Authenticode SignedData objects contain SpcIndirectDataContent contents (microsoft_spc_indirect_data_content, OID 1.3.6.1.4.1.311.2.1.4), which (amongst others) define the hash of the PE file. The PE file is hashed particularly, as we need to skip the PE file checksum, the pointer to the certificate table in the data directory, and the certificate table itself.

The signature is valid, in principle, if the hash we calculate is the same as in SpcIndirectDataContent, and the SignerInfo contains a hash over this content.

See also

There are various other projects that also deal with Authenticode, which also provide useful insights. These include:

Other useful references include:

Additional gotcha’s

There are a few additional gotcha’s when verifying Authenticode signatures, which are not very well defined in the original specification, but we have been able to reverse-engineer or otherwise use to our advantage.

RFC3161 countersignatures

There are two types of countersignature: a regular countersignature, as used in PKCS#7, or a nested Time-Stamp Protocol response (RFC3161). This response, available as unauthenticated attribute with microsoft_time_stamp_token (OID 1.3.6.1.4.1.311.3.3.1), is added as nested authenticode.pkcs7.SignedData object.

This is transparently handled by the AuthenticodeSignedData.countersigner attribute, but note that this attribute can return two different types.

Nested signatures

Instead of adding multiple signatures to the certificate table, SignedData objects can also be nested in others as unauthenticated attributes with microsoft_nested_signature (OID 1.3.6.1.4.1.311.2.4.1).

This is transparently handled by the SignedPEFile class.

Page hashes

The SpcIndirectDataContent class may contain a binary structure that defines hashes for portions of the file (in the SpcLink.moniker field). If this is the case, the moniker will use class ID a6b586d5-b4a1-2466-ae05-a217da8e60d6, and its serialized data will contain another SpcAttributeTypeAndOptionalValue with OIDs microsoft_spc_pe_image_page_hashes_v1 (1.3.6.1.4.1.311.2.3.1) for SHA-1 or microsoft_spc_pe_image_page_hashes_v2 (1.3.6.1.4.1.311.2.3.2) for SHA-256.

The value will be a binary structure that describes offsets (4 bytes integer) and hash digest (digest length of the algorithm) of parts of the binary. These offsets appear to be relative to the entire file, and the final offset is always at the end of the file (describing the end of the previous hash), and the final hash is ignored:

0000000  08d88d96cb3fddf7a7c73598e95388ce60432c2c5ff17b8c558ce599645db73e
0001024  5ebe1d0255524e4291105759b80abad8294e269e3e11fce76ed6b2e005a79df0
0005120  255d7a5768ac44963184e0b5281d64fd9282f953211d03fd49a3d8190044dc35
...
1436160  35c36ac4c657e82cc3aa1311373c1b17552780f64e000a2c31742125365145cd
1438720  0000000000000000000000000000000000000000000000000000000000000000

Each hash is then calculated between the two defined offsets, using the same omissions as for normal Authenticode validation. The hashes are filled with NULL bytes when the hash would be shorter than the page size (typically 4096), ignoring omissions.

In the example above, for the first hash, we would calculate the hash over the first 1024 bytes of the PE file, skipping the checksum and table locations located in the PE header file, and then add 3072 NULL bytes to complete a full PE page. Note that the actual digest is calculated over less than 4096 bytes due to the omissions.

Additional attributes, extensions

Some attributes are present on SignerInfo objects that have additional meanings:

microsoft_spc_sp_opus_info (1.3.6.1.4.1.311.2.1.12)

Contains the program name and URL

microsoft_spc_statement_type (1.3.6.1.4.1.311.2.1.11)

Defines that the key purpose is individual (1.3.6.1.4.1.311.2.1.21) or commercial (1.3.6.1.4.1.311.2.1.22), but unused in practice.

microsoft_spc_relaxed_pe_marker_check (1.3.6.1.4.1.311.2.6.1)

Purpose unknown

microsoft_platform_manifest_binary_id (1.3.6.1.4.1.311.10.3.28)

Purpose unknown

For certificates, these extensions are known:

microsoft_spc_sp_agency_info (1.3.6.1.4.1.311.2.1.10)

Purpose unknown

microsoft_spc_financial_criteria (1.3.6.1.4.1.311.2.1.27)

Purpose unknown

The following key purpose is relevant for Authenticode:

microsoft_lifetime_signing (1.3.6.1.4.1.311.10.3.13)

The certificate is only valid for it’s lifetime, and cannot be extend with a counter signature.

All these attributes and extensions are defined in the ASN.1 spec of this library, but not all of them are used.

Future work:

  • 1.3.6.1.4.1.311.2.5.1 (enhanced_hash)

Authenticode-signed File Objects

To support both PE and MSI files, a generic interface exists. When you call AuthenticodeFile.detect(), either a SignedPeFile or SignedMsiFile will be returned, both implementing the same interface. This generic interface allows access to zero or more AuthenticodeSignedData objects, and allows validation of the signature.

class signify.authenticode.AuthenticodeFile

An Authenticode-signed file that is to be parsed to find the relevant sections for Authenticode parsing.

classmethod detect(file_obj: BinaryIO) AuthenticodeFile

This initializer will return either SignedMsiFile or SignedPEFile, and otherwise throw an error.

explain_verify(*args: Any, **kwargs: Any) tuple[AuthenticodeVerificationResult, Exception | None]

This will return a value indicating the signature status of this PE file. This will not raise an error when the verification fails, but rather indicate this through the resulting enum

Return type:

(signify.authenticode.AuthenticodeVerificationResult, Exception)

Returns:

The verification result, and the exception containing more details (if available or None)

get_fingerprint(digest_algorithm: HashFunction) bytes

Gets the fingerprint for this file

iter_signed_datas(*, include_nested: bool = True, ignore_parse_errors: bool = True) Iterator[AuthenticodeSignedData]

Returns an iterator over AuthenticodeSignedData objects relevant for this Authenticode-signed file.

Parameters:
  • include_nested – Boolean, if True, will also iterate over all nested SignedData structures

  • ignore_parse_errors

    Indicates how to handle ParseError that may be raised while fetching embedded AuthenticodeSignedData structures.

    When True, which is the default and seems to be how Windows handles this as well, this will fetch as many valid AuthenticodeSignedData structures until an exception occurs.

    Note that this will also silence the ParseError that occurs when there’s no valid AuthenticodeSignedData to fetch.

    When False, this will raise the ParseError as soon as one occurs.

Raises:
  • ParseError – For parse errors in the signed file

  • signify.authenticode.AuthenticodeParseError – For parse errors in the SignedData

Returns:

iterator of signify.authenticode.SignedData

property signed_datas: Iterator[AuthenticodeSignedData]

Returns an iterator over AuthenticodeSignedData objects relevant for this file. See iter_signed_datas()

verify(*, multi_verify_mode: Literal['any', 'first', 'all', 'best'] = 'any', expected_hashes: dict[str, bytes] | None = None, ignore_parse_errors: bool = True, **kwargs: Any) list[tuple[AuthenticodeSignedData, Iterable[list[Certificate]]]]

Verifies the SignedData structures. This is a little bit more efficient than calling all verify-methods separately.

Parameters:
  • expected_hashes – When provided, should be a mapping of hash names to digests. This could speed up the verification process.

  • multi_verify_mode

    Indicates how to verify when there are multiple AuthenticodeSignedData objects in this file. Can be:

    • ’any’ (default) to indicate that any of the signatures must validate correctly.

    • ’first’ to indicate that the first signature must verify correctly (the default of tools such as sigcheck.exe)

    • ’all’ to indicate that all signatures must verify

    • ’best’ to indicate that the signature using the best hashing algorithm must verify (e.g. if both SHA-1 and SHA-256 are present, only SHA-256 is checked); if multiple signatures exist with the same algorithm, any may verify

    This argument has no effect when only one signature is present.

  • ignore_parse_errors

    Indicates how to handle ParseError that may be raised during parsing of the signed file’s certificate table.

    When True, which is the default and seems to be how Windows handles this as well, this will verify based on all available AuthenticodeSignedData before a parse error occurs.

    AuthenticodeNotSignedError will be raised when no valid AuthenticodeSignedData exists.

    When False, this will raise the ParseError as soon as one occurs. This often occurs before AuthenticodeNotSignedError is potentially raised.

Returns:

the used structure(s) in validation, as a list of tuples, in the form (signed data object, certificate chain)

Raises:
  • AuthenticodeVerificationError – when the verification failed

  • ParseError – for parse errors in the signed file

verify_additional_hashes(signed_data: AuthenticodeSignedData) None

Verifies additional hashes that may be present in the AuthenticodeSignedData referencing this data. Return None when the verification succeeds, or raises an error otherwise.

The default implementation is to do nothing.

class signify.authenticode.AuthenticodeVerificationResult(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)

This represents the result of an Authenticode verification. If everything is OK, it will equal to AuthenticodeVerificationResult.OK, otherwise one of the other enum items will be returned. Remember that onl the first exception is processed - there may be more wrong.

CERTIFICATE_ERROR = 6

An error occurred during the processing of a certificate (e.g. during chain building), or when verifying the certificate’s signature.

COUNTERSIGNER_ERROR = 9

Something went wrong when verifying the countersignature.

INCONSISTENT_DIGEST_ALGORITHM = 7

A highly specific error raised when different digest algorithms are used in SignedData, SpcInfo or SignerInfo.

INVALID_ADDITIONAL_HASH = 10

The additional file hash, such as the page hash for PE files, or the extended digest for MSI files, does not match the calculated hash.

INVALID_DIGEST = 8

The verified digest does not match the calculated digest of the file. This is a tell-tale sign that the file may have been tampered with.

NOT_SIGNED = 2

The provided PE file is not signed.

OK = 1

The signature is valid.

PARSE_ERROR = 3

The Authenticode signature could not be parsed.

UNKNOWN_ERROR = 5

An unknown error occurred during parsing or verifying.

VERIFY_ERROR = 4

The Authenticode signature could not be verified. This is a more generic error than other possible statuses and is used as a catch-all.

Signed PE File

This class is used for the verification of PE files.

class signify.authenticode.SignedPEFile(file_obj: BinaryIO)
__init__(file_obj: BinaryIO)

A PE file that is to be parsed to find the relevant sections for Authenticode parsing.

Parameters:

file_obj – A PE file opened in binary file

get_authenticode_omit_sections() dict[str, RelRange] | None

Returns all ranges of the raw file that are relevant for exclusion for the calculation of the hash function used in Authenticode.

The relevant sections are (as per http://download.microsoft.com/download/9/c/5/9c5b2167-8017-4bae-9fde-d599bac8184a/Authenticode_PE.docx, chapter Calculating the PE Image Hash):

  • The location of the checksum

  • The location of the entry of the Certificate Table in the Data Directory

  • The location of the Certificate Table.

Returns:

dict if successful, or None if not successful

get_fingerprint(digest_algorithm: HashFunction, start: int = 0, end: int = -1, aligned: bool = False) bytes

Gets the fingerprint for this file, with the provided start and end, and optionally aligned to the PE file’s alignment.

get_fingerprinter() SignedPEFingerprinter

Returns a fingerprinter object for this file.

Return type:

signify.fingerprinter.SignedPEFingerprinter

iter_signed_datas(*, include_nested: bool = True, ignore_parse_errors: bool = True) Iterator[AuthenticodeSignedData]

Returns an iterator over AuthenticodeSignedData objects relevant for this Authenticode-signed file.

Parameters:
  • include_nested – Boolean, if True, will also iterate over all nested SignedData structures

  • ignore_parse_errors

    Indicates how to handle ParseError that may be raised while fetching embedded AuthenticodeSignedData structures.

    When True, which is the default and seems to be how Windows handles this as well, this will fetch as many valid AuthenticodeSignedData structures until an exception occurs.

    Note that this will also silence the ParseError that occurs when there’s no valid AuthenticodeSignedData to fetch.

    When False, this will raise the ParseError as soon as one occurs.

Raises:
  • ParseError – For parse errors in the signed file

  • signify.authenticode.AuthenticodeParseError – For parse errors in the SignedData

Returns:

iterator of signify.authenticode.SignedData

property page_size: int

Gets the page size from the optional COFF header, or if not available, returns 4096 as best guess.

verify_additional_hashes(signed_data: AuthenticodeSignedData) None

Verifies the page hashes (if available) in the SpcPeImageData field.

class signify.authenticode.SignedPEFingerprinter(file_obj: BinaryIO, block_size: int = 1000000)

An extension of the Fingerprinter class that enables the calculation of authentihashes of PE Files.

add_signed_pe_hashers(*hashers: HashFunction, start: int = 0, end: int = -1, block_size: int | None = None) bool

Specialized method of add_hashers() to add hashers with ranges limited to those that are needed to calculate the hash of signed PE Files.

Signed MSI File

This class is used for the verification of MSI files.

Signed Data File

This class is used for the verification of simple P7X files with Authenticode signatures.

PKCS7 objects

To help understand the specific SignedData and SignerInfo objects, the following graph may help:

http://yuml.me/f68f2b83.svg
class signify.authenticode.AuthenticodeSignedData(asn1: cms.SignedData, signed_file: signed_file.AuthenticodeFile | None = None)

The signify.pkcs7.SignedData structure for Authenticode. It holds the same information as its superclass, with additionally the IndirectData.

__init__(asn1: cms.SignedData, signed_file: signed_file.AuthenticodeFile | None = None)
Parameters:
  • asn1 (asn1.pkcs7.SignedData) – The ASN.1 structure of the SignedData object

  • signed_file – The related AuthenticodeFile.

property content: IndirectData

The indirect data content of this AuthenticodeSignedData object.

explain_verify(*args: Any, **kwargs: Any) tuple[AuthenticodeVerificationResult, Exception | None]

This will return a value indicating the signature status of this object. This will not raise an error when the verification fails, but rather indicate this through the resulting enum

Return type:

Tuple[AuthenticodeVerificationResult, Exception]

Returns:

The verification result, and the exception containing more details (if available or None)

property indirect_data: IndirectData

Alias for content

iter_recursive_nested() Iterator[AuthenticodeSignedData]

Returns an iterator over AuthenticodeSignedData objects, including the current one, but also any nested AuthenticodeSignedData objects in the AuthenticodeSignerInfo structure.

See AuthenticodeSignerInfo.nested_signed_datas

verify(verification_context: ~signify.x509.context.VerificationContext | None = None, *, expected_hash: bytes | None = None, verify_additional_hashes: bool = True, cs_verification_context: ~signify.x509.context.VerificationContext | None = None, trusted_certificate_store: ~signify.x509.context.CertificateStore = <signify.x509.context.FileSystemCertificateStore object>, verification_context_kwargs: dict[str, ~typing.Any] | None = None, countersignature_mode: ~typing.Literal['strict', 'permit', 'ignore'] = 'strict') Iterable[list[Certificate]]

Verifies the SignedData structure, adds this to the base methods of SignedData:

  • Verifies that the digest algorithms match across the structure (SpcInfo, AuthenticodeSignedData and AuthenticodeSignerInfo must have the same)

  • Ensures that the hash in SpcInfo.digest matches the expected hash. If no expected hash is provided to this function, it is calculated using the Fingerprinter obtained from the AuthenticodeFile object.

Parameters:
  • expected_hash – The expected hash digest of the AuthenticodeFile.

  • verify_additional_hashes – Defines whether additional hashes, should be verified, such as page hashes for PE files and extended digests for MSI files.

  • verification_context – See SignedData.verify()

  • cs_verification_context – See SignedData.verify()

  • trusted_certificate_store – See SignedData.verify()

  • verification_context_kwargs – See SignedData.verify()

  • countersignature_mode – See SignedData.verify()

Raises:

AuthenticodeVerificationError – when the verification failed

Returns:

A list of valid certificate chains for this SignedData.

class signify.authenticode.IndirectData(asn1: SpcIndirectDataContent)

The Authenticode’s SpcIndirectDataContent information, and their children. This is expected to be part of the content of the SignedData structure in Authenticode.

Note that this structure is completely flattened out from this ASN.1 spec:

SpcIndirectDataContent ::= SEQUENCE {
    data SpcAttributeTypeAndOptionalValue,
    messageDigest  DigestInfo
}
SpcAttributeTypeAndOptionalValue ::= SEQUENCE {
    type ObjectID,
    value [0] EXPLICIT ANY OPTIONAL
}
asn1

The underlying ASN.1 data object

property content: PeImageData | SigInfo | None

Nested content of this IndirectData.

property content_asn1: Asn1Value

ASN.1 structure of the content.

property content_type: str

The contenttype string

property digest: bytes

The (signed) digest as present in this structure. This should match the digest calculated over the data itself.

property digest_algorithm: HashFunction

Digest algorithm of the digest.

class signify.authenticode.PeImageData(asn1: SpcPeImageData)

Information about the PE file, as provided in the IndirectData. It is based on the following structure:

SpcPeImageData ::= SEQUENCE {
    flags SpcPeImageFlags DEFAULT { includeResources },
    file SpcLink
}
SpcPeImageFlags ::= BIT STRING {
    includeResources            (0),
    includeDebugInfo            (1),
    includeImportAddressTable   (2)
}
SpcLink ::= CHOICE {
    url      [0] IMPLICIT IA5STRING,
    moniker  [1] IMPLICIT SpcSerializedObject,
    file     [2] EXPLICIT SpcString
}
SpcSerializedObject ::= SEQUENCE {
    classId SpcUuid,
    serializedData OCTETSTRING
}

This structure contains flags, which define which parts of the PE file are hashed. It is always ignored.

The file attribute originally contained information that describes the software publisher, but can now be a URL (which is ignored), a file, which is set to a SpcString set to <<<Obsolete>>>, or the moniker setting a SpcSerializedObject.

If used, the moniker always has UUID a6b586d5-b4a1-2466-ae05-a217da8e60d6 (bytes a6 b5 86 d5 b4 a1 24 66  ae 05 a2 17 da 8e 60 d6), and a binary structure. Ominously, this is left outside of scope of the Authenticode documentation, noting that it contains a binary structure that contains page hashes.

property class_id: str

Available if file_link_type is moniker. Contains the class ID. Should be a6b586d5-b4a1-2466-ae05-a217da8e60d6.

property content: list[bytes]

Available if serialized_data_asn1_available is True.

property content_pairs: Iterable[tuple[str, list[bytes]]]

Available if serialized_data_asn1_available is True.

property content_type: str

Available if serialized_data_asn1_available is True.

property content_types: list[str]

Available if serialized_data_asn1_available is True.

property contents: list[list[bytes]]

Available if serialized_data_asn1_available is True.

Describes which of the options is used in this content.

property flags: set[str]

Defines which parts of the PE file are hashed. It is always ignored.

classmethod page_hash_algorithm(content_type: str) HashFunction

Returns the used page hash algorithm for the provided content type.

property page_hash_algorithms: list[HashFunction]

Returns all used page hash algorithms in this structure.

property page_hashes: Iterable[tuple[int, int, bytes, HashFunction]]

Iterates over all page hash ranges, and their hash digests, as defined in the SpcSerializedObject. If not available, will simply return an empty list.

classmethod parse_page_hash_content(hash_algorithm: HashFunction, content: bytes) Iterable[tuple[int, int, bytes]]

Parses the content in the page hash content blob. It is constructed as 4 bytes offset, and the hash digest. The final entry will be the final offset and a zero hash (0000…).

This method yields tuples of start offset, end offset, and the hash digest.

property publisher: str

Available if file_link_type is url or file. Contains the information in the attribute in string form.

property serialized_data: bytes

Available if file_link_type is moniker. Raw serialized data as bytes.

property serialized_data_asn1: list[SpcAttributeTypeAndOptionalValue]

Available if serialized_data_asn1_available is True. Return the data in ASN.1 form.

property serialized_data_asn1_available: bool

Defines whether the property serialized_data_asn1 is available.

class signify.authenticode.SigInfo(asn1: SpcSigInfo)

SigInfo, mostly used in MSI files. It defines information about the SIP, which is the Subject Interface Package: A Microsoft proprietary specification for a software layer that enables applications to create, store, retrieve, and verify a subject signature.

property sip_guid: str

The SIP GUID.

property sip_version: int

The SIP version.

class signify.authenticode.AuthenticodeSignerInfo(asn1: SignerInfo, parent: SignedData | None = None)

Subclass of SignerInfo that is used by the verification of Authenticode. Note that this will contain the same attributes as SignerInfo, with some additions.

The countersigner attribute can hold the same as in the normal SignerInfo, but may also contain a RFC3161SignedData class.

property countersigner: AuthenticodeCounterSignerInfo | RFC3161SignedData | None

Authenticode may use a different countersigning mechanism, rather than using a nested AuthenticodeCounterSignerInfo, it may use a nested RFC-3161 response, which is a nested signify.pkcs7.SignedData structure (of type RFC3161SignedData). This is also assigned to the countersigner attribute if this is available.

property more_info: str | None

This information is extracted from the SpcSpOpusInfo authenticated attribute, containing the URL with more information.

property nested_signed_datas: list[AuthenticodeSignedData]

It is possible for Authenticode SignerInfo objects to contain nested signify.pkcs7.SignedData objects. This is similar to including multiple SignedData structures in the signify.authenticode.AuthenticodeFile.

This field is extracted from the unauthenticated attributes.

property program_name: str | None

This information is extracted from the SpcSpOpusInfo authenticated attribute, containing the program’s name.

property publisher_info: str | None

This information is extracted from the SpcSpOpusInfo authenticated attribute, containing the publisher_info. It is almost never set, but is defined in the ASN.1 structure.

property statement_types: list[str] | None

Defines the key purpose of the signer. This is ignored by the verification.

Countersignature

The countersignature is used to verify the timestamp of the signature. This is usually done by sending the signature to a time-stamping service, that provides the countersignature. This allows the signature to continue to be valid, even after the original certificate chain expiring.

There are two types of countersignature: a regular countersignature, as used in PKCS7, or a nested RFC3161 response. This nested object is basically a authenticode.pkcs7.SignedData object, which holds its own set of certificates.

Regular

class signify.authenticode.AuthenticodeCounterSignerInfo(asn1: SignerInfo, parent: SignedData | None = None)

Subclass of CounterSignerInfo that is used to contain the countersignerinfo for Authenticode.

RFC3161

class signify.authenticode.RFC3161SignedData(asn1: SignedData)

Some samples have shown to include a RFC-3161 countersignature in the unauthenticated attributes (as OID 1.3.6.1.4.1.311.3.3.1, which is in the Microsoft private namespace). This attribute contains its own signed data structure.

This is a subclass of signify.pkcs7.SignedData, containing a RFC3161 TSTInfo in its content field.

check_message_digest(data: bytes) bool

Given the data, returns whether the hash_algorithm and message_digest match the data provided.

property content: TSTInfo

Contains the TSTInfo class for this SignedData.

property signing_time: datetime

Transparent attribute to ensure that the signing_time attribute is consistently available.

property tst_info: TSTInfo

Alias for content.

verify(verification_context: VerificationContext | None = None, *, trusted_certificate_store: CertificateStore | None = None, verification_context_kwargs: dict[str, Any] | None = None) Iterable[Iterable[Certificate]]

Verifies the RFC3161 SignedData object. The context that is passed in must account for the certificate store of this object, or be left None.

The object is verified by verifying that the hash of the TSTInfo matches the SignerInfo.message_digest value. The remainder of the validation is done by calling SignerInfo.verify()

class signify.authenticode.TSTInfo(asn1: TSTInfo)

This is an implementation of the TSTInfo class as defined by RFC3161, used as content for a SignedData structure.

property hash_algorithm: HashFunction

The hash algorithm of the message imprint.

property message_digest: bytes

The hashed message

property policy: str

Policy attribute

property serial_number: int

The serial number of this signature

property signing_authority: CertificateName | None

The authority generating this signature

property signing_time: datetime

The time this signature was generated

property signing_time_accuracy: timedelta | None

The accuracy of the above time

property signing_time_ordering: bool

Indicates whether the signing time can be ordered.

class signify.authenticode.RFC3161SignerInfo(asn1: SignerInfo, parent: SignedData | None = None)

Subclass of SignerInfo that is used to contain the signerinfo for the RFC3161SignedData option.