Files
egutierrez 621e8895c9 feat(infra): auto-commit con 86 cambios
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 19:38:15 +02:00

68 lines
1.9 KiB
Go

package infra
import (
"bytes"
"fmt"
"os/exec"
"strings"
)
// WGKeys holds a WireGuard Curve25519 key pair and an optional preshared key,
// all encoded as base64 strings.
type WGKeys struct {
PrivateKey string // base64 Curve25519 private key
PublicKey string // base64 Curve25519 public key
PresharedKey string // base64 preshared key, empty if not requested
}
// WGKeygen generates a WireGuard key pair using `wg genkey` / `wg pubkey`.
// If withPSK is true it also runs `wg genpsk` to produce a preshared key.
// Requires the `wg` binary in PATH (install wireguard-tools).
// NEVER log PrivateKey or PresharedKey in plain text.
func WGKeygen(withPSK bool) (WGKeys, error) {
// Generate private key
privOut, err := runWG(nil, "genkey")
if err != nil {
return WGKeys{}, fmt.Errorf("wg genkey: %w", err)
}
privateKey := strings.TrimSpace(privOut)
// Derive public key from private key
pubOut, err := runWG(strings.NewReader(privateKey), "pubkey")
if err != nil {
return WGKeys{}, fmt.Errorf("wg pubkey: %w", err)
}
publicKey := strings.TrimSpace(pubOut)
keys := WGKeys{
PrivateKey: privateKey,
PublicKey: publicKey,
}
if withPSK {
pskOut, err := runWG(nil, "genpsk")
if err != nil {
return WGKeys{}, fmt.Errorf("wg genpsk: %w", err)
}
keys.PresharedKey = strings.TrimSpace(pskOut)
}
return keys, nil
}
// runWG executes `wg <subcommand>`, optionally piping stdin, and returns stdout.
// stderr is captured and included in the error when exit code != 0.
func runWG(stdin interface{ Read([]byte) (int, error) }, subcommand string) (string, error) {
cmd := exec.Command("wg", subcommand)
if stdin != nil {
cmd.Stdin = stdin
}
var stdout, stderr bytes.Buffer
cmd.Stdout = &stdout
cmd.Stderr = &stderr
if err := cmd.Run(); err != nil {
return "", fmt.Errorf("%w: %s", err, strings.TrimSpace(stderr.String()))
}
return stdout.String(), nil
}