github.com/igoogolx/clash@v1.19.8/transport/ssr/protocol/auth_aes128_sha1.go (about)

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