summaryrefslogtreecommitdiffstats
path: root/internal/handler/submit.go
diff options
context:
space:
mode:
authorGab Virebent <gabriel1@virebent.art>2026-07-01 17:41:47 +0200
committerGab Virebent <gabriel1@virebent.art>2026-07-01 17:41:47 +0200
commit78d57b1090a5a23abce2a732f091a4ef007d60cc (patch)
tree997b816317241db94810f789eb7122857b27ddd2 /internal/handler/submit.go
parentaa459e3b84cc4c5d908f3781c9253848c18640c3 (diff)
downloadnymdrop-78d57b1090a5a23abce2a732f091a4ef007d60cc.tar.gz
nymdrop-78d57b1090a5a23abce2a732f091a4ef007d60cc.tar.xz
nymdrop-78d57b1090a5a23abce2a732f091a4ef007d60cc.zip
Add client-side proof of work and fix X25519 WebCrypto API usage
Self-contained hashcash-style PoW on /submit: client finds a nonce so SHA-256("<unix-ts>:<nonce>") has enough leading zero bits, sent as an X-Nymdrop-Pow header; server verifies and rejects expired or replayed stamps, no challenge round-trip required. Difficulty tunable via --pow-difficulty without a rebuild. Also fixes a latent bug in the browser crypto: X25519 was being requested as ECDH with namedCurve "X25519", which is not a valid WebCrypto combination and always throws. Modern WebCrypto exposes X25519 as its own algorithm identifier.
Diffstat (limited to 'internal/handler/submit.go')
-rw-r--r--internal/handler/submit.go14
1 files changed, 12 insertions, 2 deletions
diff --git a/internal/handler/submit.go b/internal/handler/submit.go
index 15251cf..2822488 100644
--- a/internal/handler/submit.go
+++ b/internal/handler/submit.go
@@ -2,15 +2,17 @@ package handler
import (
"net/http"
+ "nymdrop/internal/pow"
"nymdrop/internal/relay"
)
type Submit struct {
relay *relay.Relay
+ pow *pow.Verifier
}
-func NewSubmit(r *relay.Relay) *Submit {
- return &Submit{relay: r}
+func NewSubmit(r *relay.Relay, p *pow.Verifier) *Submit {
+ return &Submit{relay: r, pow: p}
}
func (s *Submit) ServeHTTP(w http.ResponseWriter, r *http.Request) {
@@ -19,6 +21,14 @@ func (s *Submit) ServeHTTP(w http.ResponseWriter, r *http.Request) {
return
}
+ // Proof-of-work computed client-side (X-Nymdrop-Pow: "<unix-ts>:<nonce>").
+ // Rejects unproven, expired, and replayed stamps before touching the relay.
+ if err := s.pow.Verify(r.Header.Get("X-Nymdrop-Pow")); err != nil {
+ // Generic error — don't reveal which check failed.
+ http.Error(w, "error", http.StatusBadRequest)
+ return
+ }
+
r.Body = http.MaxBytesReader(w, r.Body, 10*1024*1024)
defer r.Body.Close()