github.com/yaling888/clash@v1.53.0/transport/ssr/protocol/auth_aes128_sha1.go (about) 1 package protocol 2 3 import ( 4 "bytes" 5 R "crypto/rand" 6 "encoding/binary" 7 "math" 8 "math/rand/v2" 9 "net" 10 "strconv" 11 "strings" 12 13 "github.com/phuslu/log" 14 15 "github.com/yaling888/clash/common/pool" 16 "github.com/yaling888/clash/transport/ssr/tools" 17 ) 18 19 type ( 20 hmacMethod func(key, data []byte) []byte 21 hashDigestMethod func([]byte) []byte 22 ) 23 24 func init() { 25 register("auth_aes128_sha1", newAuthAES128SHA1, 9) 26 } 27 28 type authAES128Function struct { 29 salt string 30 hmac hmacMethod 31 hashDigest hashDigestMethod 32 } 33 34 type authAES128 struct { 35 *Base 36 *authData 37 *authAES128Function 38 *userData 39 iv []byte 40 hasSentHeader bool 41 rawTrans bool 42 packID uint32 43 recvID uint32 44 } 45 46 func newAuthAES128SHA1(b *Base) Protocol { 47 a := &authAES128{ 48 Base: b, 49 authData: &authData{}, 50 authAES128Function: &authAES128Function{salt: "auth_aes128_sha1", hmac: tools.HmacSHA1, hashDigest: tools.SHA1Sum}, 51 userData: &userData{}, 52 } 53 a.initUserData() 54 return a 55 } 56 57 func (a *authAES128) initUserData() { 58 params := strings.Split(a.Param, ":") 59 if len(params) > 1 { 60 if userID, err := strconv.ParseUint(params[0], 10, 32); err == nil { 61 binary.LittleEndian.PutUint32(a.userID[:], uint32(userID)) 62 a.userKey = a.hashDigest([]byte(params[1])) 63 } else { 64 log.Warn().Msgf("[SSR] wrong protocol-param for %s, only digits are expected before ':'", a.salt) 65 } 66 } 67 if len(a.userKey) == 0 { 68 a.userKey = a.Key 69 _, _ = R.Read(a.userID[:]) 70 } 71 } 72 73 func (a *authAES128) StreamConn(c net.Conn, iv []byte) net.Conn { 74 p := &authAES128{ 75 Base: a.Base, 76 authData: a.next(), 77 authAES128Function: a.authAES128Function, 78 userData: a.userData, 79 packID: 1, 80 recvID: 1, 81 } 82 p.iv = iv 83 return &Conn{Conn: c, Protocol: p} 84 } 85 86 func (a *authAES128) PacketConn(c net.PacketConn) net.PacketConn { 87 p := &authAES128{ 88 Base: a.Base, 89 authAES128Function: a.authAES128Function, 90 userData: a.userData, 91 } 92 return &PacketConn{PacketConn: c, Protocol: p} 93 } 94 95 func (a *authAES128) Decode(dst, src *bytes.Buffer) error { 96 if a.rawTrans { 97 _, _ = dst.ReadFrom(src) 98 return nil 99 } 100 for src.Len() > 4 { 101 macKey := pool.GetBufferWriter() 102 macKey.Grow(len(a.userKey) + 4) 103 copy(*macKey, a.userKey) 104 binary.LittleEndian.PutUint32((*macKey)[len(a.userKey):], a.recvID) 105 if !bytes.Equal(a.hmac(macKey.Bytes(), src.Bytes()[:2])[:2], src.Bytes()[2:4]) { 106 src.Reset() 107 pool.PutBufferWriter(macKey) 108 return errAuthAES128MACError 109 } 110 111 length := int(binary.LittleEndian.Uint16(src.Bytes()[:2])) 112 if length >= 8192 || length < 7 { 113 a.rawTrans = true 114 src.Reset() 115 pool.PutBufferWriter(macKey) 116 return errAuthAES128LengthError 117 } 118 if length > src.Len() { 119 pool.PutBufferWriter(macKey) 120 break 121 } 122 123 ok := bytes.Equal(a.hmac(macKey.Bytes(), src.Bytes()[:length-4])[:4], src.Bytes()[length-4:length]) 124 pool.PutBufferWriter(macKey) 125 if !ok { 126 a.rawTrans = true 127 src.Reset() 128 return errAuthAES128ChksumError 129 } 130 131 a.recvID++ 132 133 pos := int(src.Bytes()[4]) 134 if pos < 255 { 135 pos += 4 136 } else { 137 pos = int(binary.LittleEndian.Uint16(src.Bytes()[5:7])) + 4 138 } 139 dst.Write(src.Bytes()[pos : length-4]) 140 src.Next(length) 141 } 142 return nil 143 } 144 145 func (a *authAES128) Encode(buf *bytes.Buffer, b []byte) error { 146 fullDataLength := len(b) 147 if !a.hasSentHeader { 148 dataLength := getDataLength(b) 149 a.packAuthData(buf, b[:dataLength]) 150 b = b[dataLength:] 151 a.hasSentHeader = true 152 } 153 for len(b) > 8100 { 154 a.packData(buf, b[:8100], fullDataLength) 155 b = b[8100:] 156 } 157 if len(b) > 0 { 158 a.packData(buf, b, fullDataLength) 159 } 160 return nil 161 } 162 163 func (a *authAES128) DecodePacket(b []byte) ([]byte, error) { 164 if len(b) < 4 { 165 return nil, errAuthAES128LengthError 166 } 167 if !bytes.Equal(a.hmac(a.Key, b[:len(b)-4])[:4], b[len(b)-4:]) { 168 return nil, errAuthAES128ChksumError 169 } 170 return b[:len(b)-4], nil 171 } 172 173 func (a *authAES128) EncodePacket(buf *bytes.Buffer, b []byte) error { 174 buf.Write(b) 175 buf.Write(a.userID[:]) 176 buf.Write(a.hmac(a.userKey, buf.Bytes())[:4]) 177 return nil 178 } 179 180 func (a *authAES128) packData(poolBuf *bytes.Buffer, data []byte, fullDataLength int) { 181 dataLength := len(data) 182 randDataLength := a.getRandDataLengthForPackData(dataLength, fullDataLength) 183 /* 184 2: uint16 LittleEndian packedDataLength 185 2: hmac of packedDataLength 186 3: maxRandDataLengthPrefix (min:1) 187 4: hmac of packedData except the last 4 bytes 188 */ 189 packedDataLength := 2 + 2 + 3 + randDataLength + dataLength + 4 190 if randDataLength < 128 { 191 packedDataLength -= 2 192 } 193 194 macKey := pool.GetBufferWriter() 195 macKey.Grow(len(a.userKey) + 4) 196 defer pool.PutBufferWriter(macKey) 197 copy(*macKey, a.userKey) 198 binary.LittleEndian.PutUint32((*macKey)[len(a.userKey):], a.packID) 199 a.packID++ 200 201 _ = binary.Write(poolBuf, binary.LittleEndian, uint16(packedDataLength)) 202 poolBuf.Write(a.hmac(macKey.Bytes(), poolBuf.Bytes()[poolBuf.Len()-2:])[:2]) 203 a.packRandData(poolBuf, randDataLength) 204 poolBuf.Write(data) 205 poolBuf.Write(a.hmac(macKey.Bytes(), poolBuf.Bytes()[poolBuf.Len()-packedDataLength+4:])[:4]) 206 } 207 208 func trapezoidRandom(maxVal int, d float64) int { 209 base := rand.Float64() 210 if d-0 > 1e-6 { 211 a := 1 - d 212 base = (math.Sqrt(a*a+4*d*base) - a) / (2 * d) 213 } 214 return int(base * float64(maxVal)) 215 } 216 217 func (a *authAES128) getRandDataLengthForPackData(dataLength, fullDataLength int) int { 218 if fullDataLength >= 32*1024-a.Overhead { 219 return 0 220 } 221 // 1460: tcp_mss 222 revLength := 1460 - dataLength - 9 223 if revLength == 0 { 224 return 0 225 } 226 if revLength < 0 { 227 if revLength > -1460 { 228 return trapezoidRandom(revLength+1460, -0.3) 229 } 230 return rand.IntN(32) 231 } 232 if dataLength > 900 { 233 return rand.IntN(revLength) 234 } 235 return trapezoidRandom(revLength, -0.3) 236 } 237 238 func (a *authAES128) packAuthData(poolBuf *bytes.Buffer, data []byte) { 239 if len(data) == 0 { 240 return 241 } 242 dataLength := len(data) 243 randDataLength := a.getRandDataLengthForPackAuthData(dataLength) 244 /* 245 7: checkHead(1) and hmac of checkHead(6) 246 4: userID 247 16: encrypted data of authdata(12), uint16 BigEndian packedDataLength(2) and uint16 BigEndian randDataLength(2) 248 4: hmac of userID and encrypted data 249 4: hmac of packedAuthData except the last 4 bytes 250 */ 251 packedAuthDataLength := 7 + 4 + 16 + 4 + randDataLength + dataLength + 4 252 253 macKey := pool.GetBufferWriter() 254 defer pool.PutBufferWriter(macKey) 255 macKey.PutSlice(a.iv) 256 macKey.PutSlice(a.Key) 257 258 poolBuf.WriteByte(byte(rand.IntN(256))) 259 poolBuf.Write(a.hmac(macKey.Bytes(), poolBuf.Bytes())[:6]) 260 poolBuf.Write(a.userID[:]) 261 err := a.authData.putEncryptedData(poolBuf, a.userKey, [2]int{packedAuthDataLength, randDataLength}, a.salt) 262 if err != nil { 263 poolBuf.Reset() 264 return 265 } 266 poolBuf.Write(a.hmac(macKey.Bytes(), poolBuf.Bytes()[7:])[:4]) 267 tools.AppendRandBytes(poolBuf, randDataLength) 268 poolBuf.Write(data) 269 poolBuf.Write(a.hmac(a.userKey, poolBuf.Bytes())[:4]) 270 } 271 272 func (a *authAES128) getRandDataLengthForPackAuthData(size int) int { 273 if size > 400 { 274 return rand.IntN(512) 275 } 276 return rand.IntN(1024) 277 } 278 279 func (a *authAES128) packRandData(poolBuf *bytes.Buffer, size int) { 280 if size < 128 { 281 poolBuf.WriteByte(byte(size + 1)) 282 tools.AppendRandBytes(poolBuf, size) 283 return 284 } 285 poolBuf.WriteByte(255) 286 _ = binary.Write(poolBuf, binary.LittleEndian, uint16(size+3)) 287 tools.AppendRandBytes(poolBuf, size) 288 }