func (request *VMessRequest) ToBytes(idHash user.CounterHash, randomRangeInt64 user.RandomInt64InRange) ([]byte, error) { buffer := make([]byte, 0, 300) counter := randomRangeInt64(time.Now().UTC().Unix(), 30) hash := idHash.Hash(request.UserId.Bytes, counter) log.Debug("Writing userhash: %v", hash) buffer = append(buffer, hash...) encryptionBegin := len(buffer) randomLength := mrand.Intn(32) + 1 randomContent := make([]byte, randomLength) _, err := rand.Read(randomContent) if err != nil { return nil, err } buffer = append(buffer, byte(randomLength)) buffer = append(buffer, randomContent...) buffer = append(buffer, request.Version) buffer = append(buffer, request.RequestIV[:]...) buffer = append(buffer, request.RequestKey[:]...) buffer = append(buffer, request.ResponseHeader[:]...) buffer = append(buffer, request.Command) buffer = append(buffer, request.Address.PortBytes()...) switch { case request.Address.IsIPv4(): buffer = append(buffer, addrTypeIPv4) buffer = append(buffer, request.Address.IP()...) case request.Address.IsIPv6(): buffer = append(buffer, addrTypeIPv6) buffer = append(buffer, request.Address.IP()...) case request.Address.IsDomain(): buffer = append(buffer, addrTypeDomain) buffer = append(buffer, byte(len(request.Address.Domain()))) buffer = append(buffer, []byte(request.Address.Domain())...) } paddingLength := mrand.Intn(32) + 1 paddingBuffer := make([]byte, paddingLength) _, err = rand.Read(paddingBuffer) if err != nil { return nil, err } buffer = append(buffer, byte(paddingLength)) buffer = append(buffer, paddingBuffer...) encryptionEnd := len(buffer) aesCipher, err := aes.NewCipher(request.UserId.CmdKey()) if err != nil { return nil, err } aesStream := cipher.NewCFBEncrypter(aesCipher, user.Int64Hash(counter)) aesStream.XORKeyStream(buffer[encryptionBegin:encryptionEnd], buffer[encryptionBegin:encryptionEnd]) return buffer, nil }
func (vmess *VMessUDP) ToBytes(idHash user.CounterHash, randomRangeInt64 user.RandomInt64InRange, buffer []byte) []byte { if buffer == nil { buffer = make([]byte, 0, 2*1024) } counter := randomRangeInt64(time.Now().UTC().Unix(), 30) hash := idHash.Hash(vmess.user.Bytes[:], counter) buffer = append(buffer, hash...) encryptBegin := 16 // Placeholder for fnv1a hash buffer = append(buffer, byte(0), byte(0), byte(0), byte(0)) fnvHash := 16 fnvHashBegin := 20 buffer = append(buffer, vmess.version) buffer = append(buffer, byte(vmess.token>>8), byte(vmess.token)) buffer = append(buffer, byte(0x00)) buffer = append(buffer, vmess.address.PortBytes()...) switch { case vmess.address.IsIPv4(): buffer = append(buffer, addrTypeIPv4) buffer = append(buffer, vmess.address.IP()...) case vmess.address.IsIPv6(): buffer = append(buffer, addrTypeIPv6) buffer = append(buffer, vmess.address.IP()...) case vmess.address.IsDomain(): buffer = append(buffer, addrTypeDomain) buffer = append(buffer, byte(len(vmess.address.Domain()))) buffer = append(buffer, []byte(vmess.address.Domain())...) } buffer = append(buffer, vmess.data...) fnv1a := fnv.New32a() fnv1a.Write(buffer[fnvHashBegin:]) fnvHashValue := fnv1a.Sum32() buffer[fnvHash] = byte(fnvHashValue >> 24) buffer[fnvHash+1] = byte(fnvHashValue >> 16) buffer[fnvHash+2] = byte(fnvHashValue >> 8) buffer[fnvHash+3] = byte(fnvHashValue) aesCipher, err := aes.NewCipher(vmess.user.CmdKey()) if err != nil { log.Error("VMess failed to create AES cipher: %v", err) return nil } aesStream := cipher.NewCFBEncrypter(aesCipher, user.Int64Hash(counter)) aesStream.XORKeyStream(buffer[encryptBegin:], buffer[encryptBegin:]) return buffer }
// ToBytes returns a VMessRequest in the form of byte array. func (request *VMessRequest) ToBytes(idHash user.CounterHash, randomRangeInt64 user.RandomInt64InRange, buffer []byte) ([]byte, error) { if buffer == nil { buffer = make([]byte, 0, 300) } counter := randomRangeInt64(time.Now().UTC().Unix(), 30) hash := idHash.Hash(request.UserId.Bytes[:], counter) log.Debug("Writing userhash: %v", hash) buffer = append(buffer, hash...) encryptionBegin := len(buffer) buffer = append(buffer, request.Version) buffer = append(buffer, request.RequestIV[:]...) buffer = append(buffer, request.RequestKey[:]...) buffer = append(buffer, request.ResponseHeader[:]...) buffer = append(buffer, request.Command) buffer = append(buffer, request.Address.PortBytes()...) switch { case request.Address.IsIPv4(): buffer = append(buffer, addrTypeIPv4) buffer = append(buffer, request.Address.IP()...) case request.Address.IsIPv6(): buffer = append(buffer, addrTypeIPv6) buffer = append(buffer, request.Address.IP()...) case request.Address.IsDomain(): buffer = append(buffer, addrTypeDomain) buffer = append(buffer, byte(len(request.Address.Domain()))) buffer = append(buffer, []byte(request.Address.Domain())...) } encryptionEnd := len(buffer) fnv1a := fnv.New32a() fnv1a.Write(buffer[encryptionBegin:encryptionEnd]) fnvHash := fnv1a.Sum32() buffer = append(buffer, byte(fnvHash>>24)) buffer = append(buffer, byte(fnvHash>>16)) buffer = append(buffer, byte(fnvHash>>8)) buffer = append(buffer, byte(fnvHash)) encryptionEnd += 4 aesCipher, err := aes.NewCipher(request.UserId.CmdKey()) if err != nil { return nil, err } aesStream := cipher.NewCFBEncrypter(aesCipher, user.Int64Hash(counter)) aesStream.XORKeyStream(buffer[encryptionBegin:encryptionEnd], buffer[encryptionBegin:encryptionEnd]) return buffer, nil }
// ToBytes returns a VMessRequest in the form of byte array. func (request *VMessRequest) ToBytes(idHash user.CounterHash, randomRangeInt64 user.RandomInt64InRange, buffer *alloc.Buffer) (*alloc.Buffer, error) { if buffer == nil { buffer = alloc.NewSmallBuffer().Clear() } counter := randomRangeInt64(time.Now().UTC().Unix(), 30) hash := idHash.Hash(request.UserId.Bytes[:], counter) buffer.Append(hash) encryptionBegin := buffer.Len() buffer.AppendBytes(request.Version) buffer.Append(request.RequestIV) buffer.Append(request.RequestKey) buffer.Append(request.ResponseHeader) buffer.AppendBytes(request.Command) buffer.Append(request.Address.PortBytes()) switch { case request.Address.IsIPv4(): buffer.AppendBytes(addrTypeIPv4) buffer.Append(request.Address.IP()) case request.Address.IsIPv6(): buffer.AppendBytes(addrTypeIPv6) buffer.Append(request.Address.IP()) case request.Address.IsDomain(): buffer.AppendBytes(addrTypeDomain, byte(len(request.Address.Domain()))) buffer.Append([]byte(request.Address.Domain())) } encryptionEnd := buffer.Len() fnv1a := fnv.New32a() fnv1a.Write(buffer.Value[encryptionBegin:encryptionEnd]) fnvHash := fnv1a.Sum32() buffer.AppendBytes(byte(fnvHash>>24), byte(fnvHash>>16), byte(fnvHash>>8), byte(fnvHash)) encryptionEnd += 4 aesCipher, err := aes.NewCipher(request.UserId.CmdKey()) if err != nil { return nil, err } aesStream := cipher.NewCFBEncrypter(aesCipher, user.Int64Hash(counter)) aesStream.XORKeyStream(buffer.Value[encryptionBegin:encryptionEnd], buffer.Value[encryptionBegin:encryptionEnd]) return buffer, nil }