package main import ( "crypto/ecdsa" "crypto/ed25519" "crypto/rand" "crypto/rsa" "crypto/x509" "encoding/json" "fmt" "log" "net/http" "os" "strings" "golang.org/x/crypto/acme" "golang.org/x/crypto/acme/autocert" ) // Diese Variablen halten die Pfade zum CA-Zertifikat und zum privaten Schlüssel const ( CA_CERT_PATH = "/path/to/your/ca_cert.pem" // Pfad zu Ihrem CA-Zertifikat CA_KEY_PATH = "/path/to/your/ca_key.pem" // Pfad zu Ihrem privaten CA-Schlüssel ) var ( privateKey interface{} caCert *x509.Certificate ) func loadCACertificate() error { // CA-Zertifikat laden certPEM, err := os.ReadFile(CA_CERT_PATH) if err != nil { return fmt.Errorf("error reading CA cert: %v", err) } caCert, err = x509.ParseCertificate(certPEM) if err != nil { return fmt.Errorf("error parsing CA cert: %v", err) } // CA-Schlüssel laden (private key) keyPEM, err := os.ReadFile(CA_KEY_PATH) if err != nil { return fmt.Errorf("error reading CA key: %v", err) } privateKey, err = parsePrivateKey(keyPEM) if err != nil { return fmt.Errorf("error parsing CA key: %v", err) } return nil } func loadEd25519PrivateKey(filePath string) (ed25519.PrivateKey, error) { // Lese die Datei keyData, err := os.ReadFile(filePath) if err != nil { return nil, fmt.Errorf("failed to read private key file: %v", err) } // Stelle sicher, dass der Schlüssel als Seed vorliegt (32 Bytes) if len(keyData) != ed25519.SeedSize { return nil, fmt.Errorf("invalid seed size for ed25519 key: expected 32 bytes") } // Ed25519-Schlüssel aus dem Seed erstellen privKey := ed25519.NewKeyFromSeed(keyData) return privKey, nil } // Funktion zum Parsen des privaten Schlüssels (RSA, ECDSA, Ed25519) func parsePrivateKey(keyPEM []byte) (interface{}, error) { // Versuche RSA-Private-Key zu laden if key, err := x509.ParsePKCS1PrivateKey(keyPEM); err == nil { return key, nil } // Versuche ECDSA-Private-Key zu laden if key, err := x509.ParseECPrivateKey(keyPEM); err == nil { return key, nil } // Versuche Ed25519-Private-Key zu laden if key, err := loadEd25519PrivateKey(string(keyPEM)); err == nil { return key, nil } return nil, fmt.Errorf("unknown private key format") } // Funktion zur Zertifikatserstellung, die das CA-Zertifikat verwendet func signCertificate(cert *x509.Certificate) ([]byte, error) { // Sie können hier das CA-Zertifikat und den privaten Schlüssel verwenden, // um das Zertifikat zu signieren. Zum Beispiel: if rsaKey, ok := privateKey.(*rsa.PrivateKey); ok { return x509.CreateCertificate(rand.Reader, cert, caCert, rsaKey.Public(), rsaKey) } else if ecdsaKey, ok := privateKey.(*ecdsa.PrivateKey); ok { return x509.CreateCertificate(rand.Reader, cert, caCert, ecdsaKey.Public(), ecdsaKey) } else if ed25519Key, ok := privateKey.(ed25519.PrivateKey); ok { return x509.CreateCertificate(rand.Reader, cert, caCert, ed25519Key.Public(), ed25519Key) } return nil, fmt.Errorf("unsupported private key type") } func handleACME(w http.ResponseWriter, r *http.Request) { acmeHandler := autocert.NewManager() acmeHandler.HostPolicy = autocert.HostWhitelist("example.com") // Passe die Domain an // POST-Anforderung für new-order if r.Method == http.MethodPost && strings.Contains(r.URL.Path, "/new-order") { handleNewOrder(w, r) return } acmeHandler.HTTPHandler(nil).ServeHTTP(w, r) } func handleNewOrder(w http.ResponseWriter, r *http.Request) { // Sicherstellen, dass es eine JSON-Anfrage ist if r.Header.Get("Content-Type") != "application/json" { http.Error(w, "Content-Type must be application/json", http.StatusBadRequest) return } var order acme.Order // Anfrage decodieren decoder := json.NewDecoder(r.Body) if err := decoder.Decode(&order); err != nil { http.Error(w, fmt.Sprintf("Error decoding request: %v", err), http.StatusBadRequest) return } // Validierung der Domain if len(order.Identifiers) == 0 || !strings.HasSuffix(order.Identifiers[0].Value, ".stadt-hilden.de") { http.Error(w, "Invalid domain", http.StatusUnauthorized) return } // Antwort für den ACME-Client erstellen orderURL := fmt.Sprintf("http://localhost:8080/acme/order/%d", 1234) response := struct { Status string `json:"status"` Expires string `json:"expires"` URL string `json:"url"` }{ Status: "pending", // Bestellung ist noch ausstehend Expires: "2025-01-01T00:00:00Z", // Beispielablaufdatum URL: orderURL, } // JSON-Antwort zurückgeben w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusCreated) if err := json.NewEncoder(w).Encode(response); err != nil { http.Error(w, fmt.Sprintf("Error encoding response: %v", err), http.StatusInternalServerError) return } } func main() { // CA-Zertifikat und privaten Schlüssel laden if err := loadCACertificate(); err != nil { log.Fatalf("Error loading CA certificate: %v", err) } // Ihr ACME-Server-Setup fortführen http.HandleFunc("/acme", handleACME) // Server starten port := "8080" fmt.Printf("Starting ACME server on :%s...\n", port) if err := http.ListenAndServe(":"+port, nil); err != nil { log.Fatalf("Failed to start server: %v", err) } }