package license import ( "crypto/ed25519" "errors" "testing" "time" ) func testKeyPair(t *testing.T) (ed25519.PublicKey, ed25519.PrivateKey) { t.Helper() pub, priv, err := ed25519.GenerateKey(nil) if err != nil { t.Fatalf("schluesselpaar erzeugen: %v", err) } return pub, priv } func TestIssueAndParse_RoundTrip(t *testing.T) { pub, priv := testKeyPair(t) issuer := NewIssuer(priv) validator := NewValidator(pub) payload := Payload{ TenantSlug: "acme", Plan: "pro", Modules: []string{"dms", "mail"}, IssuedAt: time.Now().Truncate(time.Second), ValidUntil: time.Now().Add(365 * 24 * time.Hour).Truncate(time.Second), } key, err := issuer.Issue(payload) if err != nil { t.Fatalf("issue: %v", err) } got, err := validator.Parse(key) if err != nil { t.Fatalf("parse: %v", err) } if got.TenantSlug != payload.TenantSlug || got.Plan != payload.Plan || len(got.Modules) != 2 { t.Fatalf("payload nach parse unerwartet: %+v", got) } } // Akzeptanzkriterium 1 + Pruefung 1: manipulierter Schluessel wird zuverlaessig erkannt. func TestParse_RejectsTamperedKey(t *testing.T) { pub, priv := testKeyPair(t) issuer := NewIssuer(priv) validator := NewValidator(pub) key, err := issuer.Issue(Payload{TenantSlug: "acme", Plan: "pro", ValidUntil: time.Now().Add(time.Hour)}) if err != nil { t.Fatalf("issue: %v", err) } // Ein Zeichen im signierten Teil aendern. tampered := []byte(key) changed := false for i, c := range tampered { if c != '.' { if c == 'A' { tampered[i] = 'B' } else { tampered[i] = 'A' } changed = true break } } if !changed { t.Fatal("testaufbau fehlerhaft: nichts zum manipulieren gefunden") } if _, err := validator.Parse(string(tampered)); !errors.Is(err, ErrInvalidSignature) { t.Fatalf("erwartet ErrInvalidSignature, habe %v", err) } } func TestParse_RejectsWrongKeyPair(t *testing.T) { _, priv := testKeyPair(t) otherPub, _ := testKeyPair(t) issuer := NewIssuer(priv) validator := NewValidator(otherPub) // falscher oeffentlicher Schluessel key, err := issuer.Issue(Payload{TenantSlug: "acme", Plan: "pro"}) if err != nil { t.Fatalf("issue: %v", err) } if _, err := validator.Parse(key); !errors.Is(err, ErrInvalidSignature) { t.Fatalf("erwartet ErrInvalidSignature, habe %v", err) } } func TestParse_RejectsMalformedKey(t *testing.T) { pub, _ := testKeyPair(t) validator := NewValidator(pub) cases := []string{"", "keine-punkt-trennung", "!!!.!!!"} for _, c := range cases { if _, err := validator.Parse(c); !errors.Is(err, ErrMalformedKey) { t.Fatalf("Parse(%q): erwartet ErrMalformedKey, habe %v", c, err) } } }