multiformats / rust-multiaddr

multiaddr implementation in rust
https://crates.io/crates/multiaddr
Other
86 stars 45 forks source link

feat: validate onion3 addresses #93

Open sdbondi opened 1 year ago

sdbondi commented 1 year ago

You can currently create invalid onion3 addresses:

   let mut b = [0u8; 35];
   OsRng.fill_bytes(&mut b);
   let addr = multiaddr::Onion3Addr::from((b, 12345u16));
   let invalid = multiaddr!(Onion3(addr));

Resulting in these error logs in tor

Jun  5 10:10:44 thor Tor[692]: Service address "pd6sf3mqkkkfrn4rk5odgcr2j5sn7m523a4tm7pzpuotk2b7rpuhaeym" invalid checksum.
Jun  5 10:10:44 thor Tor[692]: Invalid onion hostname pd6sf3mqkkkfrn4rk5odgcr2j5sn7m523a4tm7pzpuotk2b7rpuhaeym.onion; rejecting

Question: Should we be validating the checksum and/or the public key in this library? Defined as follows:

  onion_address = base32(PUBKEY | CHECKSUM | VERSION) + ".onion"
     CHECKSUM = H(".onion checksum" | PUBKEY | VERSION)[:2]

     where:
       - PUBKEY is the 32 bytes ed25519 master pubkey of the hidden service.
       - VERSION is a one byte version field (default value '\x03')
       - ".onion checksum" is a constant string
       - CHECKSUM is truncated to two bytes before inserting it in onion_address

source: https://github.com/torproject/torspec/blob/main/rend-spec-v3.txt#LL2258C6-L2258C6

This would introduce a number of dependencies: base32(edit: not required due to existing data-encoding dep), sha3 and an ed25519 library if we decided to validate the PUBKEY.

In many cases the user can leave it to tor, but you may not want to e.g. include the address in a database if it is invalid.

I wanted thoughts on if this is in scope for this library or if this validation should be left up to the user.

I'd be happy to work on a PR for this if this is in scope. Changes should be fairly minor: Fallible TryFrom impl, decoding the address and verifying the checksum, version and possibly the ed25519 key, and adding some new tests.