erste module drin.

zwischenstand: Architektur aktualisiert, TOFU implementiert,
This commit is contained in:
br committed 2026-10-01 22:22:13 +02:00
1 parent 9d5789c5d7
commit c8df9d7651
41 files changed
+6455 -36

No files matched your search

+87
View File
@@ -0,0 +1,87 @@
package auth
import (
"bytes"
"crypto/ed25519"
"errors"
"io"
"net/http"
"strings"
"testing"
)
type ed25519PublicKey = ed25519.PublicKey
func TestSign_SetsHeaders(t *testing.T) {
priv, _ := GenerateKey()
s := &Signer{Key: priv}
r, _ := http.NewRequest(http.MethodGet, "https://ingress.example:8443/api/v1/stream", nil)
if err := s.Sign(r); err != nil {
t.Fatalf("Sign: %v", err)
}
if got := r.Header.Get(HeaderKey); got != EncodePublicKey(priv.Public().(ed25519.PublicKey)) {
t.Errorf("%s = %q", HeaderKey, got)
}
for _, h := range []string{HeaderTimestamp, HeaderNonce, HeaderSignature} {
if r.Header.Get(h) == "" {
t.Errorf("Header %s fehlt", h)
}
}
}
func TestSign_FreshNonceEachTime(t *testing.T) {
priv, _ := GenerateKey()
s := &Signer{Key: priv}
seen := map[string]bool{}
for range 100 {
r, _ := http.NewRequest(http.MethodGet, "https://h/x", nil)
if err := s.Sign(r); err != nil {
t.Fatal(err)
}
n := r.Header.Get(HeaderNonce)
if seen[n] {
t.Fatalf("Nonce %q doppelt", n)
}
seen[n] = true
}
}
func TestSign_PreservesBody(t *testing.T) {
priv, _ := GenerateKey()
r, _ := http.NewRequest(http.MethodPost, "https://h/api/v1/state", strings.NewReader(`{"a":1}`))
if err := (&Signer{Key: priv}).Sign(r); err != nil {
t.Fatal(err)
}
body, _ := io.ReadAll(r.Body)
if string(body) != `{"a":1}` {
t.Errorf("Body nach Sign = %q", body)
}
if r.GetBody == nil {
t.Fatal("GetBody fehlt – Redirects/Retries könnten den Body nicht erneut senden")
}
again, _ := r.GetBody()
body, _ = io.ReadAll(again)
if !bytes.Equal(body, []byte(`{"a":1}`)) {
t.Errorf("GetBody liefert %q", body)
}
}
// Kein Signieren für Klartext-Verbindungen: Signatur und Body dürfen nie
// unverschlüsselt über die Leitung gehen.
func TestSign_RefusesPlainHTTP(t *testing.T) {
priv, _ := GenerateKey()
r, _ := http.NewRequest(http.MethodGet, "http://ingress.example:8080/api/v1/stream", nil)
if err := (&Signer{Key: priv}).Sign(r); !errors.Is(err, ErrInsecureTransport) {
t.Errorf("erwartet ErrInsecureTransport, bekommen %v", err)
}
if r.Header.Get(HeaderSignature) != "" {
t.Error("Signatur trotz Klartext gesetzt")
}
}
func TestSign_NoKey(t *testing.T) {
r, _ := http.NewRequest(http.MethodGet, "https://h/x", nil)
if err := (&Signer{}).Sign(r); !errors.Is(err, ErrInvalidKey) {
t.Errorf("erwartet ErrInvalidKey, bekommen %v", err)
}
}