Files
docuseal/lib/submissions/timestamp_handler.rb
T

73 lines
2.1 KiB
Ruby
Raw Normal View History

2023-12-02 18:14:33 +02:00
# frozen_string_literal: true
module Submissions
class TimestampHandler
2025-04-30 23:48:03 +03:00
HASH_ALGORITHM = 'SHA256'
2025-11-18 22:17:05 +02:00
TIMEOUT = 10
2023-12-02 18:14:33 +02:00
TimestampError = Class.new(StandardError)
2024-10-29 08:29:26 +02:00
attr_reader :tsa_url, :tsa_fallback_url
2023-12-02 18:14:33 +02:00
def initialize(tsa_url:)
2024-10-29 08:29:26 +02:00
@tsa_url, @tsa_fallback_url = tsa_url.split(',')
2023-12-02 18:14:33 +02:00
end
def finalize_objects(_signature_field, signature)
signature.document.version = '2.0'
signature[:Type] = :DocTimeStamp
signature[:Filter] = :'Adobe.PPKLite'
signature[:SubFilter] = :'ETSI.RFC3161'
end
2025-04-30 22:58:50 +03:00
# rubocop:disable Metrics
2023-12-02 18:14:33 +02:00
def sign(io, byte_range)
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])
uri = Addressable::URI.parse(tsa_url)
conn = Faraday.new(uri.origin) do |c|
2025-11-18 22:17:05 +02:00
c.options.read_timeout = TIMEOUT
c.options.open_timeout = TIMEOUT
2026-01-26 18:18:07 +02:00
c.request :authorization, :basic, uri.user, uri.password if uri.password.present?
2023-12-02 18:14:33 +02:00
end
2025-05-06 18:44:29 +03:00
response = conn.post(uri.request_uri, build_payload(digest.digest),
2023-12-02 18:14:33 +02:00
'content-type' => 'application/timestamp-query')
2024-10-29 08:29:26 +02:00
if response.status != 200 || response.body.blank?
raise TimestampError if tsa_fallback_url.blank?
Rollbar.error('TimestampError: use fallback URL') if defined?(Rollbar)
response = Faraday.post(tsa_fallback_url, build_payload(digest.digest),
'content-type' => 'application/timestamp-query')
raise TimestampError if response.status != 200 || response.body.blank?
end
2023-12-02 18:14:33 +02:00
OpenSSL::Timestamp::Response.new(response.body).token.to_der
2025-04-30 22:58:50 +03:00
rescue StandardError => e
Rollbar.error(e) if defined?(Rollbar)
2025-05-01 00:14:04 +03:00
Rails.logger.error(e)
2025-04-30 22:58:50 +03:00
OpenSSL::ASN1::GeneralizedTime.new(Time.now.utc).to_der
2023-12-02 18:14:33 +02:00
end
2025-04-30 22:58:50 +03:00
# rubocop:enable Metrics
2023-12-02 18:14:33 +02:00
def build_payload(digest)
req = OpenSSL::Timestamp::Request.new
req.algorithm = HASH_ALGORITHM
req.message_imprint = digest
req.to_der
end
end
end