github.com/metacubex/mihomo@v1.18.5/transport/ssr/protocol/auth_aes128_sha1.go (about) 1 package protocol 2 3 import ( 4 "bytes" 5 "encoding/binary" 6 "math" 7 "net" 8 "strconv" 9 "strings" 10 11 N "github.com/metacubex/mihomo/common/net" 12 "github.com/metacubex/mihomo/common/pool" 13 "github.com/metacubex/mihomo/log" 14 "github.com/metacubex/mihomo/transport/ssr/tools" 15 16 "github.com/zhangyunhao116/fastrand" 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.Warnln("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 fastrand.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 N.EnhancePacketConn) N.EnhancePacketConn { 87 p := &authAES128{ 88 Base: a.Base, 89 authAES128Function: a.authAES128Function, 90 userData: a.userData, 91 } 92 return &PacketConn{EnhancePacketConn: 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.Get(len(a.userKey) + 4) 102 defer pool.Put(macKey) 103 copy(macKey, a.userKey) 104 binary.LittleEndian.PutUint32(macKey[len(a.userKey):], a.recvID) 105 if !bytes.Equal(a.hmac(macKey, src.Bytes()[:2])[:2], src.Bytes()[2:4]) { 106 src.Reset() 107 return errAuthAES128MACError 108 } 109 110 length := int(binary.LittleEndian.Uint16(src.Bytes()[:2])) 111 if length >= 8192 || length < 7 { 112 a.rawTrans = true 113 src.Reset() 114 return errAuthAES128LengthError 115 } 116 if length > src.Len() { 117 break 118 } 119 120 if !bytes.Equal(a.hmac(macKey, src.Bytes()[:length-4])[:4], src.Bytes()[length-4:length]) { 121 a.rawTrans = true 122 src.Reset() 123 return errAuthAES128ChksumError 124 } 125 126 a.recvID++ 127 128 pos := int(src.Bytes()[4]) 129 if pos < 255 { 130 pos += 4 131 } else { 132 pos = int(binary.LittleEndian.Uint16(src.Bytes()[5:7])) + 4 133 } 134 dst.Write(src.Bytes()[pos : length-4]) 135 src.Next(length) 136 } 137 return nil 138 } 139 140 func (a *authAES128) Encode(buf *bytes.Buffer, b []byte) error { 141 fullDataLength := len(b) 142 if !a.hasSentHeader { 143 dataLength := getDataLength(b) 144 a.packAuthData(buf, b[:dataLength]) 145 b = b[dataLength:] 146 a.hasSentHeader = true 147 } 148 for len(b) > 8100 { 149 a.packData(buf, b[:8100], fullDataLength) 150 b = b[8100:] 151 } 152 if len(b) > 0 { 153 a.packData(buf, b, fullDataLength) 154 } 155 return nil 156 } 157 158 func (a *authAES128) DecodePacket(b []byte) ([]byte, error) { 159 if len(b) < 4 { 160 return nil, errAuthAES128LengthError 161 } 162 if !bytes.Equal(a.hmac(a.Key, b[:len(b)-4])[:4], b[len(b)-4:]) { 163 return nil, errAuthAES128ChksumError 164 } 165 return b[:len(b)-4], nil 166 } 167 168 func (a *authAES128) EncodePacket(buf *bytes.Buffer, b []byte) error { 169 buf.Write(b) 170 buf.Write(a.userID[:]) 171 buf.Write(a.hmac(a.userKey, buf.Bytes())[:4]) 172 return nil 173 } 174 175 func (a *authAES128) packData(poolBuf *bytes.Buffer, data []byte, fullDataLength int) { 176 dataLength := len(data) 177 randDataLength := a.getRandDataLengthForPackData(dataLength, fullDataLength) 178 /* 179 2: uint16 LittleEndian packedDataLength 180 2: hmac of packedDataLength 181 3: maxRandDataLengthPrefix (min:1) 182 4: hmac of packedData except the last 4 bytes 183 */ 184 packedDataLength := 2 + 2 + 3 + randDataLength + dataLength + 4 185 if randDataLength < 128 { 186 packedDataLength -= 2 187 } 188 189 macKey := pool.Get(len(a.userKey) + 4) 190 defer pool.Put(macKey) 191 copy(macKey, a.userKey) 192 binary.LittleEndian.PutUint32(macKey[len(a.userKey):], a.packID) 193 a.packID++ 194 195 binary.Write(poolBuf, binary.LittleEndian, uint16(packedDataLength)) 196 poolBuf.Write(a.hmac(macKey, poolBuf.Bytes()[poolBuf.Len()-2:])[:2]) 197 a.packRandData(poolBuf, randDataLength) 198 poolBuf.Write(data) 199 poolBuf.Write(a.hmac(macKey, poolBuf.Bytes()[poolBuf.Len()-packedDataLength+4:])[:4]) 200 } 201 202 func trapezoidRandom(max int, d float64) int { 203 base := fastrand.Float64() 204 if d-0 > 1e-6 { 205 a := 1 - d 206 base = (math.Sqrt(a*a+4*d*base) - a) / (2 * d) 207 } 208 return int(base * float64(max)) 209 } 210 211 func (a *authAES128) getRandDataLengthForPackData(dataLength, fullDataLength int) int { 212 if fullDataLength >= 32*1024-a.Overhead { 213 return 0 214 } 215 // 1460: tcp_mss 216 revLength := 1460 - dataLength - 9 217 if revLength == 0 { 218 return 0 219 } 220 if revLength < 0 { 221 if revLength > -1460 { 222 return trapezoidRandom(revLength+1460, -0.3) 223 } 224 return fastrand.Intn(32) 225 } 226 if dataLength > 900 { 227 return fastrand.Intn(revLength) 228 } 229 return trapezoidRandom(revLength, -0.3) 230 } 231 232 func (a *authAES128) packAuthData(poolBuf *bytes.Buffer, data []byte) { 233 if len(data) == 0 { 234 return 235 } 236 dataLength := len(data) 237 randDataLength := a.getRandDataLengthForPackAuthData(dataLength) 238 /* 239 7: checkHead(1) and hmac of checkHead(6) 240 4: userID 241 16: encrypted data of authdata(12), uint16 BigEndian packedDataLength(2) and uint16 BigEndian randDataLength(2) 242 4: hmac of userID and encrypted data 243 4: hmac of packedAuthData except the last 4 bytes 244 */ 245 packedAuthDataLength := 7 + 4 + 16 + 4 + randDataLength + dataLength + 4 246 247 macKey := pool.Get(len(a.iv) + len(a.Key)) 248 defer pool.Put(macKey) 249 copy(macKey, a.iv) 250 copy(macKey[len(a.iv):], a.Key) 251 252 poolBuf.WriteByte(byte(fastrand.Intn(256))) 253 poolBuf.Write(a.hmac(macKey, poolBuf.Bytes())[:6]) 254 poolBuf.Write(a.userID[:]) 255 err := a.authData.putEncryptedData(poolBuf, a.userKey, [2]int{packedAuthDataLength, randDataLength}, a.salt) 256 if err != nil { 257 poolBuf.Reset() 258 return 259 } 260 poolBuf.Write(a.hmac(macKey, poolBuf.Bytes()[7:])[:4]) 261 tools.AppendRandBytes(poolBuf, randDataLength) 262 poolBuf.Write(data) 263 poolBuf.Write(a.hmac(a.userKey, poolBuf.Bytes())[:4]) 264 } 265 266 func (a *authAES128) getRandDataLengthForPackAuthData(size int) int { 267 if size > 400 { 268 return fastrand.Intn(512) 269 } 270 return fastrand.Intn(1024) 271 } 272 273 func (a *authAES128) packRandData(poolBuf *bytes.Buffer, size int) { 274 if size < 128 { 275 poolBuf.WriteByte(byte(size + 1)) 276 tools.AppendRandBytes(poolBuf, size) 277 return 278 } 279 poolBuf.WriteByte(255) 280 binary.Write(poolBuf, binary.LittleEndian, uint16(size+3)) 281 tools.AppendRandBytes(poolBuf, size) 282 }