Skip to content

Instantly share code, notes, and snippets.

@mtigas
Last active September 20, 2024 18:35
Show Gist options
  • Save mtigas/9c2386adf65345be34045dace134140b to your computer and use it in GitHub Desktop.
Save mtigas/9c2386adf65345be34045dace134140b to your computer and use it in GitHub Desktop.
experiments with using v3 onions with client auth (as of tor 0.3.5.X)
#!/bin/bash
# needs openssl 1.1+
# needs `basez` https://manpages.debian.org/testing/basez/base32hex.1.en.html
# (but something else that decodes the base64 and re-encodes the raw key bytes
# to base32 is probably fine too)
##### generate a key
openssl genpkey -algorithm x25519 -out /tmp/k1.prv.pem
##### re-formatting the keys into base32 in a way that tor likes:
# basically take the base64pem from the above key file, decode it to raw binary data,
# strip the PKCS header (key is final 32bytes of the raw data), re-encode it into base32,
# strip the "=" padding
cat /tmp/k1.prv.pem |\
grep -v " PRIVATE KEY" |\
base64pem -d |\
tail --bytes=32 |\
base32 |\
sed 's/=//g' > /tmp/k1.prv.key
openssl pkey -in /tmp/k1.prv.pem -pubout |\
grep -v " PUBLIC KEY" |\
base64pem -d |\
tail --bytes=32 |\
base32 |\
sed 's/=//g' > /tmp/k1.pub.key
##### do the outputs
echo "X25519 Private Key:"
cat /tmp/k1.prv.key
echo
echo "X25519 Public Key: (give this to the onion service)"
cat /tmp/k1.pub.key
echo
echo "====="
echo "Tor client configuration"
echo "====="
echo "Make sure you have ClientOnionAuthDir set in your torrc. In the"
echo "<ClientOnionAuthDir> directory, create an '.auth_private' file for the"
echo "onion service corresponding to this key (i.e. 'bob_onion.auth_private')."
echo "The contents of the <ClientOnionAuthDir>/<user>.auth_private file should"
echo "look like:"
echo
echo " <56-char-onion-addr-without-.onion-part>:descriptor:x25519:`cat /tmp/k1.prv.key`"
echo
echo "i.e.:"
echo " p53lf57qovyuvwsc6xnrppyply3vtqm7l6pcobkmyqsiofyeznfu5uqd:descriptor:x25519:`cat /tmp/k1.prv.key`"
echo
echo "====="
echo "Onion service configuration"
echo "====="
echo "Inside the HiddenServiceDir for this onion service, create an"
echo "/authorized_clients/ subdirectory and a '.auth' file for the user (i.e."
echo "'alice.auth'). The contents of the <HiddenServiceDir>/authorized_clients/<username>.auth"
echo "file should look like:"
echo
echo " descriptor:x25519:`cat /tmp/k1.pub.key`"
rm -f /tmp/k1.pub.key /tmp/k1.prv.key /tmp/k1.prv.pem
X25519 Private Key:
BBBEAUAO3PIFAH7SBGBI6A2QFAZBXG2NVN7HMBXFCZENJVF6C5AQ
X25519 Public Key: (give this to the onion service)
SUCXD2A4YRK4JQ37QCIAQXGASQWVLFH45XENCC5YDZFR6RIT6ETA
=====
Tor client configuration
=====
Make sure you have ClientOnionAuthDir set in your torrc. In the
<ClientOnionAuthDir> directory, create an '.auth_private' file for the
onion service corresponding to this key (i.e. 'bob_onion.auth_private').
The contents of the <ClientOnionAuthDir>/<user>.auth_private file should
look like:
<56-char-onion-addr-without-.onion-part>:descriptor:x25519:BBBEAUAO3PIFAH7SBGBI6A2QFAZBXG2NVN7HMBXFCZENJVF6C5AQ
i.e.:
p53lf57qovyuvwsc6xnrppyply3vtqm7l6pcobkmyqsiofyeznfu5uqd:descriptor:x25519:BBBEAUAO3PIFAH7SBGBI6A2QFAZBXG2NVN7HMBXFCZENJVF6C5AQ
=====
Onion service configuration
=====
Inside the HiddenServiceDir for this onion service, create an
/authorized_clients/ subdirectory and a '.auth' file for the user (i.e.
'alice.auth'). The contents of the <HiddenServiceDir>/authorized_clients/<username>.auth
file should look like:
descriptor:x25519:SUCXD2A4YRK4JQ37QCIAQXGASQWVLFH45XENCC5YDZFR6RIT6ETA
@nyxnor
Copy link

nyxnor commented Dec 11, 2021

Use tail -c 32 for posix.
Also, on openbsd, the openssl command is called eopenssl11 or eopenssl30 depending on the version installed via pkg_add.
There is no basez port on opensbd but it is coming soon.

#!/usr/bin/env sh

openssl_command="eopenssl30" ## [openssl|eopenssl11|eopenssl30]
"${openssl_command}" genpkey -algorithm x25519 -out /tmp/k1.prv.pem
grep -v " PRIVATE KEY" /tmp/k1.prv.pem | base64pem -d | tail -c 32 | base32 | sed "s/=//g" > /tmp/k1.prv.key
"${openssl_command}" pkey -in /tmp/k1.prv.pem -pubout | grep -v " PUBLIC KEY" | base64pem -d | tail -c 32 | base32 | sed "s/=//g" > /tmp/k1.pub.key

@stokito
Copy link

stokito commented May 11, 2022

Hi, please pull my version https://gist.github.com/stokito/8d1fb41a3834deaf27f5619dc2bbb061
I adopted the script for OpenWrt.

Changes:

  • Use /bin/sh shebang. No need to use bash here
  • The base64pem replaced with plain base64. The string is anyway smaller than 76. The base64pem is not available on OpenWrt.
  • Use tail -c 32 for posix as @nyxnor mentioned. The BusyBox's tail doesn't have --bytes

Thank you.

@stokito
Copy link

stokito commented May 12, 2022

Turned out that for OpenWrt there is package tor-gencert for "Generate certs and keys for Tor directory authorities".
Also see https://openwrt.org/docs/guide-user/services/tor/hs#client_authorization_old

@balki
Copy link

balki commented Sep 20, 2024

I created a simpler script in golang with zero dependencies for this.

❯ go run go.balki.me/onion-auth-gen@latest
private key       : KPNW2PPM4EZRNUWYDXRYBUB2D5G73RLVQTELWBT7RDYELTOSBESA
public descriptor : descriptor:x25519:DBOQW4FQU6XFTELGIFTJCOK3S4NIV4H5LU64R2SJ3NF7VUEIOBHA

source : https://gitea.balki.me/balki/onion-auth-gen
play: https://go.dev/play/p/xs8OKwEMeiK
feedback: https://toot.io/@balki@balki.me/113161952110702933

@stokito
Copy link

stokito commented Sep 20, 2024

@balki the Golang is not a script, but a program compiled to a native code. If you are looking for a generator in the Golang see my version https://github.com/stokito/oniongen-go/tree/optimization

In your sample you incorrectly generating a public key: it lacks of version and checksum.
Basically it's not that important because once you have a private key the Tor will generate the hostname file itself from the private key.

@balki
Copy link

balki commented Sep 20, 2024

@stokito It is not generating onion address / hostname. this is for generating client authorization key pair. Alternative to this

@stokito
Copy link

stokito commented Sep 20, 2024

@balki yeah, sorry, I missed this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment