github.com/chwjbn/xclash@v0.2.0/transport/ssr/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/chwjbn/xclash/common/pool"
    13  	"github.com/chwjbn/xclash/log"
    14  	"github.com/chwjbn/xclash/transport/ssr/tools"
    15  )
    16  
    17  type (
    18  	hmacMethod       func(key, data []byte) []byte
    19  	hashDigestMethod func([]byte) []byte
    20  )
    21  
    22  func init() {
    23  	register("auth_aes128_sha1", newAuthAES128SHA1, 9)
    24  }
    25  
    26  type authAES128Function struct {
    27  	salt       string
    28  	hmac       hmacMethod
    29  	hashDigest hashDigestMethod
    30  }
    31  
    32  type authAES128 struct {
    33  	*Base
    34  	*authData
    35  	*authAES128Function
    36  	*userData
    37  	iv            []byte
    38  	hasSentHeader bool
    39  	rawTrans      bool
    40  	packID        uint32
    41  	recvID        uint32
    42  }
    43  
    44  func newAuthAES128SHA1(b *Base) Protocol {
    45  	a := &authAES128{
    46  		Base:               b,
    47  		authData:           &authData{},
    48  		authAES128Function: &authAES128Function{salt: "auth_aes128_sha1", hmac: tools.HmacSHA1, hashDigest: tools.SHA1Sum},
    49  		userData:           &userData{},
    50  	}
    51  	a.initUserData()
    52  	return a
    53  }
    54  
    55  func (a *authAES128) initUserData() {
    56  	params := strings.Split(a.Param, ":")
    57  	if len(params) > 1 {
    58  		if userID, err := strconv.ParseUint(params[0], 10, 32); err == nil {
    59  			binary.LittleEndian.PutUint32(a.userID[:], uint32(userID))
    60  			a.userKey = a.hashDigest([]byte(params[1]))
    61  		} else {
    62  			log.Warnln("Wrong protocol-param for %s, only digits are expected before ':'", a.salt)
    63  		}
    64  	}
    65  	if len(a.userKey) == 0 {
    66  		a.userKey = a.Key
    67  		rand.Read(a.userID[:])
    68  	}
    69  }
    70  
    71  func (a *authAES128) StreamConn(c net.Conn, iv []byte) net.Conn {
    72  	p := &authAES128{
    73  		Base:               a.Base,
    74  		authData:           a.next(),
    75  		authAES128Function: a.authAES128Function,
    76  		userData:           a.userData,
    77  		packID:             1,
    78  		recvID:             1,
    79  	}
    80  	p.iv = iv
    81  	return &Conn{Conn: c, Protocol: p}
    82  }
    83  
    84  func (a *authAES128) PacketConn(c net.PacketConn) net.PacketConn {
    85  	p := &authAES128{
    86  		Base:               a.Base,
    87  		authAES128Function: a.authAES128Function,
    88  		userData:           a.userData,
    89  	}
    90  	return &PacketConn{PacketConn: c, Protocol: p}
    91  }
    92  
    93  func (a *authAES128) Decode(dst, src *bytes.Buffer) error {
    94  	if a.rawTrans {
    95  		dst.ReadFrom(src)
    96  		return nil
    97  	}
    98  	for src.Len() > 4 {
    99  		macKey := pool.Get(len(a.userKey) + 4)
   100  		defer pool.Put(macKey)
   101  		copy(macKey, a.userKey)
   102  		binary.LittleEndian.PutUint32(macKey[len(a.userKey):], a.recvID)
   103  		if !bytes.Equal(a.hmac(macKey, src.Bytes()[:2])[:2], src.Bytes()[2:4]) {
   104  			src.Reset()
   105  			return errAuthAES128MACError
   106  		}
   107  
   108  		length := int(binary.LittleEndian.Uint16(src.Bytes()[:2]))
   109  		if length >= 8192 || length < 7 {
   110  			a.rawTrans = true
   111  			src.Reset()
   112  			return errAuthAES128LengthError
   113  		}
   114  		if length > src.Len() {
   115  			break
   116  		}
   117  
   118  		if !bytes.Equal(a.hmac(macKey, src.Bytes()[:length-4])[:4], src.Bytes()[length-4:length]) {
   119  			a.rawTrans = true
   120  			src.Reset()
   121  			return errAuthAES128ChksumError
   122  		}
   123  
   124  		a.recvID++
   125  
   126  		pos := int(src.Bytes()[4])
   127  		if pos < 255 {
   128  			pos += 4
   129  		} else {
   130  			pos = int(binary.LittleEndian.Uint16(src.Bytes()[5:7])) + 4
   131  		}
   132  		dst.Write(src.Bytes()[pos : length-4])
   133  		src.Next(length)
   134  	}
   135  	return nil
   136  }
   137  
   138  func (a *authAES128) Encode(buf *bytes.Buffer, b []byte) error {
   139  	fullDataLength := len(b)
   140  	if !a.hasSentHeader {
   141  		dataLength := getDataLength(b)
   142  		a.packAuthData(buf, b[:dataLength])
   143  		b = b[dataLength:]
   144  		a.hasSentHeader = true
   145  	}
   146  	for len(b) > 8100 {
   147  		a.packData(buf, b[:8100], fullDataLength)
   148  		b = b[8100:]
   149  	}
   150  	if len(b) > 0 {
   151  		a.packData(buf, b, fullDataLength)
   152  	}
   153  	return nil
   154  }
   155  
   156  func (a *authAES128) DecodePacket(b []byte) ([]byte, error) {
   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  }