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