Skip to content

New Onion enrollment proposal - #17

Open
lsd-cat wants to merge 2 commits into
mainfrom
onion-draft
Open

New Onion enrollment proposal#17
lsd-cat wants to merge 2 commits into
mainfrom
onion-draft

Conversation

@lsd-cat

@lsd-cat lsd-cat commented May 22, 2026

Copy link
Copy Markdown
Member

Comment thread onion.md Outdated

- `sig_wc` verifies under `KP_wc_blind` over `statement`.
- `sig_tor` verifies under `KP_hs_blind` over `statement`.
- `period_num` is the current Tor time period (within a small tolerance

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

from https://github.com/torproject/torspec/blob/main/rend-spec-v3.txt#L740-L768:

  • the length of this Tor time period is controlled via a Tor consensus parameter hsdir-interval
  • the rotation offset is fixed afaict

so presumably:

  • we can use consensus BFT time for the wall clock part (all validators need to agree on this)
  • if the hsdir-interval is not expected to change then we can hardcode it and the rotation offset. but we can put both parameters in the chain parameters so we can just make a config update if it ever changes

@lsd-cat lsd-cat May 26, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it's ever expected to change, but to be safe I'd agree on chain parameters. I'm not sure we need the tolerance in practice, Tor has it but it's also that big onion services might have thousands of concurrent users with their own clock drift. As in WEBCAT this is basically a one time check, we can probably be fine without if we implement the client properly (to avoid building a proof at 11.50pm with the previous day derivation).

Comment thread onion.md Outdated
Comment thread onion.md
| | value |
|---|---|
| Trusted setup (one-time) | ~8 min, ~7 GB peak RAM |
| Proving key | ~3.0 GB |

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm so clients would need to download quite a large file to generate their webcat enrollment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it might be good to figure out where the constraint costs are coming from, e.g. if it's largely SHA3 then we can control at least the WEBCAT side by not using SHA3. although it's probably all the non-native field arithmetic

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll check again, I think when trying it was something on the lines of a ~15% difference and it didn't seem worth to bring another primitive into this for that, but I'll try again and report back with concrete numbers!

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i took a look at the circuit PoC code, right now it's just under 10M R1CS constraints and most of the constraint cost will be range checks due to all the non native field arithmetic (since we're constraining limbs to be in the right range)

i wonder if we could get to a more reasonable proving key size with optimization: for example, one quick win is https://github.com/freedomofpress/webcat-infra-chain/compare/onion-enrollment-poc#diff-633f0da3e05d3a97e57b023460b3d48a8f7827b87d9d467a51f24b418c17fcfdR181-R182 where we are using variable base scalar mult but in our case the bases are actually the same (both pk_point) so that would save ~1.5-2M constraints or so

that plus any other ideas we have might have (e.g. ditching SHA3 for WEBCAT) might reduce constraint cost considerably in aggregate

if that failed the other avenue to explore is to use a proof system with lookups - this means massive reduction in cost for the range checks

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the prime order subgroup check for pk_point is very expensive (2.5M constraints)

observations:

we should think about this more but my take now is:

  • allowing torsion tainted pk_point is a reasonable choice (afaict only the owner of the onion service can register torsion variant ghost entries anyway)
  • we drop the prime order subgroup check in circuit
  • in the browser extension we should do the torsion check when we get an onion (per this doc)

that with the above optimization should be ~50% of the original constraint cost so we're getting closer

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm gonna try to apply this, it makes sense to me. I also wonder if we have to check for the torsion component at all on the WEBCAT side, since tor will do the same and likely fail earlier (as I guess the onion resolution/fetching will fail anyway).

@lsd-cat lsd-cat Jun 2, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, here's how a squeezed version could look like:

  1. Removed the in-circuit prime-order subgroup check. We do the torsion check elsewhere (if we need to).
  2. Windowed scalar multiplication (4-bit) for the two blinded-key mults.
  3. Dedicated T-less point doubling (cheaper than the unified add).
  4. Shared window table across both mults (same base key).
  5. Poseidon instead of SHA3 for h_wc.
Metric Before After
Constraints 9,486,885 4,115,846
Proving key 3.07 GB 1.18 GB
FFT domain 2²⁴ 2²²
Proof size 192 B 192 B
Setup time 822 s ~70 s
Proving time ~893 s ~60–70 s
Verifying time ~3 ms ~3 ms

Honestly I can't tell much at this stage about the implementation security of the whole thing, so let's keep this just as a benchmark. I'lll put this version in a different branch and it can be a useful reference

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wow that's quite a proving speedup!

Comment thread onion.md Outdated
Comment thread onion.md Outdated
Comment thread onion.md

### 6.2 Audit-log subtree

Append-only. Keyed by `(KP_wc_blind, block_height)` so every accepted

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

already in the CometBFT transactions we'll have the full data needed for a third party to reverify everything because all transactions are cryptographically linked to the block header via the DataHash field, and the header itself is signed. i.e. we could have a light client verification flow that uses also the DataHash

however, adding the audit subtree would get us the ability to efficiently query on keys so we should think about if we need that (and can't already do that with the canonical subtree)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

e.g. we can only generate proofs of non inclusion from the audit subtree to demonstrate an onion has never been blocked but idk if we would ever want to do that

Comment thread onion.md
- The pending entry is publicly observable, so monitors of the chain
can detect a change attempt against a domain they care about
(§5.5).
- If a second change submission arrives while a pending change is

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so in the definition of "change submission" above you specify that the policy hash differs from the canonical. but, an attacker can resubmit the exact same bundle again and reset the timer, so i think we also want to add a note that we will accept as a no-op subsequent submissions with policy_hash identical to the existing pending policy_hash and not reset the timer

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But the bundles would be valid only for one day? But agreed that we should drop identical submissions

Comment thread onion.md
Comment thread onion.md
generating the zero-knowledge proof and maintaining a published descriptor
acts as the rate limit. Generating a proof already takes ~8 minutes
of CPU time and several GB of RAM (Section 4.2), which is a
meaningful rate limit on its own. If empirically this turns out to

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a submitter only needs KS_hd_id for new submissions, a third party spammer can keep resubmitting the same generated proof within the tor period

Comment thread onion.md Outdated
@lsd-cat

lsd-cat commented May 27, 2026

Copy link
Copy Markdown
Member Author

Thanks for the review! I addressed that stuff that was easy and where the directions was already clear (expiry and cooldown as configurable paramas), left open what we might still want to discuss

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants