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