
GoBalance Bug Reveals Tor Onion Master Keys
GoBalance Bug Reveals Tor Onion Master Keys
A dark-web site's .onion address looks like a random string, but it is really a public key. Whoever holds the matching private key controls that address. On 8 October 2026, the security firm Searchlight Cyber disclosed a flaw in GoBalance, a load balancer used by many hidden services, that let anyone recover that private key from a single piece of public data. No break-in, no server access — just a descriptor anybody on the Tor network can fetch (Searchlight Cyber).
The week before, two of the Dread forum's onion addresses had been hijacked and pointed at a rival site. Dread's operators first blamed their own mistake. The flaw is a better explanation for at least the second takeover — and it is a clean lesson in how one wrong function call can quietly destroy the security of a whole cryptographic scheme.
What an onion address really is
A v3 onion address is the base32 encoding of an ed25519 public key, plus a version and checksum (Tor address spec). The service holds the matching secret key and uses it to sign a small record — a descriptor — that tells the Tor network where to route traffic. Anyone can fetch that descriptor; that is the point. It is signed so that clients can verify it without the operator handing out the key.
To sign a descriptor, you need the service's master identity key. In the world of Tor's reference implementation, that key is unusual. It is not the 32-byte seed you might expect. Tor stores the key already expanded: a file called hs_ed25519_secret_key holds 64 bytes — a 32-byte secret scalar a, followed by a 32-byte value used to derive each signature's nonce. Call the second half h.
The seed form is the safer one, because it lets the software re-derive both halves with SHA-512 whenever it needs them. The expanded form skips that step: what is on disk is exactly what gets used.
The defect: 64 bytes in, 32 bytes used
GoBalance is a Go rewrite of Tor's OnionBalance, shipped inside the EndGame toolkit that dark-web operators use to survive DDoS attacks. In the rewrite, the descriptor-signing path had a subtle bug: when signing with a Tor-format key, it passed the signer only the first 32 bytes of the 64-byte key.
That is the whole bug. Here is the shape of it, reduced to the essentials:
// Tor hs_ed25519_secret_key is 64 bytes: scalar a (32) || nonce prefix h (32).
expanded := loadTorFormatKey() // len(expanded) == 64
// BUG: gobpk.Seed() returns ed25519.PrivateKey.Seed(), i.e. expanded[:32].
// Only "a" reaches the signer. "h" is silently dropped.
sig := util.BlindedSignWithTorKey(msg, privKey.Seed(), blindedKey, blindingNonce)
// FIXED: hand the signer the full expanded key so the nonce prefix survives.
sig := util.BlindedSignWithTorKey(msg, expanded, blindedKey, blindingNonce)
In Go, ed25519.PrivateKey.Seed() is defined to return the first 32 bytes — the seed. That is correct for a normal key, because the other half can be regenerated. But for a Tor-format key there is no seed to regenerate from. The code called Seed() on data that was never a seed, and the missing half h was lost.
Why losing h hands over the key
An ed25519 signature is a pair (R, S) where R = rB. The security of the scheme hinges on the nonce r staying secret. Normally r is derived from the secret half h and the message, so an attacker sees one equation with two unknowns — the nonce and the secret scalar — and cannot solve it.
Strip out h, and the nonce stops being secret. In GoBalance, the code splits the key and derives the nonce prefix from its second half. With the second half empty, that prefix becomes the SHA-512 of a fixed, public string — the same bytes for every service, every descriptor. The nonce is then a function of the signed message, and the message (the signing certificate) is published with the descriptor. The nonce is public.
That leaves a single unknown. Fetch a descriptor, read R, S, the message, the blinding nonce and the blinded public key, and the master secret scalar falls out of one linear equation. Because the descriptor also carries the public blinding nonce, the attacker can reverse the blinding step and recover the service's long-term master key directly (Searchlight Cyber).
That last detail is the worst part. This is not a short-lived key that rotates. It is the identity key the address is built on, so a recovered key can sign valid descriptors for that address far into the future.
What the flaw does and does not give you
It is worth being precise, because the headlines were not.
- It gives the attacker the address. They can publish their own descriptor and redirect visitors to a server they control, including a convincing copy of the original site.
- It does not give them the servers. The bug leaks the signing key, not the site's database, backend or stored user data. Getting user data from a takeover would need a further step such as traffic interception or phishing.
- It does not hit everyone running GoBalance. Only services whose master key is stored in Tor's own expanded format are affected. GoBalance's own setup tool writes keys in the safer 32-byte seed format, which the standard signing path handles correctly. So "runs GoBalance" is not the same as "exposed."
- It does not affect Tor or OnionBalance. The bug was introduced in the Go rewrite. The original tools are fine.
The fallout
Between 5 and 7 October, Dread — one of the largest dark-web forums — lost both of its onion addresses. The primary address was defaced on 5 October and pointed at a rival platform; the second, a backup reserved for premium members, was taken over two days later. That second takeover is the significant one: a single accidental key upload does not explain two independent keys being lost. Dread has since moved to a newly generated address and told users to change their passwords.
At least one other market, Omega, confirmed publicly on 8 October that it had pulled its old address "due to an issue caused by the GoBalance bug" and moved to a new one. How many other services are affected is not clear; Dread's operator said several markets were hit but did not name or count them.
As of 9 October there was no CVE, no advisory from the Tor Project, and no patch from GoBalance's maintainer (The Hacker News). An independent researcher published a patch and a working proof-of-concept that recovers a master key from a single public descriptor (GitHub). The demo used only test keys, and The Hacker News has not run the code.
Why this matters beyond the dark web
Strip away the setting and this is a general lesson about cryptographic code.
A convenience wrapper can hide a meaning change. Seed() is a perfectly sensible name. The bug is not in the name; it is that the function's contract ("return the first 32 bytes because the rest is derivable") stopped being true the moment the key came from Tor's expanded format. The code kept calling a seed function on a non-seed.
Public keys and descriptors are not just routing metadata. Anything that signs a descriptor is touching the site's long-term identity. The blast radius of a bug in that path is the identity itself, not one session.
You cannot un-leak a published descriptor. A patch fixes future behavior. It does not pull back a key that has already been exposed. Any service that ran a vulnerable version has to treat its address as burned and migrate to a new one — which is exactly what Dread and Omega did.
That pattern should be familiar to anyone who has handled a leaked credential. It is the same reason a rotated token beats a patched one: once the secret is out, the only real fix is to stop trusting it. You can see the same lesson in our write-up on GitLab's never-expiring issue-email tokens, where the remedy was rotating the token rather than patching around it.
For most developers this bug is a warning about a class of mistake, not a system you run. But if you write or maintain anything that handles keys — signing services, token issuers, custom crypto integrations — the GoBalance flaw is worth reading twice. The vulnerability was a single dropped half of a 64-byte value. Everything downstream was unrecoverable.
Sources
- Searchlight Cyber: Leaking the Keys to the Kingdom: How a Single Slip Handed Over a Darknet Empire
- The Hacker News: GoBalance Flaw Lets Attackers Hijack .onion Addresses by Recovering Tor-Format Keys
- GitHub: gobalance-patch - proof-of-concept key recovery
- The Tor Project: Tor v3 Onion Address Specification
- Go Documentation: crypto/ed25519
// author
Editor & Operator
Mohd Firdaus Abu Bakar (MrDodgerX) is an enterprise geospatial systems engineer in Malaysia and the editor behind hejes.my. He runs the briefing pipeline, curates and edits every draft, verifies each factual claim against primary sources, and presses the publish button — nothing ships without his review. He writes about AI, security and Malaysia's tech scene from a builder's perspective. Professional profile and code: the links below.
// sources //
fact-check verified · 12 OCT 2026 · hejes-content-fact-check
- Leaking the Keys to the Kingdom: How a Single Slip Handed Over a Darknet EmpireSearchlight Cyber · accessed 12 OCT 2026
- GoBalance Flaw Lets Attackers Hijack .onion Addresses by Recovering Tor-Format KeysThe Hacker News · accessed 12 OCT 2026
- gobalance-patch - proof-of-concept key recoveryGitHub · accessed 12 OCT 2026
- Tor v3 Onion Address SpecificationThe Tor Project · accessed 12 OCT 2026
- crypto/ed25519Go Documentation · accessed 12 OCT 2026
related //

Flock's CEO says just gunshots. Its website says more.
Flock's CEO told Disrupt its audio sensors detect "just gunshots", but the company's own product page and FAQ list crashes, fireworks, and sideshows too.
Three Remote Hacks Hit a Fully Patched Pixel 10
At Pwn2Own Ireland, three teams broke into a fully patched Google Pixel 10 over the network on the same day, splitting $562,500 in prizes.

LMCache CVE-2026-105192: Unpatched 9.8 RCE
LMCache unpickles data straight off an unauthenticated socket. One message is RCE, your exposure is one flag wide, and no patch exists.
// join the feed
one fresh insight per week. no spam, ever.
weekly digest. unsubscribe anytime.