Hi Ops,
We recently began responding to t-shirt requests again. Sorry for the
long silence. There's been a lot happening around here but not enough
time or people to do everything, so the t-shirt requests simply remained
untouched. But, despite the overload, t-shirts are important because
they are a small token of our thanks and appreciation for making the
network what it is today.
We responded to around 70 t-shirt requests from relay operators in
April, which comprised all requests for which we could verify (within
reason) the request came from the person who controlled the qualifying
relay. We still have another 20 requests where the requestor is not
obviously the owner of the relay. Currently the content of a relay's
Contact field is used, but this does not always provide enough (or any)
information. For this case, we need an authentication mechanism which
proves control of the relay but is something relay operators won't mind
running.
My currently plan is to ask relay operators to sign the fingerprint file
which tor creates. The major disadvantage of this method is that it must
be run as root (or a user with access to tor's data directory).
The following process is the current plan, but does anyone have a better
idea? Does it seem logical?
------------------------------------------------------------
When we receive a t-shirt request from someone who isn't obviously in
control of the relay, we ask them to sign their fingerprint file with
a unique salt.
Assuming the path to their data dir is /var/lib/tor, we ask them to run:
$ (echo -n "salt "; cat /var/lib/tor/fingerprint) | openssl sha256 \
-binary | openssl pkeyutl -inkey /var/lib/tor/keys/secret_id_key \
-sign -pkeyopt digest:sha256 -pkeyopt rsa_padding_mode:pss \
-pkeyopt rsa_pss_saltlen:32 | openssl base64 > signed_fingerprint
They send us both /var/lib/tor/fingerprint and signed_fingerprint.
When we receive them, we confirm the fingerprint in the fingerprint file
matches the qualifying relay. Then we retrieve the relay's public key
from its descriptor and convert it into pkcs#8 format using:
$ openssl rsa -pubin -in pubkey_pkcs1 -RSAPublicKey_in -out pubkey
and then we verify the sig using following commands:
$ (echo -n "salt "; cat fingerprint) | openssl sha256 -binary | \
openssl pkeyutl -pubin -verify -inkey pubkey -sigfile \
$(OUT=/tmp/signed_fingerprint_bin; base64 -d signed_fingerprint > \
${OUT}; echo ${OUT}) -pkeyopt digest:sha256 -pkeyopt \
rsa_padding_mode:pss -pkeyopt rsa_pss_saltlen:32; rm \
/tmp/signed_fingerprint_bin;
This should yield "Signature Verified Successfully".
------------------------------------------------------------
Another disadvantage of this is PSS wasn't implemented in openssl's
apps until 1.0.1. I wonder how many relays are running on servers which
are still using openssl 0.9.8 (and 1.0.0?). For these servers we can
fallback on pkcs#1 v1.5 signatures.
------------------------------------------------------------
The signature can be created using a command similar to the one above:
$ (echo -n "salt "; cat /var/lib/tor/fingerprint) | openssl dgst \
-sha256 | openssl rsautl -inkey /var/lib/tor/keys/secret_id_key \
-sign | openssl base64 > signed_fingerprint
Again, they provide /var/lib/tor/fingerprint and signed_fingerprint,
and we verify using:
$ test "$(openssl base64 -d -in signed_fingerprint | openssl rsautl \
-pubin -verify -inkey pubkey)" = "$((echo -n "salt "; cat \
fingerprint) | openssl dgst -sha256)"; echo $?
In addition, again, we confirm the fingerprint in the fingerprint file
matches the fingerprint of the qualifying relay.
------------------------------------------------------------
Originally I used a few bashisms which made these simpler, but for
this I suspect portability is important.
Sorry this is a bit long.
Thanks,
Matt