package relay import ( "encoding/hex" "encoding/json" "fmt" "os" ) type keypairFile struct { Pub string `json:"pub"` Priv string `json:"priv"` } // LoadOrCreateKeyPair loads an X25519 relay keypair from path, creating it if absent. func LoadOrCreateKeyPair(path string) (*KeyPair, error) { data, err := os.ReadFile(path) if err == nil { var f keypairFile if err := json.Unmarshal(data, &f); err != nil { return nil, fmt.Errorf("parse relay key file: %w", err) } pubBytes, err := hex.DecodeString(f.Pub) if err != nil || len(pubBytes) != 32 { return nil, fmt.Errorf("invalid relay pub key in %s", path) } privBytes, err := hex.DecodeString(f.Priv) if err != nil || len(privBytes) != 32 { return nil, fmt.Errorf("invalid relay priv key in %s", path) } kp := &KeyPair{} copy(kp.Pub[:], pubBytes) copy(kp.Priv[:], privBytes) return kp, nil } if !os.IsNotExist(err) { return nil, fmt.Errorf("read relay key file: %w", err) } // Generate new keypair and persist. kp, err := GenerateKeyPair() if err != nil { return nil, err } f := keypairFile{ Pub: kp.PubHex(), Priv: hex.EncodeToString(kp.Priv[:]), } out, _ := json.MarshalIndent(f, "", " ") if err := os.WriteFile(path, out, 0600); err != nil { return nil, fmt.Errorf("write relay key file: %w", err) } return kp, nil }