The result of the verifying_key() method is VerifyingKey (PublicKey) that is not the same as the true PublicKey in the hs_ed25519_public_key file. I’ve been trying to solve this for a few days now and searching for information, but I haven’t found anything relevant. I’m using the public and private keys of the respective hidden service, but I get a completely different onion domain. The key pair is correct.
I think the problem has to do something related with the private key since the only one that gives me the real domain is the public key from the hs_ed25519_public_key file.
use base32::{encode, Alphabet}; use ed25519_dalek::SigningKey; use sha3::{Digest, Sha3_256}; use std::{fs, io}; const VERSION: u8 = 0x03; const SALT: &[u8] = b".onion checksum"; fn main() -> io::Result<()> { let client_sc = fs::read("hs_ed25519_secret_key")?; let fixed = extract_key(&client_sc); let signing_key = SigningKey::from_bytes(&fixed); let client_pk = signing_key.verifying_key(); let secret = client_pk.as_bytes(); let pubkey = fs::read("hs_ed25519_public_key")?; let public = extract_key(&pubkey); println!("Domain from hs_ed25519_secret_key (derived): {}", get_service_id(&secret)); println!("Domain from hs_ed25519_public_key: {}", get_service_id(&public)); // valid domain Ok(()) } fn extract_key(data: &[u8]) -> [u8; 32] { let key_bytes = &data[32..64]; key_bytes.try_into().unwrap() } fn get_service_id(public_key: &[u8; 32]) -> String { let checkdigits = get_checkdigits(public_key); let mut combined = Vec::new(); combined.extend_from_slice(public_key); combined.extend_from_slice(&checkdigits); combined.push(VERSION); let encoded = encode(Alphabet::Rfc4648 { padding: false }, &combined); encoded.to_lowercase() } fn get_checkdigits(public_key: &[u8; 32]) -> [u8; 2] { let mut hasher = Sha3_256::new(); hasher.update(SALT); hasher.update(public_key); hasher.update([VERSION]); let checksum = hasher.finalize(); [checksum[0], checksum[1]] }