Class: HexaPDF::Document::Signatures::TimestampHandler
- Inherits:
-
Object
- Object
- HexaPDF::Document::Signatures::TimestampHandler
- Defined in:
- lib/hexapdf/document/signatures.rb
Overview
This is a signing handler for adding a timestamp signature (a PDF2.0 feature) to a PDF document. It is registered under the :timestamp name.
The timestamp is provided by a timestamp authority and establishes the document contents at the time indicated in the timestamp. Timestamping a PDF document is usually done in context of long term validation but can also be done standalone.
Usage
It is necessary to provide at least the URL of the timestamp authority server (TSA) via #tsa_url, everything else is optional and uses default values. The TSA server must not use authentication to be usable.
Example:
document.sign("output.pdf", handler: :timestamp, tsa_url: 'https://freetsa.org/tsr')
Instance Attribute Summary collapse
-
#contact_info ⇒ Object
The contact information.
-
#location ⇒ Object
The timestamping location.
-
#reason ⇒ Object
The reason for timestamping.
-
#signature_size ⇒ Object
Returns the size of the serialized signature that should be reserved.
-
#tsa_hash_algorithm ⇒ Object
The hash algorithm to use for timestamping.
-
#tsa_policy_id ⇒ Object
The policy OID to use for timestamping.
-
#tsa_url ⇒ Object
The URL of the timestamp authority server.
Instance Method Summary collapse
-
#finalize_objects(_signature_field, signature) ⇒ Object
Finalizes the signature field as well as the signature dictionary before writing.
-
#initialize(**arguments) ⇒ TimestampHandler
constructor
Creates a new TimestampHandler with the given attributes.
-
#sign(io, byte_range) ⇒ Object
Returns the DER serialized OpenSSL::PKCS7 structure containing the timestamp token for the given IO byte ranges.
Constructor Details
#initialize(**arguments) ⇒ TimestampHandler
Creates a new TimestampHandler with the given attributes.
283 284 285 286 |
# File 'lib/hexapdf/document/signatures.rb', line 283 def initialize(**arguments) @signature_size = nil arguments.each {|name, value| send("#{name}=", value) } end |
Instance Attribute Details
#contact_info ⇒ Object
The contact information. If used, will be set on the signature object.
280 281 282 |
# File 'lib/hexapdf/document/signatures.rb', line 280 def contact_info @contact_info end |
#location ⇒ Object
The timestamping location. If used, will be set on the signature object.
277 278 279 |
# File 'lib/hexapdf/document/signatures.rb', line 277 def location @location end |
#reason ⇒ Object
The reason for timestamping. If used, will be set on the signature object.
274 275 276 |
# File 'lib/hexapdf/document/signatures.rb', line 274 def reason @reason end |
#signature_size ⇒ Object
Returns the size of the serialized signature that should be reserved.
289 290 291 |
# File 'lib/hexapdf/document/signatures.rb', line 289 def signature_size @signature_size || (sign(StringIO.new, [0, 0, 0, 0]).size * 1.5).to_i end |
#tsa_hash_algorithm ⇒ Object
The hash algorithm to use for timestamping. Defaults to SHA512.
259 260 261 |
# File 'lib/hexapdf/document/signatures.rb', line 259 def tsa_hash_algorithm @tsa_hash_algorithm end |
#tsa_policy_id ⇒ Object
The policy OID to use for timestamping. Defaults to nil.
262 263 264 |
# File 'lib/hexapdf/document/signatures.rb', line 262 def tsa_policy_id @tsa_policy_id end |
#tsa_url ⇒ Object
The URL of the timestamp authority server.
This value is required.
256 257 258 |
# File 'lib/hexapdf/document/signatures.rb', line 256 def tsa_url @tsa_url end |
Instance Method Details
#finalize_objects(_signature_field, signature) ⇒ Object
Finalizes the signature field as well as the signature dictionary before writing.
294 295 296 297 298 299 300 301 |
# File 'lib/hexapdf/document/signatures.rb', line 294 def finalize_objects(_signature_field, signature) signature.document.version = '2.0' signature[:Type] = :DocTimeStamp signature[:SubFilter] = :'ETSI.RFC3161' signature[:Reason] = reason if reason signature[:Location] = location if location signature[:ContactInfo] = contact_info if contact_info end |
#sign(io, byte_range) ⇒ Object
Returns the DER serialized OpenSSL::PKCS7 structure containing the timestamp token for the given IO byte ranges.
305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 |
# File 'lib/hexapdf/document/signatures.rb', line 305 def sign(io, byte_range) hash_algorithm = tsa_hash_algorithm || 'SHA512' digest = OpenSSL::Digest.new(hash_algorithm) io.pos = byte_range[0] digest << io.read(byte_range[1]) io.pos = byte_range[2] digest << io.read(byte_range[3]) req = OpenSSL::Timestamp::Request.new req.algorithm = hash_algorithm req. = digest.digest req.policy_id = tsa_policy_id if tsa_policy_id http_response = Net::HTTP.post(URI(tsa_url), req.to_der, 'content-type' => 'application/timestamp-query') if http_response.kind_of?(Net::HTTPOK) response = OpenSSL::Timestamp::Response.new(http_response.body) if response.status == 0 response.token.to_der else raise HexaPDF::Error, "Timestamp token could not be created: #{response.failure_info}" end else raise HexaPDF::Error, "Invalid TSA server response: #{http_response.body}" end end |