From 09e94c6213414bab70cd54119a0f0395a3db1468 Mon Sep 17 00:00:00 2001 From: Chaosoffire <81634128+chaosoffire@users.noreply.github.com> Date: Mon, 15 Dec 2025 21:43:33 +0800 Subject: [PATCH] refactor: replace math/rand with crypto/rand for secure generation - Updated `common.Random` and added `common.RandomInt` to use `crypto/rand` for cryptographically secure random number generation. - Added a thread-safe fallback to `math/rand` in case of system entropy failure. - Optimized `allSeq` initialization by using a rune slice literal instead of a loop in `init()`. - Refactored `util/outJson.go` to use the new `common.RandomInt`, removing the direct dependency on `math/rand`. --- util/common/random.go | 55 +++++++++++++++++++++++++++++++------------ util/outJson.go | 5 ++-- 2 files changed, 43 insertions(+), 17 deletions(-) diff --git a/util/common/random.go b/util/common/random.go index 5352b78..e4940ec 100644 --- a/util/common/random.go +++ b/util/common/random.go @@ -1,30 +1,55 @@ package common import ( - "math/rand" + crand "crypto/rand" + "math/big" + mrand "math/rand" + "sync" "time" ) var ( - allSeq []rune - rnd = rand.New(rand.NewSource(time.Now().UnixNano())) + allSeq []rune = []rune{ + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + } + + fallbackRand = mrand.New(mrand.NewSource(time.Now().UnixNano())) + fallbackMu = sync.Mutex{} ) -func init() { - chars := "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" - for _, char := range chars { - allSeq = append(allSeq, char) - } -} - func Random(n int) string { - runes := make([]rune, n) - for i := 0; i < n; i++ { - runes[i] = allSeq[rnd.Intn(len(allSeq))] + if n <= 0 || len(allSeq) == 0 { + return "" } - return string(runes) + result := make([]rune, n) + maxBig := big.NewInt(int64(len(allSeq))) + for i := 0; i < n; i++ { + num, err := crand.Int(crand.Reader, maxBig) + if err != nil { + // fallback + fallbackMu.Lock() + result[i] = allSeq[fallbackRand.Intn(len(allSeq))] + fallbackMu.Unlock() + continue + } + result[i] = allSeq[int(num.Int64())] + } + return string(result) } func RandomInt(n int) int { - return rnd.Intn(n) + if n <= 0 { + return 0 + } + max := big.NewInt(int64(n)) + result, err := crand.Int(crand.Reader, max) + if err != nil { + // fallback + fallbackMu.Lock() + defer fallbackMu.Unlock() + return fallbackRand.Intn(n) + } + return int(result.Int64()) } diff --git a/util/outJson.go b/util/outJson.go index 8553ebf..4e8e720 100644 --- a/util/outJson.go +++ b/util/outJson.go @@ -2,7 +2,8 @@ package util import ( "encoding/json" - "math/rand" + + "github.com/alireza0/s-ui/util/common" "github.com/alireza0/s-ui/database/model" ) @@ -108,7 +109,7 @@ func addTls(out *map[string]interface{}, tls *model.Tls) { realityConfig := tlsConfig["reality"].(map[string]interface{}) realityConfig["enabled"] = true if shortIDs, ok := reality["short_id"].([]interface{}); ok && len(shortIDs) > 0 { - realityConfig["short_id"] = shortIDs[rand.Intn(len(shortIDs))] + realityConfig["short_id"] = shortIDs[common.RandomInt(len(shortIDs))] } tlsConfig["reality"] = realityConfig }