package auth import ( "crypto/ecdsa" "crypto/elliptic" "crypto/rand" "crypto/x509" "encoding/pem" "errors" "os" "path/filepath" "testing" ) func TestKeyFile_RoundTrip(t *testing.T) { priv, err := GenerateKey() if err != nil { t.Fatal(err) } path := filepath.Join(t.TempDir(), "node.key") if err := WritePrivateKey(path, priv); err != nil { t.Fatalf("WritePrivateKey: %v", err) } info, err := os.Stat(path) if err != nil { t.Fatal(err) } if perm := info.Mode().Perm(); perm != 0o600 { t.Errorf("Dateirechte %o, erwartet 600", perm) } got, err := ReadPrivateKey(path) if err != nil { t.Fatalf("ReadPrivateKey: %v", err) } if !got.Equal(priv) { t.Error("gelesener Schlüssel weicht ab") } } func TestWritePrivateKey_NeverOverwrites(t *testing.T) { priv, _ := GenerateKey() path := filepath.Join(t.TempDir(), "node.key") if err := WritePrivateKey(path, priv); err != nil { t.Fatal(err) } other, _ := GenerateKey() if err := WritePrivateKey(path, other); !errors.Is(err, os.ErrExist) { t.Errorf("erwartet os.ErrExist, bekommen %v", err) } if got, _ := ReadPrivateKey(path); !got.Equal(priv) { t.Error("bestehender Schlüssel wurde überschrieben") } } func TestReadPrivateKey_RejectsInsecurePermissions(t *testing.T) { priv, _ := GenerateKey() path := filepath.Join(t.TempDir(), "node.key") if err := WritePrivateKey(path, priv); err != nil { t.Fatal(err) } if err := os.Chmod(path, 0o644); err != nil { t.Fatal(err) } if _, err := ReadPrivateKey(path); !errors.Is(err, ErrInsecureKeyFile) { t.Errorf("erwartet ErrInsecureKeyFile, bekommen %v", err) } } func TestReadPrivateKey_InvalidContent(t *testing.T) { ecKey, _ := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) ecDER, _ := x509.MarshalPKCS8PrivateKey(ecKey) tests := map[string][]byte{ "kein PEM": []byte("hallo"), "falscher Typ": pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: []byte{1, 2, 3}}), "kaputtes PKCS8": pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: []byte{1, 2, 3}}), "kein Ed25519": pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: ecDER}), } for name, content := range tests { t.Run(name, func(t *testing.T) { path := filepath.Join(t.TempDir(), "node.key") if err := os.WriteFile(path, content, 0o600); err != nil { t.Fatal(err) } if _, err := ReadPrivateKey(path); !errors.Is(err, ErrInvalidKey) { t.Errorf("erwartet ErrInvalidKey, bekommen %v", err) } }) } if _, err := ReadPrivateKey(filepath.Join(t.TempDir(), "fehlt.key")); !errors.Is(err, os.ErrNotExist) { t.Errorf("fehlende Datei: erwartet os.ErrNotExist, bekommen %v", err) } } func TestPublicKeyEncoding(t *testing.T) { priv, _ := GenerateKey() pub := priv.Public().(ed25519PublicKey) enc := EncodePublicKey(pub) got, err := DecodePublicKey(enc) if err != nil { t.Fatalf("DecodePublicKey: %v", err) } if !got.Equal(pub) { t.Error("Round-Trip weicht ab") } for _, bad := range []string{"", "!!!", "AAAA"} { if _, err := DecodePublicKey(bad); !errors.Is(err, ErrInvalidKey) { t.Errorf("DecodePublicKey(%q): erwartet ErrInvalidKey, bekommen %v", bad, err) } } }