This commit is contained in:
51
main.go
51
main.go
@@ -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
|
||||
}
|
||||
|
Reference in New Issue
Block a user