github.com/laof/lite-speed-test@v0.0.0-20230930011949-1f39b7037845/transport/ssr/protocol/auth_sha1_v4.go (about) 1 package protocol 2 3 import ( 4 "bytes" 5 "encoding/binary" 6 "hash/adler32" 7 "hash/crc32" 8 "math/rand" 9 "net" 10 11 "github.com/laof/lite-speed-test/common/pool" 12 "github.com/laof/lite-speed-test/transport/ssr/tools" 13 ) 14 15 func init() { 16 register("auth_sha1_v4", newAuthSHA1V4, 7) 17 } 18 19 type authSHA1V4 struct { 20 *Base 21 *authData 22 iv []byte 23 hasSentHeader bool 24 rawTrans bool 25 } 26 27 func newAuthSHA1V4(b *Base) Protocol { 28 return &authSHA1V4{Base: b, authData: &authData{}} 29 } 30 31 func (a *authSHA1V4) StreamConn(c net.Conn, iv []byte) net.Conn { 32 p := &authSHA1V4{Base: a.Base, authData: a.next()} 33 p.iv = iv 34 return &Conn{Conn: c, Protocol: p} 35 } 36 37 func (a *authSHA1V4) PacketConn(c net.PacketConn) net.PacketConn { 38 return c 39 } 40 41 func (a *authSHA1V4) Decode(dst, src *bytes.Buffer) error { 42 if a.rawTrans { 43 dst.ReadFrom(src) 44 return nil 45 } 46 for src.Len() > 4 { 47 if uint16(crc32.ChecksumIEEE(src.Bytes()[:2])&0xffff) != binary.LittleEndian.Uint16(src.Bytes()[2:4]) { 48 src.Reset() 49 return errAuthSHA1V4CRC32Error 50 } 51 52 length := int(binary.BigEndian.Uint16(src.Bytes()[:2])) 53 if length >= 8192 || length < 7 { 54 a.rawTrans = true 55 src.Reset() 56 return errAuthSHA1V4LengthError 57 } 58 if length > src.Len() { 59 break 60 } 61 62 if adler32.Checksum(src.Bytes()[:length-4]) != binary.LittleEndian.Uint32(src.Bytes()[length-4:length]) { 63 a.rawTrans = true 64 src.Reset() 65 return errAuthSHA1V4Adler32Error 66 } 67 68 pos := int(src.Bytes()[4]) 69 if pos < 255 { 70 pos += 4 71 } else { 72 pos = int(binary.BigEndian.Uint16(src.Bytes()[5:7])) + 4 73 } 74 dst.Write(src.Bytes()[pos : length-4]) 75 src.Next(length) 76 } 77 return nil 78 } 79 80 func (a *authSHA1V4) Encode(buf *bytes.Buffer, b []byte) error { 81 if !a.hasSentHeader { 82 dataLength := getDataLength(b) 83 84 a.packAuthData(buf, b[:dataLength]) 85 b = b[dataLength:] 86 87 a.hasSentHeader = true 88 } 89 for len(b) > 8100 { 90 a.packData(buf, b[:8100]) 91 b = b[8100:] 92 } 93 if len(b) > 0 { 94 a.packData(buf, b) 95 } 96 97 return nil 98 } 99 100 func (a *authSHA1V4) DecodePacket(b []byte) ([]byte, error) { return b, nil } 101 102 func (a *authSHA1V4) EncodePacket(buf *bytes.Buffer, b []byte) error { 103 buf.Write(b) 104 return nil 105 } 106 107 func (a *authSHA1V4) packData(poolBuf *bytes.Buffer, data []byte) { 108 dataLength := len(data) 109 randDataLength := a.getRandDataLength(dataLength) 110 /* 111 2: uint16 BigEndian packedDataLength 112 2: uint16 LittleEndian crc32Data & 0xffff 113 3: maxRandDataLengthPrefix (min:1) 114 4: adler32Data 115 */ 116 packedDataLength := 2 + 2 + 3 + randDataLength + dataLength + 4 117 if randDataLength < 128 { 118 packedDataLength -= 2 119 } 120 121 binary.Write(poolBuf, binary.BigEndian, uint16(packedDataLength)) 122 binary.Write(poolBuf, binary.LittleEndian, uint16(crc32.ChecksumIEEE(poolBuf.Bytes()[poolBuf.Len()-2:])&0xffff)) 123 a.packRandData(poolBuf, randDataLength) 124 poolBuf.Write(data) 125 binary.Write(poolBuf, binary.LittleEndian, adler32.Checksum(poolBuf.Bytes()[poolBuf.Len()-packedDataLength+4:])) 126 } 127 128 func (a *authSHA1V4) packAuthData(poolBuf *bytes.Buffer, data []byte) { 129 dataLength := len(data) 130 randDataLength := a.getRandDataLength(12 + dataLength) 131 /* 132 2: uint16 BigEndian packedAuthDataLength 133 4: uint32 LittleEndian crc32Data 134 3: maxRandDataLengthPrefix (min: 1) 135 12: authDataLength 136 10: hmacSHA1DataLength 137 */ 138 packedAuthDataLength := 2 + 4 + 3 + randDataLength + 12 + dataLength + 10 139 if randDataLength < 128 { 140 packedAuthDataLength -= 2 141 } 142 143 salt := []byte("auth_sha1_v4") 144 crcData := pool.Get(len(salt) + len(a.Key) + 2) 145 defer pool.Put(crcData) 146 binary.BigEndian.PutUint16(crcData, uint16(packedAuthDataLength)) 147 copy(crcData[2:], salt) 148 copy(crcData[2+len(salt):], a.Key) 149 150 key := pool.Get(len(a.iv) + len(a.Key)) 151 defer pool.Put(key) 152 copy(key, a.iv) 153 copy(key[len(a.iv):], a.Key) 154 155 poolBuf.Write(crcData[:2]) 156 binary.Write(poolBuf, binary.LittleEndian, crc32.ChecksumIEEE(crcData)) 157 a.packRandData(poolBuf, randDataLength) 158 a.putAuthData(poolBuf) 159 poolBuf.Write(data) 160 poolBuf.Write(tools.HmacSHA1(key, poolBuf.Bytes()[poolBuf.Len()-packedAuthDataLength+10:])[:10]) 161 } 162 163 func (a *authSHA1V4) packRandData(poolBuf *bytes.Buffer, size int) { 164 if size < 128 { 165 poolBuf.WriteByte(byte(size + 1)) 166 tools.AppendRandBytes(poolBuf, size) 167 return 168 } 169 poolBuf.WriteByte(255) 170 binary.Write(poolBuf, binary.BigEndian, uint16(size+3)) 171 tools.AppendRandBytes(poolBuf, size) 172 } 173 174 func (a *authSHA1V4) getRandDataLength(size int) int { 175 if size > 1200 { 176 return 0 177 } 178 if size > 400 { 179 return rand.Intn(256) 180 } 181 return rand.Intn(512) 182 }