0

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]] } 

1 Answer 1

1

Problem solved. The secret key had to be expanded first, and then the public key was derived from it.

use base32::{encode, Alphabet}; use sha3::{Digest, Sha3_256}; use std::{fs, io}; use ed25519_dalek::hazmat::ExpandedSecretKey; use ed25519_dalek::VerifyingKey; const VERSION: u8 = 0x03; const SALT: &[u8] = b".onion checksum"; fn main() -> io::Result<()> { let client_sc = fs::read("hs_ed25519_secret_key2")?; let fixed = extract_secret(&client_sc); let exp1 = ExpandedSecretKey::from_bytes(&fixed); let exp = VerifyingKey::from(&exp1); let exp_bytes = exp.as_bytes(); let pubkey = fs::read("hs_ed25519_public_key2")?; let public = extract_pubkey(&pubkey); println!("Domain from hs_ed25519_secret_key (derived): {}", get_service_id(&exp_bytes)); println!("Domain from hs_ed25519_public_key: {}", get_service_id(&public)); Ok(()) } fn extract_secret(data: &[u8]) -> [u8; 64] { let key_bytes = &data[32..96]; key_bytes.try_into().unwrap() } fn extract_pubkey(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]] } 

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.