84 lines
2.4 KiB
Nix
84 lines
2.4 KiB
Nix
{pkgs ? import <nixpkgs> {}}:
|
|
pkgs.python3Packages.buildPythonApplication rec {
|
|
pname = "tor-hostname";
|
|
version = "1.0.0";
|
|
|
|
format = "other";
|
|
|
|
propagatedBuildInputs = with pkgs.python3Packages; [
|
|
pynacl
|
|
cryptography
|
|
];
|
|
|
|
dontUnpack = true;
|
|
|
|
installPhase = ''
|
|
mkdir -p $out/bin
|
|
cat > $out/bin/tor-hostname <<'EOF'
|
|
#!/usr/bin/env python3
|
|
"""Convert Tor v3 secret key to .onion hostname"""
|
|
|
|
import hashlib
|
|
import base64
|
|
import sys
|
|
|
|
def onion_address_from_public_key(public_key):
|
|
"""Generate .onion address from ed25519 public key"""
|
|
version = b'\x03'
|
|
checksum = hashlib.sha3_256(b'.onion checksum' + public_key + version).digest()[:2]
|
|
onion_address = base64.b32encode(public_key + checksum + version).decode().lower()
|
|
return f"{onion_address}.onion"
|
|
|
|
def read_tor_secret_key(filepath):
|
|
"""Read Tor hs_ed25519_secret_key file"""
|
|
with open(filepath, 'rb') as f:
|
|
content = f.read()
|
|
|
|
header = b'== ed25519v1-secret: type0 ==\x00\x00\x00'
|
|
|
|
if not content.startswith(header):
|
|
raise ValueError("Invalid Tor secret key file format")
|
|
|
|
expanded_key = content[32:96]
|
|
return expanded_key
|
|
|
|
def derive_public_from_expanded_secret(expanded_key):
|
|
"""Derive ed25519 public key from 64-byte expanded secret key"""
|
|
from nacl.bindings import crypto_scalarmult_ed25519_base_noclamp
|
|
|
|
secret_scalar = expanded_key[:32]
|
|
public_key = crypto_scalarmult_ed25519_base_noclamp(secret_scalar)
|
|
return public_key
|
|
|
|
def main():
|
|
if len(sys.argv) != 2:
|
|
print(f"Usage: {sys.argv[0]} <path_to_hs_ed25519_secret_key>")
|
|
sys.exit(1)
|
|
|
|
secret_key_path = sys.argv[1]
|
|
|
|
try:
|
|
expanded_key = read_tor_secret_key(secret_key_path)
|
|
public_key = derive_public_from_expanded_secret(expanded_key)
|
|
hostname = onion_address_from_public_key(public_key)
|
|
print(hostname)
|
|
except FileNotFoundError:
|
|
print(f"Error: File not found: {secret_key_path}")
|
|
sys.exit(1)
|
|
except Exception as e:
|
|
print(f"Error: {e}")
|
|
sys.exit(1)
|
|
|
|
if __name__ == '__main__':
|
|
main()
|
|
EOF
|
|
|
|
chmod +x $out/bin/tor-hostname
|
|
'';
|
|
|
|
meta = with pkgs.lib; {
|
|
description = "Convert Tor v3 secret key to .onion hostname";
|
|
license = licenses.mit;
|
|
platforms = platforms.unix;
|
|
};
|
|
}
|