Fix Tor v3 onion address checksum: SHA-256 -> SHA3-256

The Tor v3 spec requires SHA3-256 (FIPS-202) for the .onion address
checksum computation, but ToStringIP() was using SHA-256 (double-hash).
This caused every reconstructed .onion address to have incorrect suffix
characters, making all outbound Tor connections fail with SOCKS5 'general
failure' - the entire network had 0 Tor peers despite working Tor instances.

Fix: Replace Hash() call with OpenSSL EVP_sha3_256() which is available
in OpenSSL 3.0+ and produces the correct FIPS-202 SHA3-256 checksum.

Tested: All 5 onion seed nodes now connect successfully.
This commit is contained in:
Krystie
2026-04-02 14:16:02 -07:00
parent 2fba88bfc5
commit 4be70e8f6a
2 changed files with 11 additions and 6 deletions
+1 -1
View File
@@ -8,7 +8,7 @@
// These need to be macros, as version.cpp's and triangles-qt.rc's voodoo requires it
#define CLIENT_VERSION_MAJOR 5
#define CLIENT_VERSION_MINOR 5
#define CLIENT_VERSION_REVISION 0
#define CLIENT_VERSION_REVISION 1
#define CLIENT_VERSION_BUILD 0
// Converts the parameter X to a string after macro replacement on X has been performed.
+10 -5
View File
@@ -6,6 +6,7 @@
#include "netbase.h"
#include "util.h"
#include "sync.h"
#include <openssl/evp.h>
#ifndef WIN32
#include <sys/fcntl.h>
@@ -860,15 +861,19 @@ std::string CNetAddr::ToStringIP() const
unsigned char addr35[35];
memcpy(addr35, tor_v3_pubkey, 32);
// Compute checksum: SHA3-256(".onion checksum" || pubkey || version)[:2]
// For now use a simplified checksum from the stored data
unsigned char checksumInput[15 + 32 + 1];
memcpy(checksumInput, ".onion checksum", 15);
memcpy(checksumInput + 15, tor_v3_pubkey, 32);
checksumInput[47] = 0x03; // version
// SHA-256 as fallback (SHA3-256 via tor_crypto_compat.h for full impl)
uint256 hash = Hash(checksumInput, checksumInput + 48);
addr35[32] = ((unsigned char*)&hash)[0];
addr35[33] = ((unsigned char*)&hash)[1];
unsigned char sha3hash[32];
unsigned int sha3len = 0;
EVP_MD_CTX *mdctx = EVP_MD_CTX_new();
EVP_DigestInit_ex(mdctx, EVP_sha3_256(), NULL);
EVP_DigestUpdate(mdctx, checksumInput, 48);
EVP_DigestFinal_ex(mdctx, sha3hash, &sha3len);
EVP_MD_CTX_free(mdctx);
addr35[32] = sha3hash[0];
addr35[33] = sha3hash[1];
addr35[34] = 0x03; // version
return EncodeBase32(addr35, 35) + ".onion";
}