[tor-talk] Validating the DA authority document

Matthew Finkel matthew.finkel at gmail.com
Mon Feb 24 00:01:20 UTC 2020

On Sun, Feb 23, 2020 at 12:13 PM Gary Chapman <garychapman72 at gmail.com> wrote:
> Hi community,
> I've tried reading the TOR docs, but I can't seem to wrap my head around

"Tor" [0]

> how the authority document works (as regards signature validation) ... I've
> gotten circuit building working in a standalone c# library, but I'm
> struggling with validating the directory.
> For clarity, the document I am referring to, is the following :

Good, I assume you already read the dir-spec? [1]

With respect to keys, it's important to understand which keys exist
and how they are used.

In the "how version 3 should be better than version 2" section (0.2):

      * The most sensitive data in the entire network (the identity keys
        of the directory authorities) needed to be stored unencrypted so
        that the authorities can sign network-status documents on the fly.
        Now, the authorities' identity keys are stored offline, and used
        to certify medium-term signing keys that can be rotated.

Therefore, we know authorities has (at least) two keys, their identity key and
their signing key.

Looking at section (appendix?) B "General-use HTTP URLs",

   The key certificate for this server (if it is an authority) should be
   available at:


This document provides all public keys associated with this authority, so you
are following the correct path.

The document (currently) contains four public keys, along with some metadata
(see 3.1. Creating key certificates for more details):

  1) version number of this certificate
  2) the authority's identity key fingerprint
  3) the period for which this certification is valid
  4) the directory's long-term (RSA) identity key
  5) the directory's medium-term (RSA) signing key
  6) a signature item 4 using the medium-term signing key
  7) a signature over items 1-6 (plus the header of 7) using the long-term
     identity key

In particular, see section 1.3 for how a signature is computed over a document.

You can take the public keys and process them with openssl, if you want to
sanity-check your implementation (either paste the key directly on the command
line as input to this command, or provide it in a file and add the |-in
<filename>| arguments):

  $ openssl rsa -RSAPublicKey_in -noout -text
  RSA Public-Key: (3072 bit)

The important piece of this part  that you should notice is that this key is
using the RSA Public Key PEM format.

> I've tried verifying various areas of the document ...
> With various line endings CRLF/LFCR/LF/CR
> With various signature algorithms SHA1withRSA / SHA256withRSA / etc
> With both of the footer signatures
> I am using the "dir identity" RSA key at the top of the document as the
> reference key to verify against - I'm assuming this is correct, it's the
> only thing I can find that looks like the top level key.
> Unfortunately, no matter what I try, I just get a signature mismatch every
> time and I'm running out of sensible permutations.  Clearly I'm missing
> something.
> Could some kind soul please point me in the right direction?

Following from the above, next, if you want to validate the signature on
this certificate using openssl apps, then it is a two-step process (as far
I can figure out):

  1) Obtain the digest of the document to-be-signed
  2) Get the digest from the signature
  3) Verify the two digests are identical

For (1), you can obtain this with:
  $ openssl dgst -sha1 -binary tor26-certificated_text | openssl base64

For (2), you can obtain this with:
  $ openssl rsautl -verify -inkey tor26_id_key -pubin -keyform PEM -in
tor26-certificated_text.bin.sig | openssl base64

(As a side note, I tried very hard getting openssl dgst to validate this
directly, but it expects the signature as a DigestInfo without padding and I
don't know how to transform the sig into that format.)

In the above example, |tor26-certificated_text| is the certificate excluding
the final signature (as defined in section 1.3). |tor26_id_key| is the identity
public key converted from PKCS#1 RSAPEM format to X.509 SubjectPublicKeyInfo
PEM.  |tor26-certificated_text.bin.sig| is the the signature at the bottom of
the file, with the SIGNATURE header and trailer stripped, and base64 decoded.

For the PEMRSA to PEM conversion, I used:

  $ openssl rsa -in tor26_rsa_id_key -RSAPublicKey_in -pubout -out tor26_id_key

When you obtain the two digests, then you can byte-for-byte compare them
however you'd like.

In the above example, I chose to encode them in base64 so that I could easily
compare them on the command line. You can leave them as binary data and compare
them however you'd like.

If the two digests are identical, then the signature is valid.

I'll skip the cross-certification signature and leave that as an exercise :)

Verifying the signature on a network-status document follows the above pattern,
except in this case the directory authority's signing key is used instead of the
identity key.

The dir-spec explains that the signature is over the data beginning with
"network-status-version" and ending with "directory-signature ".

Similar to the above commands:
  $ openssl rsautl -pubin -inkey tor26_signing_key -in
tor26-consensus-consensus_signed.bin.sig | openssl base64

All signatures appended on the consensus (should) be over the same digest, so
it doesn't matter which signature you use.

The digest of the consensus follows similarly:
  $ openssl dgst -sha1 -binary consensus_signed | openssl base64

I assume whichever crypto library you're using provide an API for directly
verifying a signature over the document, so as long as you are using the
correct public key and the correct header of the document, then
verification should be "easy". I hope this helps point you in the
right direction.

- Matt

[0] https://2019.www.torproject.org/docs/faq.html.en#WhyCalledTor
[1] https://spec.torproject.org/dir-spec

More information about the tor-talk mailing list