From cb639ca052d21adbcb46be3b8280de23d77df5f8 Mon Sep 17 00:00:00 2001 From: jbergner Date: Mon, 22 Sep 2025 20:48:52 +0200 Subject: [PATCH] RC1 --- main.go | 63 ++++++++++++++++++++++++++++++++++++------- templates/result.html | 9 ++++--- 2 files changed, 60 insertions(+), 12 deletions(-) diff --git a/main.go b/main.go index 1a72b68..b1e4132 100644 --- a/main.go +++ b/main.go @@ -2,6 +2,7 @@ package main import ( "embed" + "errors" "fmt" "html/template" "log" @@ -43,6 +44,7 @@ type genResult struct { PrivateArmored string Fingerprint string Created time.Time + UIDOnKey string // tatsächliche UID im Schlüssel } func main() { @@ -95,27 +97,69 @@ func handleGenerate(w http.ResponseWriter, r *http.Request) { http.Error(w, fmt.Sprintf("Fehler beim Erzeugen der Schlüssel: %v", err), http.StatusInternalServerError) return } - _ = resultTmpl.Execute(w, res) } +// sanitizeName entfernt verbotene Zeichen aus Name/Comment-Feldern, die vom OpenPGP-Format für UID reserviert sind +func sanitizeName(s string) string { + s = strings.TrimSpace(s) + // Entferne reservierte und Steuerzeichen, die in der UID nicht vorkommen dürfen + replacer := strings.NewReplacer("<", "", ">", "", "(", "", ")", "", "\r", "", "\n", "") + s = replacer.Replace(s) + // trim doppelte Spaces + for strings.Contains(s, " ") { + s = strings.ReplaceAll(s, " ", " ") + } + return s +} + +func sanitizeEmail(s string) string { + s = strings.TrimSpace(s) + s = strings.ReplaceAll(s, " ", "") // keine Spaces + replacer := strings.NewReplacer("<", "", ">", "", "(", "", ")", "", "\r", "", "\n", "") + s = replacer.Replace(s) + return s +} + +func validateEmailBasic(s string) bool { + if s == "" { + return false + } + if strings.ContainsAny(s, " <>()\r\n\t") { + return false + } + // sehr einfache Plausibilitätsprüfung + at := strings.IndexByte(s, '@') + if at <= 0 || at == len(s)-1 { + return false + } + if strings.Contains(s[at+1:], "@") { + return false + } + return true +} + func generatePGP(in genInput) (*genResult, error) { - // Kommentar wird in die User-ID integriert - name := in.Name - if in.Comment != "" { - name = fmt.Sprintf("%s (%s)", in.Name, in.Comment) + // Kommentar nicht in UID einbetten (gopenpgp's GenerateKey nimmt nur Name+Email) + name := sanitizeName(in.Name) + email := sanitizeEmail(in.Email) + if !validateEmailBasic(email) { + return nil, errors.New("ungültige E‑Mail-Adresse") + } + if name == "" { + return nil, errors.New("Name darf nicht leer sein") } - // 1) Schlüssel erzeugen (noch unverschlüsselt) - key, err := crypto.GenerateKey(name, in.Email, "rsa", in.RSABits) + // 1) Schlüssel erzeugen (UID = "Name ") + key, err := crypto.GenerateKey(name, email, "rsa", in.RSABits) if err != nil { return nil, fmt.Errorf("GenerateKey: %w", err) } - // 2) Optional mit Passphrase sperren (at-rest Verschlüsselung) + // 2) Optional mit Passphrase sperren if in.Passphrase != "" { if _, err := key.Lock([]byte(in.Passphrase)); err != nil { - return nil, fmt.Errorf("Lock (Passphrase setzen) fehlgeschlagen: %w", err) + return nil, fmt.Errorf("Passphrase setzen fehlgeschlagen: %w", err) } } @@ -138,6 +182,7 @@ func generatePGP(in genInput) (*genResult, error) { PrivateArmored: armoredPriv, Fingerprint: fp, Created: created, + UIDOnKey: fmt.Sprintf("%s <%s>", name, email), }, nil } diff --git a/templates/result.html b/templates/result.html index cd677ec..4fa1f10 100644 --- a/templates/result.html +++ b/templates/result.html @@ -23,7 +23,10 @@
Fingerprint: {{.Fingerprint}}
Erstellt: {{.Created.Format "2006-01-02 15:04:05"}}
-
User ID: {{.Name}} {{if .Comment}}({{.Comment}}){{end}} <{{.Email}}> • RSA {{.RSABits}}
+
User ID im Schlüssel: {{if .UIDOnKey}}{{.UIDOnKey}}{{else}}{{.Name}} <{{.Email}}>{{end}} • RSA {{.RSABits}}
+ {{if .Comment}} +
Kommentar (nur Anzeige, nicht in UID eingebettet): {{.Comment}}
+ {{end}}
@@ -42,7 +45,7 @@
-

Verwahren Sie den privaten Schlüssel sicher. Teilen Sie ihn niemals. Nutzen Sie eine starke Passphrase.

+

Verwahren Sie den privaten Schlüssel sicher. Teilen Sie ihn niemals.

- + \ No newline at end of file