class HexaPDF::DigitalSignature::Handler

ones that don’t have a default implementation.
Specific signature handlers need to override methods if necessary and implement the needed
The base signature handler providing common functionality.

def certificate_chain

Needs to be implemented by specific handlers.

Returns the certificate chain.
def certificate_chain
  raise "Needs to be implemented by specific handlers"
end

def check_certified_signature(result)

Sets an informational message on +result+ whether the signature is a certified signature.
def check_certified_signature(result)
  sigref = signature_dict[:Reference]&.find {|ref| ref[:TransformMethod] == :DocMDP }
  if sigref && signature_dict.document.catalog[:Perms]&.[](:DocMDP) == signature_dict
    perms = sigref[:TransformParams]&.[](:P) || 2
    result.log(:info, "Certified signature (#{DOCMDP_PERMS_MESSAGE_MAP[perms]})")
  end
end

def initialize(signature_dict)

Creates a new signature handler for the given signature dictionary.
def initialize(signature_dict)
  @signature_dict = signature_dict
end

def signer_certificate

Needs to be implemented by specific handlers.

Returns the certificate used for signing.
def signer_certificate
  raise "Needs to be implemented by specific handlers"
end

def signer_name

Returns the common name of the signer (/Name field of the signature dictionary).
def signer_name
  @signature_dict[:Name]
end

def signing_time

Returns the time of signing (/M field of the signature dictionary).
def signing_time
  @signature_dict[:M]
end

def store_verification_callback(result, allow_self_signed: false)

+allow_self_signed+:: Specifies whether self-signed certificates are allowed.

+result+:: The VerificationResult object that should be updated if problems are found.

Returns the block that should be used as the OpenSSL::X509::Store verification callback.
def store_verification_callback(result, allow_self_signed: false)
  lambda do |_success, context|
    if context.error == OpenSSL::X509::V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT ||
        context.error == OpenSSL::X509::V_ERR_SELF_SIGNED_CERT_IN_CHAIN
      result.log(allow_self_signed ? :info : :error, "Self-signed certificate found")
    end
    true
  end
end

def verify(store, allow_self_signed: false)

Needs to be called by specific handlers.

object for use by concrete implementations.
Verifies general signature properties and prepares the provided OpenSSL::X509::Store
def verify(store, allow_self_signed: false)
  result = VerificationResult.new
  check_certified_signature(result)
  verify_signing_time(result)
  store.verify_callback =
    store_verification_callback(result, allow_self_signed: allow_self_signed)
  result
end

def verify_signing_time(result)

Verifies that the signing time was within the validity period of the signer certificate.
def verify_signing_time(result)
  time = signing_time
  cert = signer_certificate
  if time && cert && (time < cert.not_before || time > cert.not_after)
    result.log(:error, "Signer certificate not valid at signing time")
  end
end