openssl - Time stamp validation, missing certificate -


what need: need verifiable time stamp on file called notes, on ubuntu computer using openssl.

what problem is: can signed timestamp http://timestamp.globalsign.com/scripts/timstamp.dll can't verify it. when run

openssl ts -verify -data notes -in test.tsr 

i two-line output (extra line breaks inserted readability)

verification: failed  3073500860:error:2f06d064:time stamp routines: ts_verify_cert:certificate verify error:ts_rsp_verify.c:246: verify error:unable local issuer certificate 

i think means need certificate named "globalsign tsa standard - g2" (see "output of script" section below), have no idea find it. grep'd /usr, /etc, , /home directories string, i'm pretty confident don't have it. can't find on google. does know certificate, or maybe i'm doing else wrong? , also, why difficult? see lots of people talking using server on various stack exchanges, seem 1 problem.


more info

i using default openssl config file @ /etc/ssl/openssl.cnf.

i use following short script generate time stamp query test.tsq, send time stamp server, receive time stamp reply test.tsr, try validate it.

#!/bin/bash #make time stamp query openssl ts -query -data notes -sha256 -cert -out test.tsq  #write query stdout in text format openssl ts -query -in test.tsq -text  echo ""  #use tsget request, since don't know how curl tsget -h http://timestamp.globalsign.com/scripts/timstamp.dll test.tsq  #write reply stdout in text form openssl ts -reply -in test.tsr -text  echo ""  #verify timestamp openssl ts -verify -data notes -in test.tsr 

the perl script tsget came openssl package think, , found @ /usr/lib/ssl/misc/tsget, i'll include here troubleshooting:

#!/usr/bin/perl -w # written zoltan glozik <zglozik@stones.com>. # copyright (c) 2002 opentsa project.  rights reserved. $::version = '$id: tsget,v 1.3 2009/09/07 17:57:18 steve exp $';  use strict; use io::handle; use getopt::std; use file::basename; use www::curl::easy;  use vars qw(%options);  # callback reading body. sub read_body {     ($maxlength, $state) = @_;     $return_data = "";     $data_len = length ${$state->{data}};     if ($state->{bytes} < $data_len) {     $data_len = $data_len - $state->{bytes};     $data_len = $maxlength if $data_len > $maxlength;     $return_data = substr ${$state->{data}}, $state->{bytes}, $data_len;     $state->{bytes} += $data_len;     }     return $return_data; }  # callback writing body variable. sub write_body {     ($data, $pointer) = @_;     ${$pointer} .= $data;     return length($data); }  # initialise new curl object. sub create_curl {     $url = shift;      # create curl object.     $curl = www::curl::easy::new();      # error-handling related options.     $curl->setopt(curlopt_verbose, 1) if $options{d};     $curl->setopt(curlopt_failonerror, 1);     $curl->setopt(curlopt_useragent, "opentsa tsget.pl/" . (split / /, $::version)[2]);      # options post method.     $curl->setopt(curlopt_upload, 1);     $curl->setopt(curlopt_customrequest, "post");     $curl->setopt(curlopt_httpheader,         ["content-type: application/timestamp-query",         "accept: application/timestamp-reply,application/timestamp-response"]);     $curl->setopt(curlopt_readfunction, \&read_body);     $curl->setopt(curlopt_headerfunction, sub { return length($_[0]); });      # options getting result.     $curl->setopt(curlopt_writefunction, \&write_body);      # ssl related options.     $curl->setopt(curlopt_sslkeytype, "pem");     $curl->setopt(curlopt_ssl_verifypeer, 1);   # verify server's certificate.     $curl->setopt(curlopt_ssl_verifyhost, 2);   # check server's cn.     $curl->setopt(curlopt_sslkey, $options{k}) if defined($options{k});     $curl->setopt(curlopt_sslkeypasswd, $options{p}) if defined($options{p});     $curl->setopt(curlopt_sslcert, $options{c}) if defined($options{c});     $curl->setopt(curlopt_cainfo, $options{c}) if defined($options{c});     $curl->setopt(curlopt_capath, $options{p}) if defined($options{p});     $curl->setopt(curlopt_random_file, $options{r}) if defined($options{r});     $curl->setopt(curlopt_egdsocket, $options{g}) if defined($options{g});      # setting destination.     $curl->setopt(curlopt_url, $url);      return $curl; }  # send request , returns body back. sub get_timestamp {     $curl = shift;     $body = shift;     $ts_body;     local $::error_buf;      # error-handling related options.     $curl->setopt(curlopt_errorbuffer, "::error_buf");      # options post method.     $curl->setopt(curlopt_infile, {data => $body, bytes => 0});     $curl->setopt(curlopt_infilesize, length(${$body}));      # options getting result.     $curl->setopt(curlopt_file, \$ts_body);      # send request...     $error_code = $curl->perform();     $error_string;     if ($error_code != 0) {         $http_code = $curl->getinfo(curlinfo_http_code);     $error_string = "could not timestamp";     $error_string .= ", http code: $http_code" unless $http_code == 0;     $error_string .= ", curl code: $error_code";     $error_string .= " ($::error_buf)" if defined($::error_buf);     } else {         $ct = $curl->getinfo(curlinfo_content_type);     if (lc($ct) ne "application/timestamp-reply"         && lc($ct) ne "application/timestamp-response") {         $error_string = "unexpected content type returned: $ct";         }     }     return ($ts_body, $error_string);  }  # print usage information , exists. sub usage {      print stderr "usage: $0 -h <server_url> [-e <extension>] [-o <output>] ";     print stderr "[-v] [-d] [-k <private_key.pem>] [-p <key_password>] ";     print stderr "[-c <client_cert.pem>] [-c <ca_certs.pem>] [-p <ca_path>] ";     print stderr "[-r <file:file...>] [-g <egd_socket>] [<request>]...\n";     exit 1; }  # ---------------------------------------------------------------------- #   main program # ----------------------------------------------------------------------  # getting command-line options (default comes tsget environment variable). $getopt_arg =  "h:e:o:vdk:p:c:c:p:r:g:"; if (exists $env{tsget}) {     @old_argv = @argv;     @argv = split /\s+/, $env{tsget};     getopts($getopt_arg, \%options) or usage;     @argv = @old_argv; } getopts($getopt_arg, \%options) or usage;  # checking argument consistency. if (!exists($options{h}) || (@argv == 0 && !exists($options{o}))     || (@argv > 1 && exists($options{o}))) {     print stderr "inconsistent command line options.\n";     usage; } # setting defaults. @argv = ("-") unless @argv != 0; $options{e} = ".tsr" unless defined($options{e});  # processing requests. $curl = create_curl $options{h}; undef $/;   # reading whole files. request: foreach (@argv) {     $input = $_;     ($base, $path) = fileparse($input, '\.[^.]*');     $output_base = $base . $options{e};     $output = defined($options{o}) ? $options{o} : $path . $output_base;      stderr->printflush("$input: ") if $options{v};     # read request.     $body;     if ($input eq "-") {     # read request stdin;     $body = <stdin>;     } else {     # read request file.         open input, "<" . $input         or warn("$input: not open input file: $!\n"), next request;         $body = <input>;         close input         or warn("$input: not close input file: $!\n"), next request;     }      # send request.     stderr->printflush("sending request") if $options{v};      ($ts_body, $error) = get_timestamp $curl, \$body;     if (defined($error)) {     die "$input: fatal error: $error\n";     }     stderr->printflush(", reply received") if $options{v};      # write response.     if ($output eq "-") {     # write stdout.         print $ts_body;     } else {     # write file.         open output, ">", $output         or warn("$output: not open output file: $!\n"), next request;         print output $ts_body;         close output         or warn("$output: not close output file: $!\n"), next request;     }     stderr->printflush(", $output written.\n") if $options{v}; } $curl->cleanup(); www::curl::easy::global_cleanup(); 

output of script

version: 1 hash algorithm: sha256 message data:     0000 - a8 31 60 9c a3 fe 14 74-05 f1 78 89 5c a6 a5   .1`....t...x.\..     0010 - d3 b7 4a 7d 18 b9 d0 f9-39 fc a8 d6 e2 2e 27   ..j}....9......' policy oid: unspecified nonce: 0x533ac264c90c4eee certificate required: yes extensions:  undefined subroutine &www::curl::easy::global_cleanup called @ /usr/local/bin/tsget line 196. status info: status: granted. status description: unspecified failure info: unspecified  tst info: version: 1 policy oid: 1.3.6.1.4.1.4146.2.2 hash algorithm: sha256 message data:     0000 - a8 31 60 9c a3 fe 14 74-05 f1 78 89 5c a6 a5   .1`....t...x.\..     0010 - d3 b7 4a 7d 18 b9 d0 f9-39 fc a8 d6 e2 2e 27   ..j}....9......' serial number: 0x3a668e2441a3707cb495191dc3ef2d717c49dd30 time stamp: sep 25 16:55:34 2015 gmt accuracy: unspecified ordering: no nonce: 0x533ac264c90c4eee tsa: dirname:/c=sg/o=gmo globalsign pte ltd/cn=globalsign tsa standard - g2 extensions:  verification: failed 3073967804:error:2f06d064:time stamp routines:ts_verify_cert:certificate verify error:ts_rsp_verify.c:246:verify error:unable local issuer certificate 

ok, did find answer: http://tsa.safecreative.org/

after googling, started impression although posts 1 this one , this one , this one , this one made seem globalsign , verisign , friends each run free timestamping server, under impression they're not free. think it's free "add on" other products sell, perhaps. possible timestamp servers, can't validate timestamp without certificate, not seem freely available. if knows otherwise, free correct me.

on other hand, http://tsa.safecreative.org/ free website (or, 5 stamps per day per ip address free), can download certificate verify timestamp. that's looking for.


Comments