Class: HexaPDF::DigitalSignature::Signing::TimestampHandler
- Inherits:
-
Object
- Object
- HexaPDF::DigitalSignature::Signing::TimestampHandler
- Defined in:
- lib/hexapdf/digital_signature/signing/timestamp_handler.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.
94 95 96 97 |
# File 'lib/hexapdf/digital_signature/signing/timestamp_handler.rb', line 94 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 dictionary.
91 92 93 |
# File 'lib/hexapdf/digital_signature/signing/timestamp_handler.rb', line 91 def contact_info @contact_info end |
#location ⇒ Object
The timestamping location. If used, will be set on the signature dictionary.
88 89 90 |
# File 'lib/hexapdf/digital_signature/signing/timestamp_handler.rb', line 88 def location @location end |
#reason ⇒ Object
The reason for timestamping. If used, will be set on the signature dictionary.
85 86 87 |
# File 'lib/hexapdf/digital_signature/signing/timestamp_handler.rb', line 85 def reason @reason end |
#signature_size ⇒ Object
Returns the size of the serialized signature that should be reserved.
100 101 102 |
# File 'lib/hexapdf/digital_signature/signing/timestamp_handler.rb', line 100 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.
70 71 72 |
# File 'lib/hexapdf/digital_signature/signing/timestamp_handler.rb', line 70 def tsa_hash_algorithm @tsa_hash_algorithm end |
#tsa_policy_id ⇒ Object
The policy OID to use for timestamping. Defaults to nil
.
73 74 75 |
# File 'lib/hexapdf/digital_signature/signing/timestamp_handler.rb', line 73 def tsa_policy_id @tsa_policy_id end |
#tsa_url ⇒ Object
The URL of the timestamp authority server.
This value is required.
67 68 69 |
# File 'lib/hexapdf/digital_signature/signing/timestamp_handler.rb', line 67 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.
105 106 107 108 109 110 111 112 113 |
# File 'lib/hexapdf/digital_signature/signing/timestamp_handler.rb', line 105 def finalize_objects(_signature_field, signature) signature.document.version = '2.0' signature[:Type] = :DocTimeStamp signature[:Filter] = :'Adobe.PPKLite' 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.
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
# File 'lib/hexapdf/digital_signature/signing/timestamp_handler.rb', line 117 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 |