github.com/inazumav/sing-box@v0.0.0-20230926072359-ab51429a14f1/transport/clashssr/protocol/base.go (about) 1 package protocol 2 3 import ( 4 "bytes" 5 "crypto/aes" 6 "crypto/cipher" 7 "encoding/base64" 8 "encoding/binary" 9 "math/rand" 10 "sync" 11 "time" 12 13 "github.com/Dreamacro/clash/common/pool" 14 "github.com/Dreamacro/clash/transport/shadowsocks/core" 15 ) 16 17 type Base struct { 18 Key []byte 19 Overhead int 20 Param string 21 } 22 23 type userData struct { 24 userKey []byte 25 userID [4]byte 26 } 27 28 type authData struct { 29 clientID [4]byte 30 connectionID uint32 31 mutex sync.Mutex 32 } 33 34 func (a *authData) next() *authData { 35 r := &authData{} 36 a.mutex.Lock() 37 defer a.mutex.Unlock() 38 if a.connectionID > 0xff000000 || a.connectionID == 0 { 39 rand.Read(a.clientID[:]) 40 a.connectionID = rand.Uint32() & 0xffffff 41 } 42 a.connectionID++ 43 copy(r.clientID[:], a.clientID[:]) 44 r.connectionID = a.connectionID 45 return r 46 } 47 48 func (a *authData) putAuthData(buf *bytes.Buffer) { 49 binary.Write(buf, binary.LittleEndian, uint32(time.Now().Unix())) 50 buf.Write(a.clientID[:]) 51 binary.Write(buf, binary.LittleEndian, a.connectionID) 52 } 53 54 func (a *authData) putEncryptedData(b *bytes.Buffer, userKey []byte, paddings [2]int, salt string) error { 55 encrypt := pool.Get(16) 56 defer pool.Put(encrypt) 57 binary.LittleEndian.PutUint32(encrypt, uint32(time.Now().Unix())) 58 copy(encrypt[4:], a.clientID[:]) 59 binary.LittleEndian.PutUint32(encrypt[8:], a.connectionID) 60 binary.LittleEndian.PutUint16(encrypt[12:], uint16(paddings[0])) 61 binary.LittleEndian.PutUint16(encrypt[14:], uint16(paddings[1])) 62 63 cipherKey := core.Kdf(base64.StdEncoding.EncodeToString(userKey)+salt, 16) 64 block, err := aes.NewCipher(cipherKey) 65 if err != nil { 66 return err 67 } 68 iv := bytes.Repeat([]byte{0}, 16) 69 cbcCipher := cipher.NewCBCEncrypter(block, iv) 70 71 cbcCipher.CryptBlocks(encrypt, encrypt) 72 73 b.Write(encrypt) 74 return nil 75 }