177 lines
5.1 KiB
Go
177 lines
5.1 KiB
Go
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)
|
|
}
|
|
}
|