1 Title: Fetching trusted timestamps using the rfc3161ng python module
2 Tags: english, sikkerhet, noark5
5 <p>I have earlier covered the basics of trusted timestamping using the
6 'openssl ts' client. See blog post for
7 <a href="http://www.hungry.com/~pere/blog/Public_Trusted_Timestamping_services_for_everyone.html">2014</a>,
8 <a href="http://www.hungry.com/~pere/blog/syslog_trusted_timestamp___chain_of_trusted_timestamps_for_your_syslog.html">2016</a>
10 <a href="http://www.hungry.com/~pere/blog/Idea_for_storing_trusted_timestamps_in_a_Noark_5_archive.html">2017</a>
11 for those stories. But some times I want to integrate the timestamping
12 in other code, and recently I needed to integrate it into Python.
13 After searching a bit, I found
14 <a href="https://dev.entrouvert.org/projects/python-rfc3161">the
15 rfc3161 library</a> which seemed like a good fit, but I soon
16 discovered it only worked for python version 2, and I needed something
17 that work with python version 3. Luckily I next came across
18 <a href="https://github.com/trbs/rfc3161ng/">the rfc3161ng library</a>,
19 a fork of the original rfc3161 library. Not only is it working with
20 python 3, it have fixed a few of the bugs in the original library, and
21 it has an active maintainer. I decided to wrap it up and make it
22 <a href="https://tracker.debian.org/pkg/python-rfc3161ng">available in
23 Debian</a>, and a few days ago it entered Debian unstable and testing.</p>
25 <p>Using the library is fairly straight forward. The only slightly
26 problematic step is to fetch the required certificates to verify the
27 timestamp. For some services it is straight forward, while for others
28 I have not yet figured out how to do it. Here is a small standalone
29 code example based on of the integration tests in the library code:</p>
36 Python 3 script demonstrating how to use the rfc3161ng module to
37 get trusted timestamps.
39 The license of this code is the same as the license of the rfc3161ng
45 import pyasn1.codec.der
56 def fetch(url, f=None):
57 response = urllib.request.urlopen(url)
58 data = response.read()
64 with tempfile.NamedTemporaryFile() as cert_f,\
65 tempfile.NamedTemporaryFile() as ca_f,\
66 tempfile.NamedTemporaryFile() as msg_f,\
67 tempfile.NamedTemporaryFile() as tsr_f:
69 # First fetch certificates used by service
70 certificate_data = fetch('https://freetsa.org/files/tsa.crt', cert_f)
71 ca_data_data = fetch('https://freetsa.org/files/cacert.pem', ca_f)
73 # Then timestamp the message
75 rfc3161ng.RemoteTimestamper('http://freetsa.org/tsr',
76 certificate=certificate_data)
77 data = b"Python forever!\n"
78 tsr = timestamper(data=data, return_tsr=True)
80 # Finally, convert message and response to something 'openssl ts' can verify
82 store(tsr_f, pyasn1.codec.der.encoder.encode(tsr))
83 args = ["openssl", "ts", "-verify",
87 "-untrusted", cert_f.name]
88 subprocess.check_call(args)
90 if '__main__' == __name__:
94 <p>The code fetches the required certificates, store them as temporary
95 files, timestamp a simple message, store the message and timestamp to
96 disk and ask 'openssl ts' to verify the timestamp. A timestamp is
97 around 1.5 kiB in size, and should be fairly easy to store for future
100 <p>As usual, if you use Bitcoin and want to show your support of my
101 activities, please send Bitcoin donations to my address
102 <b><a href="bitcoin:15oWEoG9dUPovwmUL9KWAnYRtNJEkP1u1b">15oWEoG9dUPovwmUL9KWAnYRtNJEkP1u1b</a></b>.</p>