Patch1
All checks were successful
release-tag / release-image (push) Successful in 1m45s

This commit is contained in:
jbergner
2025-04-29 15:02:54 +02:00
parent 08f1c19bc3
commit 1c4e736a6d

51
main.go
View File

@@ -421,60 +421,69 @@ type jwsPayload struct {
}
// -----------------------------------------------------------------------------
// JWS verification helper supports both JSON & compact JWS formats
// verifyJWS akzeptiert JSON- und Compact-Serialisierung ohne Base64-Gefrickel
// -----------------------------------------------------------------------------
func (s *server) verifyJWS(ctx context.Context, w http.ResponseWriter, r *http.Request) (*jwsPayload, bool) {
if !jwsVerify {
lg := slog.New(slog.NewJSONHandler(os.Stdout, nil))
slog.SetDefault(lg)
if !jwsVerify { // Signaturprüfung ausgeschaltet (Debug)
data, _ := io.ReadAll(r.Body)
return &jwsPayload{Data: data}, true
}
// read full body once
raw, err := io.ReadAll(r.Body)
body, err := io.ReadAll(r.Body)
if err != nil {
lg.Error("read body", "http.StatusBadRequest", "")
http.Error(w, "read body", http.StatusBadRequest)
return nil, false
}
// try JWS JSON first …
var sig jose.JSONWebSignature
if err := json.Unmarshal(raw, &sig); err != nil || len(sig.Signatures) == 0 {
// … fallback to compact serialization
cp, err2 := jose.ParseSigned(string(raw))
if err2 != nil {
http.Error(w, "bad JWS", http.StatusBadRequest)
return nil, false
}
sig = *cp
// ── JSON-Serialisierung versuchen … ───────────────────────────────────────
var sig *jose.JSONWebSignature
if err := json.Unmarshal(body, &sig); err == nil && len(sig.Signatures) > 0 {
// ok
} else if cp, err := jose.ParseSigned(string(body)); err == nil { // … sonst Compact
sig = cp
} else {
lg.Error("bad JWS", "http.StatusBadRequest", "")
http.Error(w, "bad JWS", http.StatusBadRequest)
return nil, false
}
prot := sig.Signatures[0].Protected // already base-64 decoded
// geschützter Header ist schon dekodiert
prot := sig.Signatures[0].Protected // jose.Header
// Nonce replay-protection
// Nonce-Replay-Schutz
if !s.db.takeNonce(ctx, prot.Nonce) {
lg.Error("bad nonce", "http.StatusForbidden", "")
http.Error(w, "bad nonce", http.StatusForbidden)
return nil, false
}
// Resolve verification key
// passenden öffentlichen Schlüssel bestimmen
var key *jose.JSONWebKey
switch {
case prot.JSONWebKey != nil:
case prot.JSONWebKey != nil: // inline JWK
key = prot.JSONWebKey
case prot.KeyID != "":
if k, err := s.db.accountKey(ctx, path.Base(prot.KeyID)); err == nil {
key = k
} else {
k, err := s.db.accountKey(ctx, path.Base(prot.KeyID))
if err != nil {
lg.Error("unknown kid", "http.StatusUnauthorized", "")
http.Error(w, "unknown kid", http.StatusUnauthorized)
return nil, false
}
key = k
default:
lg.Error("no verification key", "http.StatusBadRequest", "")
http.Error(w, "no verification key", http.StatusBadRequest)
return nil, false
}
// Signatur prüfen
payload, err := sig.Verify(key)
if err != nil {
lg.Error("signature invalid", "http.StatusUnauthorized", "")
http.Error(w, "signature invalid", http.StatusUnauthorized)
return nil, false
}