Class: HexaPDF::DigitalSignature::Signing::SignedDataCreator

Inherits:
Object
  • Object
show all
Defined in:
lib/hexapdf/digital_signature/signing/signed_data_creator.rb

Overview

This class is used for creating a CMS SignedData binary data object, as needed for PDF signing.

OpenSSL already provides the ability to access, sign and create such CMS objects but is limited in what it offers in terms of data added to it. Since HexaPDF needs to follow the PDF standard, it needs control over the created structure so as to make it compatible with the various requirements.

As the created CMS object is only meant to be used in the context of PDF signing, it also restricts certain things, like allowing only a single signer.

Additionally, only RSA signatures are currently supported!

See: PDF2.0 s12.8.3.3, PDF2.0 s12.8.3.4, RFC5652, ETSI TS 102 778 Parts 1-4

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeSignedDataCreator

Creates a new SignedData object.



94
95
96
97
98
99
100
# File 'lib/hexapdf/digital_signature/signing/signed_data_creator.rb', line 94

def initialize
  @certificate = nil
  @key = nil
  @certificates = []
  @digest_algorithm = 'sha256'
  @timestamp_handler = nil
end

Instance Attribute Details

#certificateObject

The OpenSSL certificate object which is used to sign the data.



70
71
72
# File 'lib/hexapdf/digital_signature/signing/signed_data_creator.rb', line 70

def certificate
  @certificate
end

#certificatesObject

Array of additional OpenSSL certificate objects that should be included.

Should include all certificates of the hierarchy of the signing certificate.



80
81
82
# File 'lib/hexapdf/digital_signature/signing/signed_data_creator.rb', line 80

def certificates
  @certificates
end

#digest_algorithmObject

The digest algorithm that should be used. Defaults to ‘sha256’.

Allowed values: sha256, sha384, sha512.



85
86
87
# File 'lib/hexapdf/digital_signature/signing/signed_data_creator.rb', line 85

def digest_algorithm
  @digest_algorithm
end

#keyObject

The OpenSSL key object which is used for signing. Needs to correspond to #certificate.

If the key is not set, a block for signing will need to be provided to #sign.



75
76
77
# File 'lib/hexapdf/digital_signature/signing/signed_data_creator.rb', line 75

def key
  @key
end

#signing_timeObject

The signing time to use instead of Time.now.



88
89
90
# File 'lib/hexapdf/digital_signature/signing/signed_data_creator.rb', line 88

def signing_time
  @signing_time
end

#timestamp_handlerObject

The timestamp handler instance that should be used for timestamping.



91
92
93
# File 'lib/hexapdf/digital_signature/signing/signed_data_creator.rb', line 91

def timestamp_handler
  @timestamp_handler
end

Class Method Details

.create(data, type: :cms, **attributes, &block) ⇒ Object

Creates a SignedDataCreator, sets the given attributes if they are not nil and then calls #create with the given data, type and block.



63
64
65
66
67
# File 'lib/hexapdf/digital_signature/signing/signed_data_creator.rb', line 63

def self.create(data, type: :cms, **attributes, &block)
  instance = new
  attributes.each {|key, value| instance.send("#{key}=", value) unless value.nil? }
  instance.create(data, type: type, &block)
end

Instance Method Details

#create(data, type: :cms, &block) ⇒ Object

Creates a CMS SignedData binary data object for the given data using the set attributes and returns it in DER-serialized form.

If the #key attribute is not set, the digest algorithm and the already digested data to be signed is yielded and the block needs to return the signature.

type

The type can either be :cms when creating standard PDF CMS signatures or :pades when creating PAdES compatible signatures. PAdES signatures are part of PDF 2.0.



111
112
113
114
115
116
117
118
119
# File 'lib/hexapdf/digital_signature/signing/signed_data_creator.rb', line 111

def create(data, type: :cms, &block) # :yield: digested_data
  signed_attrs = create_signed_attrs(data, signing_time: (type == :cms))
  signature = digest_and_sign_data(set(*signed_attrs.value).to_der, &block)
  unsigned_attrs = create_unsigned_attrs(signature)

  signer_info = create_signer_info(signature, signed_attrs, unsigned_attrs)
  signed_data = create_signed_data(signer_info)
  (signed_data)
end