github.com/Asutorufa/yuhaiin@v0.3.6-0.20240502055049-7984da7023a0/pkg/net/proxy/shadowsocksr/protocol/auth_sha1_v4.go (about) 1 package protocol 2 3 import ( 4 "bytes" 5 "crypto" 6 crand "crypto/rand" 7 "encoding/binary" 8 "math/rand/v2" 9 "time" 10 11 ssr "github.com/Asutorufa/yuhaiin/pkg/net/proxy/shadowsocksr/utils" 12 ) 13 14 type authSHA1v4 struct { 15 Protocol 16 hasSentHeader bool 17 } 18 19 func NewAuthSHA1v4(info Protocol) protocol { return &authSHA1v4{Protocol: info} } 20 21 func (a *authSHA1v4) packData(data []byte) (outData []byte) { 22 dataLength := len(data) 23 randLength := 1 24 25 if dataLength <= 1300 { 26 if dataLength > 400 { 27 randLength += rand.IntN(128) 28 } else { 29 randLength += rand.IntN(1024) 30 } 31 } 32 33 outLength := randLength + dataLength + 8 34 outData = make([]byte, outLength) 35 // 0~1, out length 36 binary.BigEndian.PutUint16(outData[0:2], uint16(outLength&0xFFFF)) 37 // 2~3, crc of out length 38 crc32 := ssr.CalcCRC32(outData, 2) 39 binary.LittleEndian.PutUint16(outData[2:4], uint16(crc32&0xFFFF)) 40 // 4, rand length 41 if randLength < 128 { 42 outData[4] = uint8(randLength & 0xFF) 43 } else { 44 outData[4] = uint8(0xFF) 45 binary.BigEndian.PutUint16(outData[5:7], uint16(randLength&0xFFFF)) 46 } 47 // rand length+4~out length-4, data 48 if dataLength > 0 { 49 copy(outData[randLength+4:], data) 50 } 51 // out length-4~end, adler32 of full data 52 adler := ssr.CalcAdler32(outData[:outLength-4]) 53 binary.LittleEndian.PutUint32(outData[outLength-4:], adler) 54 55 return outData 56 } 57 58 func (a *authSHA1v4) packAuthData(data []byte) (outData []byte) { 59 60 dataLength := len(data) 61 randLength := 1 62 if dataLength <= 1300 { 63 if dataLength > 400 { 64 randLength += rand.IntN(128) 65 } else { 66 randLength += rand.IntN(1024) 67 } 68 } 69 dataOffset := randLength + 4 + 2 70 outLength := dataOffset + dataLength + 12 + ssr.ObfsHMACSHA1Len 71 outData = make([]byte, outLength) 72 73 a.Auth.nextAuth() 74 75 // 0-1, out length 76 binary.BigEndian.PutUint16(outData[0:2], uint16(outLength&0xFFFF)) 77 78 // 2~6, crc of out length+salt+key 79 salt := []byte("auth_sha1_v4") 80 crcData := make([]byte, len(salt)+len(a.Key())+2) 81 copy(crcData[0:2], outData[0:2]) 82 copy(crcData[2:], salt) 83 copy(crcData[2+len(salt):], a.Key()) 84 crc32 := ssr.CalcCRC32(crcData, len(crcData)) 85 // 2~6, crc of out length+salt+key 86 binary.LittleEndian.PutUint32(outData[2:], crc32) 87 // 6~rand length+6, rand numbers 88 crand.Read(outData[dataOffset-randLength : dataOffset]) 89 // 6, rand length 90 if randLength < 128 { 91 outData[6] = byte(randLength & 0xFF) 92 } else { 93 // 6, magic number 0xFF 94 outData[6] = 0xFF 95 // 7-8, rand length 96 binary.BigEndian.PutUint16(outData[7:9], uint16(randLength&0xFFFF)) 97 } 98 // rand length+6~rand length+10, time stamp 99 now := time.Now().Unix() 100 binary.LittleEndian.PutUint32(outData[dataOffset:dataOffset+4], uint32(now)) 101 // rand length+10~rand length+14, client ID 102 copy(outData[dataOffset+4:dataOffset+4+4], a.Auth.clientID[0:4]) 103 // rand length+14~rand length+18, connection ID 104 binary.LittleEndian.PutUint32(outData[dataOffset+8:dataOffset+8+4], a.Auth.connectionID.Load()) 105 // rand length+18~rand length+18+data length, data 106 copy(outData[dataOffset+12:], data) 107 108 key := make([]byte, a.IVSize()+len(a.Key())) 109 copy(key, a.IV) 110 copy(key[a.IVSize():], a.Key()) 111 112 h := ssr.Hmac(crypto.SHA1, key, outData[:outLength-ssr.ObfsHMACSHA1Len], nil) 113 // out length-10~out length/rand length+18+data length~end, hmac 114 copy(outData[outLength-ssr.ObfsHMACSHA1Len:], h[0:ssr.ObfsHMACSHA1Len]) 115 return outData 116 } 117 118 func (a *authSHA1v4) EncryptStream(buffer *bytes.Buffer, plainData []byte) (err error) { 119 dataLength := len(plainData) 120 offset := 0 121 if !a.hasSentHeader && dataLength > 0 { 122 headSize := GetHeadSize(plainData, 30) 123 if headSize > dataLength { 124 headSize = dataLength 125 } 126 buffer.Write(a.packAuthData(plainData[:headSize])) 127 offset += headSize 128 dataLength -= headSize 129 a.hasSentHeader = true 130 } 131 const blockSize = 4096 132 for dataLength > blockSize { 133 buffer.Write(a.packData(plainData[offset : offset+blockSize])) 134 offset += blockSize 135 dataLength -= blockSize 136 } 137 if dataLength > 0 { 138 buffer.Write(a.packData(plainData[offset:])) 139 } 140 141 return nil 142 } 143 144 func (a *authSHA1v4) DecryptStream(dst *bytes.Buffer, plainData []byte) (n int, err error) { 145 dataLength := len(plainData) 146 plainLength := dataLength 147 for dataLength > 4 { 148 crc32 := ssr.CalcCRC32(plainData, 2) 149 if binary.LittleEndian.Uint16(plainData[2:4]) != uint16(crc32&0xFFFF) { 150 //common.Error("auth_sha1_v4 post decrypt data crc32 error") 151 return 0, ssr.ErrAuthSHA1v4CRC32Error 152 } 153 length := int(binary.BigEndian.Uint16(plainData[0:2])) 154 if length >= 8192 || length < 8 { 155 //common.Error("auth_sha1_v4 post decrypt data length error") 156 dataLength = 0 157 plainData = nil 158 return 0, ssr.ErrAuthSHA1v4DataLengthError 159 } 160 if length > dataLength { 161 break 162 } 163 164 if CheckAdler32(plainData, length) { 165 pos := int(plainData[4]) 166 if pos != 0xFF { 167 pos += 4 168 } else { 169 pos = int(binary.BigEndian.Uint16(plainData[5:5+2])) + 4 170 } 171 outLength := length - pos - 4 172 dst.Write(plainData[pos : pos+outLength]) 173 dataLength -= length 174 plainData = plainData[length:] 175 } else { 176 //common.Error("auth_sha1_v4 post decrypt incorrect checksum") 177 dataLength = 0 178 plainData = nil 179 return 0, ssr.ErrAuthSHA1v4IncorrectChecksum 180 } 181 } 182 return plainLength - dataLength, nil 183 } 184 185 func (a *authSHA1v4) GetOverhead() int { 186 return 7 187 } 188 189 func calcShortAdler32(input []byte, a, b uint32) (uint32, uint32) { 190 for _, i := range input { 191 a += uint32(i) 192 b += a 193 } 194 a %= 65521 195 b %= 65521 196 return a, b 197 } 198 199 func CalcAdler32(input []byte) uint32 { 200 var a uint32 = 1 201 var b uint32 = 0 202 const nMax = 5552 203 for length := len(input); length > nMax; length -= nMax { 204 a, b = calcShortAdler32(input[:nMax], a, b) 205 input = input[nMax:] 206 } 207 a, b = calcShortAdler32(input, a, b) 208 return (b << 16) + a 209 } 210 211 func CheckAdler32(input []byte, l int) bool { 212 adler32 := CalcAdler32(input[:l-4]) 213 checksum := binary.LittleEndian.Uint32(input[l-4:]) 214 return adler32 == checksum 215 } 216 217 func (a *authSHA1v4) EncryptPacket(b []byte) ([]byte, error) { 218 return b, nil 219 } 220 func (a *authSHA1v4) DecryptPacket(b []byte) ([]byte, error) { 221 return b, nil 222 }