github.com/inazumav/sing-box@v0.0.0-20230926072359-ab51429a14f1/transport/clashssr/protocol/auth_aes128_sha1.go (about)

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