Class: HexaPDF::Type::Signature::AdbePkcs7Detached

Inherits:
Handler
  • Object
show all
Defined in:
lib/hexapdf/type/signature/adbe_pkcs7_detached.rb

Overview

The signature handler for the adbe.pkcs7.detached sub-filter.

Instance Attribute Summary

Attributes inherited from Handler

#signature_dict

Instance Method Summary collapse

Constructor Details

#initialize(signature_dict) ⇒ AdbePkcs7Detached

Creates a new signature handler for the given signature dictionary.



48
49
50
51
# File 'lib/hexapdf/type/signature/adbe_pkcs7_detached.rb', line 48

def initialize(signature_dict)
  super
  @pkcs7 = OpenSSL::PKCS7.new(signature_dict.contents)
end

Instance Method Details

#certificate_chainObject

Returns the certificate chain.



64
65
66
# File 'lib/hexapdf/type/signature/adbe_pkcs7_detached.rb', line 64

def certificate_chain
  @pkcs7.certificates
end

#signer_certificateObject

Returns the signer certificate (an instance of OpenSSL::X509::Certificate).



69
70
71
72
# File 'lib/hexapdf/type/signature/adbe_pkcs7_detached.rb', line 69

def signer_certificate
  info = signer_info
  certificate_chain.find {|cert| cert.issuer == info.issuer && cert.serial == info.serial }
end

#signer_infoObject

Returns the signer information object (an instance of OpenSSL::PKCS7::SignerInfo).



75
76
77
# File 'lib/hexapdf/type/signature/adbe_pkcs7_detached.rb', line 75

def signer_info
  @pkcs7.signers.first
end

#signer_nameObject

Returns the common name of the signer.



54
55
56
# File 'lib/hexapdf/type/signature/adbe_pkcs7_detached.rb', line 54

def signer_name
  signer_certificate.subject.to_a.assoc("CN")&.[](1) || super
end

#signing_timeObject

Returns the time of signing.



59
60
61
# File 'lib/hexapdf/type/signature/adbe_pkcs7_detached.rb', line 59

def signing_time
  signer_info.signed_time rescue super
end

#verify(store, allow_self_signed: false) ⇒ Object

Verifies the signature using the provided OpenSSL::X509::Store object.



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/hexapdf/type/signature/adbe_pkcs7_detached.rb', line 80

def verify(store, allow_self_signed: false)
  result = super

  signer_info = self.signer_info
  signer_certificate = self.signer_certificate
  certificate_chain = self.certificate_chain

  if certificate_chain.empty?
    result.log(:error, "No certificates found in signature")
    return result
  end

  if @pkcs7.signers.size != 1
    result.log(:error, "Exactly one signer needed, found #{@pkcs7.signers.size}")
  end

  unless signer_certificate
    result.log(:error, "Signer serial=#{signer_info.serial} issuer=#{signer_info.issuer} " \
               "not found in certificates stored in PKCS7 object")
    return result
  end

  key_usage = signer_certificate.extensions.find {|ext| ext.oid == 'keyUsage' }
  unless key_usage && key_usage.value.split(', ').include?("Digital Signature")
    result.log(:error, "Certificate key usage is missing 'Digital Signature'")
  end

  if @pkcs7.verify(certificate_chain, store, signature_dict.signed_data,
                   OpenSSL::PKCS7::DETACHED | OpenSSL::PKCS7::BINARY)
    result.log(:info, "Signature valid")
  else
    result.log(:error, "Signature verification failed")
  end

  result
end