github.com/metacubex/mihomo@v1.18.5/transport/ssr/protocol/auth_aes128_sha1.go (about)

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