HankoXml

Class: HankoXml::Xades::Signer

Inherits:
Signer
  • Object
show all
Defined in:
lib/hanko_xml/xades.rb

Overview

A Signer that produces XAdES-B (baseline) signatures (#57).

On top of the Signer's own references it adds a ds:Object holding xades:QualifyingProperties, and a Reference over its xades:SignedProperties: SigningTime, SigningCertificateV2 (digest of certificate:), and optionally SignaturePolicyIdentifier, SignerRoleV2 and DataObjectFormat.

With timestamper:, a XAdES-T signature (#162): an RFC 3161 token over the canonicalized ds:SignatureValue in a xades:SignatureTimeStamp.

With validation_data: as well, XAdES-LT (#167): CertificateValues and RevocationValues after the SignatureTimeStamp. Xades::Augmenter adds either to a signature that already exists.

Always builds a new (template: :build).

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(certificate: nil, signing_time: nil, signature_policy: nil, claimed_roles: [], data_object_format: nil, signature_id: nil, template: :build, timestamper: nil, timestamp_digest_method: nil, timestamp_canonicalization_method: :exc_c14n, validation_data: nil, **options, &block) ⇒ Signer

All other keywords are Signer's.

Parameters:

  • certificate (Key, OpenSSL::X509::Certificate, String, Pathname) (defaults to: nil) —

    Required: SigningCertificateV2 commits to it.

  • signing_time (Time, nil) (defaults to: nil) —

    The SigningTime to sign; nil means the time #sign runs.

  • signature_policy (SignaturePolicy, Hash, :implied, nil) (defaults to: nil) —

    SignaturePolicyIdentifier, if any.

  • claimed_roles (Array<String>) (defaults to: []) —

    SignerRoleV2/ClaimedRoles.

  • data_object_format (DataObjectFormat, Hash, nil) (defaults to: nil) —

    Describes the signed data; applies to each of this Signer's own references, which get an Id when they have none.

  • signature_id (String, nil) (defaults to: nil) —

    The Id; generated when nil, since QualifyingProperties targets it.

  • timestamper (#call, nil) (defaults to: nil) —

    Called with a DER RFC 3161 TimeStampReq, returns the TSA's DER TimeStampResp. The library never opens a connection: the callable owns the TSA exchange.

  • timestamp_digest_method (Symbol, nil) (defaults to: nil) —

    The imprint digest; nil means digest_method:.

  • timestamp_canonicalization_method (Symbol) (defaults to: :exc_c14n) —

    How ds:SignatureValue is canonicalized for the imprint.

  • validation_data (ValidationData, Hash, nil) (defaults to: nil) —

    Certificates, CRLs and OCSP responses to embed (XAdES-LT); needs timestamper:, since B-LT builds on B-T.



124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/hanko_xml/xades.rb', line 124

def initialize(certificate: nil, signing_time: nil, signature_policy: nil, claimed_roles: [],
               data_object_format: nil, signature_id: nil, template: :build, timestamper: nil,
               timestamp_digest_method: nil, timestamp_canonicalization_method: :exc_c14n, validation_data: nil,
               **options, &block)
  unless template.to_sym == :build
    raise HankoXml::ConfigurationError,
          "template: #{template.inspect} is not supported for XAdES; it always builds a new <Signature>"
  end
  if signing_time && !signing_time.respond_to?(:utc)
    raise HankoXml::ConfigurationError, "signing_time: must be a Time, got #{signing_time.class}"
  end

  @signing_time = signing_time&.dup&.utc&.freeze
  @signature_policy = coerce_signature_policy(signature_policy)
  @claimed_roles = Array(claimed_roles).map { |role| role.to_s.dup.freeze }.freeze
  @data_object_format = coerce_data_object_format(data_object_format)
  SignatureTimeStamper.check_timestamper!(timestamper)
  @timestamper = timestamper
  @timestamp_digest_method = timestamp_digest_method
  @timestamp_canonicalization_method = timestamp_canonicalization_method
  @validation_data = ValidationData.coerce(validation_data)
  if @validation_data && !timestamper
    raise HankoXml::ConfigurationError, "validation_data: needs timestamper: (XAdES-LT builds on XAdES-T)"
  end

  super(certificate: certificate, signature_id: signature_id || "xades-#{SecureRandom.hex(8)}",
        template: :build, **options, &block)
end

Instance Attribute Details

#claimed_roles ⇒ Object (readonly)

Returns the value of attribute claimed_roles.



104
105
106
# File 'lib/hanko_xml/xades.rb', line 104

def claimed_roles
  @claimed_roles
end

#data_object_format ⇒ Object (readonly)

Returns the value of attribute data_object_format.



104
105
106
# File 'lib/hanko_xml/xades.rb', line 104

def data_object_format
  @data_object_format
end

#signature_policy ⇒ Object (readonly)

Returns the value of attribute signature_policy.



104
105
106
# File 'lib/hanko_xml/xades.rb', line 104

def signature_policy
  @signature_policy
end

#signing_time ⇒ Object (readonly)

Returns the value of attribute signing_time.



104
105
106
# File 'lib/hanko_xml/xades.rb', line 104

def signing_time
  @signing_time
end

#timestamp_canonicalization_method ⇒ Object (readonly)

Returns the value of attribute timestamp_canonicalization_method.



104
105
106
# File 'lib/hanko_xml/xades.rb', line 104

def timestamp_canonicalization_method
  @timestamp_canonicalization_method
end

#timestamper ⇒ Object (readonly)

Returns the value of attribute timestamper.



104
105
106
# File 'lib/hanko_xml/xades.rb', line 104

def timestamper
  @timestamper
end

#validation_data ⇒ Object (readonly)

Returns the value of attribute validation_data.



104
105
106
# File 'lib/hanko_xml/xades.rb', line 104

def validation_data
  @validation_data
end

Instance Method Details

#references ⇒ Object

This Signer's own references (the whole document when it has none), then the Reference over SignedProperties.



155
156
157
158
159
160
# File 'lib/hanko_xml/xades.rb', line 155

def references
  own = super
  own = [HankoXml::Reference.new(uri: "", digest_method: digest_method)] if own.empty?
  own = own.each_with_index.map { |ref, i| with_id(ref, i) } if data_object_format
  [*own, signed_properties_reference]
end

#signature_timestamp_id ⇒ Object



178
179
180
# File 'lib/hanko_xml/xades.rb', line 178

def signature_timestamp_id
  "#{signature_id}-sigts"
end

#signed_properties_id ⇒ Object



169
170
171
# File 'lib/hanko_xml/xades.rb', line 169

def signed_properties_id
  "#{signature_id}-signedprops"
end

#template(doc_or_xml) ⇒ Object

The the Signer would build, with xades:QualifyingProperties.



163
164
165
166
167
# File 'lib/hanko_xml/xades.rb', line 163

def template(doc_or_xml)
  signature = super
  signature.add_child(QualifyingProperties.new(signature, self).build)
  signature
end

#timestamp_digest_method ⇒ Object

The imprint digest: timestamp_digest_method:, or else digest_method:.



174
175
176
# File 'lib/hanko_xml/xades.rb', line 174

def timestamp_digest_method
  @timestamp_digest_method || digest_method
end

#to_h ⇒ Object



182
183
184
185
186
187
188
# File 'lib/hanko_xml/xades.rb', line 182

def to_h
  super.merge(signing_time: signing_time, signature_policy: signature_policy, claimed_roles: claimed_roles,
              data_object_format: data_object_format, timestamper: timestamper,
              timestamp_digest_method: timestamp_digest_method,
              timestamp_canonicalization_method: timestamp_canonicalization_method,
              validation_data: validation_data)
end