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`.
This commit is contained in:
Chaosoffire
2025-12-15 21:43:33 +08:00
parent 65e51f8aea
commit 09e94c6213
2 changed files with 43 additions and 17 deletions
+40 -15
View File
@@ -1,30 +1,55 @@
package common package common
import ( import (
"math/rand" crand "crypto/rand"
"math/big"
mrand "math/rand"
"sync"
"time" "time"
) )
var ( var (
allSeq []rune allSeq []rune = []rune{
rnd = rand.New(rand.NewSource(time.Now().UnixNano())) '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 { func Random(n int) string {
runes := make([]rune, n) if n <= 0 || len(allSeq) == 0 {
for i := 0; i < n; i++ { return ""
runes[i] = allSeq[rnd.Intn(len(allSeq))]
} }
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 { 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())
} }
+3 -2
View File
@@ -2,7 +2,8 @@ package util
import ( import (
"encoding/json" "encoding/json"
"math/rand"
"github.com/alireza0/s-ui/util/common"
"github.com/alireza0/s-ui/database/model" "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 := tlsConfig["reality"].(map[string]interface{})
realityConfig["enabled"] = true realityConfig["enabled"] = true
if shortIDs, ok := reality["short_id"].([]interface{}); ok && len(shortIDs) > 0 { 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 tlsConfig["reality"] = realityConfig
} }