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