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  }