This commit is contained in:
CN-JS-HuiBai
2026-04-15 01:32:40 +08:00
parent 13636715a7
commit 74966e4ebe

View File

@@ -3,8 +3,10 @@ package xboard
import ( import (
"bytes" "bytes"
"context" "context"
"crypto/md5"
"crypto/rand" "crypto/rand"
"encoding/base64" "encoding/base64"
"encoding/hex"
"encoding/json" "encoding/json"
"fmt" "fmt"
"io" "io"
@@ -27,17 +29,19 @@ import (
"github.com/sagernet/sing/service" "github.com/sagernet/sing/service"
) )
// ss2022UserKey prepares a user key for SS2022: // ss2022Key derives a secure 2022 key from a seed string (like UUID or ServerKey).
// Truncate UUID string to keyLen and encode as Base64 for sing-box. // Logic: base64(hex(md5(seed)))[:keyLen] -- this is a common panel pattern.
func ss2022UserKey(identity string, keyLen int) string { func ss2022Key(seed string, keyLen int) string {
if len(identity) > keyLen { h := md5.Sum([]byte(seed))
identity = identity[:keyLen] hexStr := hex.EncodeToString(h[:]) // 32 characters
} else if len(identity) < keyLen { if len(hexStr) > keyLen {
hexStr = hexStr[:keyLen]
} else if len(hexStr) < keyLen {
padded := make([]byte, keyLen) padded := make([]byte, keyLen)
copy(padded, []byte(identity)) copy(padded, []byte(hexStr))
identity = string(padded) hexStr = string(padded)
} }
return base64.StdEncoding.EncodeToString([]byte(identity)) return base64.StdEncoding.EncodeToString([]byte(hexStr))
} }
// ss2022KeyLength returns the required key length for a given SS2022 cipher. // ss2022KeyLength returns the required key length for a given SS2022 cipher.
@@ -618,9 +622,11 @@ func (s *Service) setupNode() error {
} }
if strings.Contains(method, "2022") { if strings.Contains(method, "2022") {
// SS2022: server_key is used DIRECTLY as PSK (like V2bX) // SS2022 key derivation for panel compatibility
ssOptions.Password = serverKey
keyLen := ss2022KeyLength(method) keyLen := ss2022KeyLength(method)
ssOptions.Password = ss2022Key(serverKey, keyLen)
// Create a dummy user (will be replaced by syncUsers)
// Create a dummy user (will be replaced by syncUsers) // Create a dummy user (will be replaced by syncUsers)
dummyKey := make([]byte, keyLen) dummyKey := make([]byte, keyLen)
@@ -892,13 +898,12 @@ func (s *Service) syncUsers() {
} }
// V2bX/Xboard approach for SS2022 user key: // V2bX/Xboard approach for SS2022 user key:
// Base64 encode the UUID string (clipped/padded to keyLen)
if isSS2022 { if isSS2022 {
originalKey := key originalKey := key
key = ss2022UserKey(key, ss2022KeyLen) key = ss2022Key(key, ss2022KeyLen)
if len(newUsers) == 0 { if len(newUsers) == 0 {
// Log first user's key derivation for debugging // Log first user's key derivation for debugging
s.logger.Info("SS2022 user key derivation: ID[:", ss2022KeyLen, "]=", originalKey[:min(ss2022KeyLen, len(originalKey))], " → b64_uPSK=", key) s.logger.Info("SS2022 user key derivation: ID[:", ss2022KeyLen, "]=", originalKey, " → b64_PSK=", key)
} }
} }