package portservice import ( "crypto/ed25519" "crypto/rand" "crypto/x509" "encoding/pem" "errors" "fmt" "os" "path/filepath" "golang.org/x/crypto/ssh" "tera-clone/services/tera-api/internal/storage/atomicfile" ) func LoadOrCreateSSHSigner(path string) (ssh.Signer, error) { if path == "" || !filepath.IsAbs(path) { return nil, errors.New("SSH host key path must be absolute") } if payload, err := os.ReadFile(path); err == nil { return ssh.ParsePrivateKey(payload) } else if !os.IsNotExist(err) { return nil, fmt.Errorf("read SSH host key: %w", err) } if err := os.MkdirAll(filepath.Dir(path), 0o750); err != nil { return nil, fmt.Errorf("prepare SSH host key directory: %w", err) } _, privateKey, err := ed25519.GenerateKey(rand.Reader) if err != nil { return nil, fmt.Errorf("generate SSH host key: %w", err) } encoded, err := x509.MarshalPKCS8PrivateKey(privateKey) if err != nil { return nil, fmt.Errorf("encode SSH host key: %w", err) } payload := pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: encoded}) if err := atomicfile.Write(path, payload, 0o600); err != nil { return nil, fmt.Errorf("persist SSH host key: %w", err) } return ssh.ParsePrivateKey(payload) }