package xraykeys import ( "crypto/rand" "encoding/base64" "encoding/hex" "fmt" "golang.org/x/crypto/curve25519" ) // GenerateRealityKeyPair returns Xray-compatible Reality private/public keys // (raw URL-safe base64 without padding, same as `xray x25519`). func GenerateRealityKeyPair() (privateKey, publicKey string, err error) { var priv [32]byte if _, err = rand.Read(priv[:]); err != nil { return "", "", err } priv[0] &= 248 priv[31] &= 127 priv[31] |= 64 var pub [32]byte curve25519.ScalarBaseMult(&pub, &priv) privateKey = base64.RawURLEncoding.EncodeToString(priv[:]) publicKey = base64.RawURLEncoding.EncodeToString(pub[:]) return privateKey, publicKey, nil } // GenerateShortID returns a random Reality shortId (1–16 hex chars). func GenerateShortID() (string, error) { b := make([]byte, 4) if _, err := rand.Read(b); err != nil { return "", err } return hex.EncodeToString(b), nil } // EnsureReality fills missing Reality keys/shortId on an inbound-like struct. func EnsureReality(privateKey, publicKey, shortID, dest, serverNames string) (priv, pub, sid, d, names string, err error) { priv, pub, sid, d, names = privateKey, publicKey, shortID, dest, serverNames if d == "" { d = "www.microsoft.com:443" } if names == "" { names = "www.microsoft.com" } if priv == "" || pub == "" { priv, pub, err = GenerateRealityKeyPair() if err != nil { return "", "", "", "", "", fmt.Errorf("reality keys: %w", err) } } if sid == "" { sid, err = GenerateShortID() if err != nil { return "", "", "", "", "", fmt.Errorf("reality short id: %w", err) } } return priv, pub, sid, d, names, nil }