Module: Pdfrb::DigitalSignature::TimestampClient
- Defined in:
- lib/pdfrb/digital_signature/timestamp_client.rb
Overview
RFC 3161 trusted timestamp client. Submits a hash to a Time Stamp Authority (TSA) over HTTPS and returns the resulting timestamp token (TSTInfo) as DER bytes, suitable for inclusion in a PAdES B-T/LTA signature.
Pure-Ruby: uses Net::HTTP with OpenSSL. The TSA URL is configurable; defaults to a free public TSA. Callers in production should configure a trusted TSA endpoint.
Constant Summary collapse
- DEFAULT_TSA_URL =
"https://freetsa.org/tsr"- DEFAULT_HASH_ALGORITHM =
"sha256"- DIGEST_OIDS =
{ "sha1" => "1.3.14.3.2.26", "sha256" => "2.16.840.1.101.3.4.2.1", "sha384" => "2.16.840.1.101.3.4.2.2", "sha512" => "2.16.840.1.101.3.4.2.3", }.freeze
Class Method Summary collapse
-
.build_tsq_request(hashed_bytes, hash_algorithm) ⇒ Object
Build the TimeStampReq DER.
- .https_post(url, body, cert: nil, key: nil) ⇒ Object
-
.request_timestamp(data:, url: DEFAULT_TSA_URL, hash_algorithm: DEFAULT_HASH_ALGORITHM, cert: nil, key: nil) ⇒ String
Submit
data(or its digest) to the TSA aturland return the DER-encoded TimeStampResp.
Class Method Details
.build_tsq_request(hashed_bytes, hash_algorithm) ⇒ Object
Build the TimeStampReq DER. Pure OpenSSL::ASN1 construction.
49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
# File 'lib/pdfrb/digital_signature/timestamp_client.rb', line 49 def build_tsq_request(hashed_bytes, hash_algorithm) oid = DIGEST_OIDS[hash_algorithm.to_s] || DIGEST_OIDS["sha256"] OpenSSL::ASN1::Sequence.new([ OpenSSL::ASN1::Integer.new(1), # version OpenSSL::ASN1::Sequence.new([ # messageImprint OpenSSL::ASN1::Sequence.new([ OpenSSL::ASN1::ObjectId.new(oid), OpenSSL::ASN1::Null.new(nil), ]), OpenSSL::ASN1::OctetString.new(hashed_bytes), ]), OpenSSL::ASN1::Boolean.new(true), # reqCert ]).to_der end |
.https_post(url, body, cert: nil, key: nil) ⇒ Object
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/pdfrb/digital_signature/timestamp_client.rb', line 64 def https_post(url, body, cert: nil, key: nil) uri = URI(url) http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true if uri.is_a?(URI::HTTPS) http.ssl_timeout = 30 if cert && key http.cert = cert http.key = key end req = Net::HTTP::Post.new(uri.request_uri) req["Content-Type"] = "application/timestamp-query" req.body = body response = http.request(req) raise "TSA error: #{response.code} #{response.}" unless response.code == "200" response.body end |
.request_timestamp(data:, url: DEFAULT_TSA_URL, hash_algorithm: DEFAULT_HASH_ALGORITHM, cert: nil, key: nil) ⇒ String
Submit data (or its digest) to the TSA at url and return
the DER-encoded TimeStampResp.
32 33 34 35 36 37 38 39 |
# File 'lib/pdfrb/digital_signature/timestamp_client.rb', line 32 def (data:, url: DEFAULT_TSA_URL, hash_algorithm: DEFAULT_HASH_ALGORITHM, cert: nil, key: nil) digest = OpenSSL::Digest.new(hash_algorithm) hashed = digest.digest(data) req = build_tsq_request(hashed, hash_algorithm) https_post(url, req, cert: cert, key: key) end |