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