From f26322e56bcca2d205854a6d326e89b442de0cfc Mon Sep 17 00:00:00 2001 From: Pim van Pelt Date: Sun, 24 Aug 2025 11:11:08 +0200 Subject: [PATCH] Add gen-key helper --- tesseract/genconf/main.go | 51 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/tesseract/genconf/main.go b/tesseract/genconf/main.go index 59f6ed7..59fd98a 100644 --- a/tesseract/genconf/main.go +++ b/tesseract/genconf/main.go @@ -1,6 +1,9 @@ package main import ( + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" "crypto/sha256" "crypto/x509" "encoding/base64" @@ -140,6 +143,8 @@ func main() { generateHTML(*configFile) case "gen-env": generateEnv(*configFile) + case "gen-key": + generateKeys(*configFile) default: fmt.Fprintf(os.Stderr, "Unknown command: %s\n", args[0]) showHelp() @@ -172,6 +177,8 @@ func showHelp() { fmt.Printf(" gen-env Generate .env files and combined roots.pem in each log's localdirectory.\n") fmt.Printf(" Creates TESSERACT_ARGS environment variable with command line flags.\n") fmt.Printf(" Combines global roots and log-specific extraroots into roots.pem.\n\n") + fmt.Printf(" gen-key Generate prime256v1 private keys for each log (only if they don't exist).\n") + fmt.Printf(" Creates EC private key files at the path specified in log.secret.\n\n") } func showConfig(yamlFile string) { @@ -411,3 +418,47 @@ func createCombinedRootsPem(rootsFile, extraRootsFile, outputPath string) error return nil } + +func generateKeys(yamlFile string) { + config := loadConfig(yamlFile) + + // Generate keys for each log + for _, logEntry := range config.Logs { + // Check if key already exists + if _, err := os.Stat(logEntry.Secret); err == nil { + fmt.Printf("Key already exists: %s (skipped)\n", logEntry.Secret) + continue + } + + // Generate new prime256v1 key + privKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + log.Fatalf("Failed to generate key for %s: %v", logEntry.ShortName, err) + } + + // Marshal private key to DER format + privKeyDER, err := x509.MarshalECPrivateKey(privKey) + if err != nil { + log.Fatalf("Failed to marshal private key for %s: %v", logEntry.ShortName, err) + } + + // Create PEM block + privKeyPEM := pem.EncodeToMemory(&pem.Block{ + Type: "EC PRIVATE KEY", + Bytes: privKeyDER, + }) + + // Ensure directory exists + if err := os.MkdirAll(filepath.Dir(logEntry.Secret), 0755); err != nil { + log.Fatalf("Failed to create directory for %s: %v", logEntry.Secret, err) + } + + // Write key to file + err = os.WriteFile(logEntry.Secret, privKeyPEM, 0600) + if err != nil { + log.Fatalf("Failed to write key file %s: %v", logEntry.Secret, err) + } + + fmt.Printf("Generated %s\n", logEntry.Secret) + } +}