Closes#39. A CAPTCHA hands a third party every visitor's connection — a strange thing to
do in a product whose argument is that it collects almost nothing. This collects nothing at
all: no personal data, no third party, no crosswalk photos. Two seconds for a person, real
money for a farm of registrations.
OFF by default, and that is not timidity. The shipped Android client knows nothing
about challenges; requiring one by default would stop every existing app creating an
account the moment a relay updated, with no error it could explain. FN_SIGNUP_POW_BITS
turns it on when a deployment's clients can answer.
The challenge route answers even when the feature is off, reporting zero bits. A 404
would tell an anonymous caller how the relay is configured, and a client that asks "how
much work?" and hears "none" needs no special case for older servers.
Stateless. The challenge carries its own expiry and a MAC over both, so nothing is
stored and a restart does not invalidate work in progress. The cost: a challenge is
replayable until it expires — bounded by a 10-minute window and the rate limits already in
front of sign-up. A trade, not an oversight, and smaller than a table of live challenges to
keep and sweep.
Capped at 24 bits however configured. A number set absurdly high does not read as
spam protection to the person it hits — it reads as an app that hangs on the sign-up
button. Verification caps too, or a client could be asked for work the server would refuse.
Counted in bits, not bytes — bytes move in steps of 256×, giving no way to ask for
two seconds rather than half a second or two minutes.
One message for all four refusals (forged, stale, malformed, unsolved): telling somebody
which it was tells an attacker which knob to turn.
The MAC secret is derived from the issuer key, not the key itself — one secret doing
two jobs is one compromise doing two.
Tests: 11 new, proven able to fail — covering only the salt with the MAC, so a stale
challenge could be extended by editing its expiry, turns 12 red. 481 in 41 suites pass.
ℹNo public-page change: with the feature off, nothing user-visible differs. Client
support (fetch challenge, solve, send) is a separate MR per platform, and should land
before any deployment turns this on.
Closes #39. A CAPTCHA hands a third party every visitor's connection — a strange thing to
do in a product whose argument is that it collects almost nothing. This collects nothing at
all: no personal data, no third party, no crosswalk photos. Two seconds for a person, real
money for a farm of registrations.
**OFF by default, and that is not timidity.** The shipped Android client knows nothing
about challenges; requiring one by default would stop every existing app creating an
account the moment a relay updated, with no error it could explain. `FN_SIGNUP_POW_BITS`
turns it on when a deployment's clients can answer.
**The challenge route answers even when the feature is off**, reporting zero bits. A 404
would tell an anonymous caller how the relay is configured, and a client that asks "how
much work?" and hears "none" needs no special case for older servers.
**Stateless.** The challenge carries its own expiry and a MAC over both, so nothing is
stored and a restart does not invalidate work in progress. The cost: a challenge is
replayable until it expires — bounded by a 10-minute window and the rate limits already in
front of sign-up. A trade, not an oversight, and smaller than a table of live challenges to
keep and sweep.
**Capped at 24 bits however configured.** A number set absurdly high does not read as
spam protection to the person it hits — it reads as an app that hangs on the sign-up
button. Verification caps too, or a client could be asked for work the server would refuse.
**Counted in bits, not bytes** — bytes move in steps of 256×, giving no way to ask for
two seconds rather than half a second or two minutes.
One message for all four refusals (forged, stale, malformed, unsolved): telling somebody
which it was tells an attacker which knob to turn.
The MAC secret is **derived** from the issuer key, not the key itself — one secret doing
two jobs is one compromise doing two.
**Tests:** 11 new, proven able to fail — covering only the salt with the MAC, so a stale
challenge could be extended by editing its expiry, turns 12 red. 481 in 41 suites pass.
ℹNo public-page change: with the feature off, nothing user-visible differs. Client
support (fetch challenge, solve, send) is a separate MR per platform, and should land
before any deployment turns this on.
added 1 commit
<ul><li>3181107e - The sign-up challenge is reachable from the app's own namespace</li></ul>
[Compare with previous version](/paulhitt/flamenet-relay/-/merge_requests/15/diffs?diff_id=1998392950&start_sha=5a07719046b319859726537b052a837a6cebc185)
added 26 commits
<ul><li>257ec212...08894ef8 - 24 commits from branch <code>main</code></li><li>7040dce5 - Charge a few seconds of arithmetic before an account exists</li><li>48ce3b16 - The sign-up challenge is reachable from the app's own namespace</li></ul>
[Compare with previous version](/paulhitt/flamenet-relay/-/merge_requests/15/diffs?diff_id=2001146131&start_sha=257ec2127436a61a736cb33b8cc2b34ed2f25c8c)
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Closes #39. A CAPTCHA hands a third party every visitor's connection — a strange thing to
do in a product whose argument is that it collects almost nothing. This collects nothing at
all: no personal data, no third party, no crosswalk photos. Two seconds for a person, real
money for a farm of registrations.
OFF by default, and that is not timidity. The shipped Android client knows nothing
about challenges; requiring one by default would stop every existing app creating an
account the moment a relay updated, with no error it could explain.
FN_SIGNUP_POW_BITSturns it on when a deployment's clients can answer.
The challenge route answers even when the feature is off, reporting zero bits. A 404
would tell an anonymous caller how the relay is configured, and a client that asks "how
much work?" and hears "none" needs no special case for older servers.
Stateless. The challenge carries its own expiry and a MAC over both, so nothing is
stored and a restart does not invalidate work in progress. The cost: a challenge is
replayable until it expires — bounded by a 10-minute window and the rate limits already in
front of sign-up. A trade, not an oversight, and smaller than a table of live challenges to
keep and sweep.
Capped at 24 bits however configured. A number set absurdly high does not read as
spam protection to the person it hits — it reads as an app that hangs on the sign-up
button. Verification caps too, or a client could be asked for work the server would refuse.
Counted in bits, not bytes — bytes move in steps of 256×, giving no way to ask for
two seconds rather than half a second or two minutes.
One message for all four refusals (forged, stale, malformed, unsolved): telling somebody
which it was tells an attacker which knob to turn.
The MAC secret is derived from the issuer key, not the key itself — one secret doing
two jobs is one compromise doing two.
Tests: 11 new, proven able to fail — covering only the salt with the MAC, so a stale
challenge could be extended by editing its expiry, turns 12 red. 481 in 41 suites pass.
ℹNo public-page change: with the feature off, nothing user-visible differs. Client
support (fetch challenge, solve, send) is a separate MR per platform, and should land
before any deployment turns this on.
added 1 commit
Compare with previous version
added 1 commit
Compare with previous version
mentioned in merge request !25
added 26 commits
main7040dce5- Charge a few seconds of arithmetic before an account exists48ce3b16- The sign-up challenge is reachable from the app's own namespaceCompare with previous version
mentioned in commit
f1f2618bdcchanged the description