diff --git a/common/crypto/auth.go b/common/crypto/auth.go index 51722c11..4d81fc41 100644 --- a/common/crypto/auth.go +++ b/common/crypto/auth.go @@ -258,7 +258,7 @@ func (w *AuthenticationWriter) seal(b *buf.Buffer) (*buf.Buffer, error) { eb := buf.New() common.Must(eb.Reset(func(bb []byte) (int, error) { - w.sizeParser.Encode(uint16(encryptedSize+paddingSize), bb[:0]) + w.sizeParser.Encode(uint16(encryptedSize+paddingSize), bb) return int(w.sizeParser.SizeBytes()), nil })) if err := eb.AppendSupplier(func(bb []byte) (int, error) { diff --git a/common/crypto/chunk.go b/common/crypto/chunk.go index 6fb037a8..b5314617 100755 --- a/common/crypto/chunk.go +++ b/common/crypto/chunk.go @@ -6,7 +6,6 @@ import ( "v2ray.com/core/common" "v2ray.com/core/common/buf" - "v2ray.com/core/common/serial" ) // ChunkSizeDecoder is a utility class to decode size value from bytes. @@ -33,7 +32,8 @@ func (PlainChunkSizeParser) SizeBytes() int32 { } func (PlainChunkSizeParser) Encode(size uint16, b []byte) []byte { - return serial.Uint16ToBytes(size, b) + binary.BigEndian.PutUint16(b, size) + return b[:2] } func (PlainChunkSizeParser) Decode(b []byte) (uint16, error) { @@ -49,8 +49,8 @@ func (p *AEADChunkSizeParser) SizeBytes() int32 { } func (p *AEADChunkSizeParser) Encode(size uint16, b []byte) []byte { - b = serial.Uint16ToBytes(size-uint16(p.Auth.Overhead()), b) - b, err := p.Auth.Seal(b[:0], b) + binary.BigEndian.PutUint16(b, size-uint16(p.Auth.Overhead())) + b, err := p.Auth.Seal(b[:0], b[:2]) common.Must(err) return b } @@ -147,7 +147,7 @@ func (w *ChunkStreamWriter) WriteMultiBuffer(mb buf.MultiBuffer) error { b := buf.New() common.Must(b.Reset(func(buffer []byte) (int, error) { - w.sizeEncoder.Encode(uint16(slice.Len()), buffer[:0]) + w.sizeEncoder.Encode(uint16(slice.Len()), buffer) return int(w.sizeEncoder.SizeBytes()), nil })) mb2Write.Append(b) diff --git a/common/net/port.go b/common/net/port.go index 3594ca0d..1fdd5256 100644 --- a/common/net/port.go +++ b/common/net/port.go @@ -3,8 +3,6 @@ package net import ( "encoding/binary" "strconv" - - "v2ray.com/core/common/serial" ) // Port represents a network port in TCP and UDP protocol. @@ -42,7 +40,7 @@ func (p Port) Value() uint16 { // String returns the string presentation of a Port. func (p Port) String() string { - return serial.Uint16ToString(p.Value()) + return strconv.Itoa(int(p)) } // FromPort returns the beginning port of this PortRange. diff --git a/common/protocol/time.go b/common/protocol/time.go index 10a585d2..0c0d145d 100644 --- a/common/protocol/time.go +++ b/common/protocol/time.go @@ -4,15 +4,10 @@ import ( "time" "v2ray.com/core/common/dice" - "v2ray.com/core/common/serial" ) type Timestamp int64 -func (v Timestamp) Bytes(b []byte) []byte { - return serial.Int64ToBytes(int64(v), b) -} - type TimestampGenerator func() Timestamp func NowTime() Timestamp { diff --git a/common/serial/numbers.go b/common/serial/numbers.go deleted file mode 100755 index a255c71b..00000000 --- a/common/serial/numbers.go +++ /dev/null @@ -1,43 +0,0 @@ -package serial - -import "strconv" - -// Uint16ToBytes serializes a uint16 into bytes in big endian order. -func Uint16ToBytes(value uint16, b []byte) []byte { - return append(b, byte(value>>8), byte(value)) -} - -func Uint16ToString(value uint16) string { - return strconv.Itoa(int(value)) -} - -func Uint32ToBytes(value uint32, b []byte) []byte { - return append(b, byte(value>>24), byte(value>>16), byte(value>>8), byte(value)) -} - -func Uint32ToString(value uint32) string { - return strconv.FormatUint(uint64(value), 10) -} - -func WriteUint32(value uint32) func([]byte) (int, error) { - return func(b []byte) (int, error) { - Uint32ToBytes(value, b[:0]) - return 4, nil - } -} - -func Int64ToBytes(value int64, b []byte) []byte { - return append(b, - byte(value>>56), - byte(value>>48), - byte(value>>40), - byte(value>>32), - byte(value>>24), - byte(value>>16), - byte(value>>8), - byte(value)) -} - -func Int64ToString(value int64) string { - return strconv.FormatInt(value, 10) -} diff --git a/common/serial/numbers_test.go b/common/serial/numbers_test.go deleted file mode 100644 index 7d67f1ed..00000000 --- a/common/serial/numbers_test.go +++ /dev/null @@ -1,20 +0,0 @@ -package serial_test - -import ( - "testing" - - "v2ray.com/core/common" - "v2ray.com/core/common/buf" - . "v2ray.com/core/common/serial" - . "v2ray.com/ext/assert" -) - -func TestUint32(t *testing.T) { - assert := With(t) - - x := uint32(458634234) - s1 := Uint32ToBytes(x, []byte{}) - s2 := buf.New() - common.Must(s2.AppendSupplier(WriteUint32(x))) - assert(s1, Equals, s2.Bytes()) -} diff --git a/common/vio/serial.go b/common/vio/serial.go index f3180ee7..cb2b56e5 100644 --- a/common/vio/serial.go +++ b/common/vio/serial.go @@ -5,12 +5,6 @@ import ( "io" ) -func WriteUint32(writer io.Writer, value uint32) (int, error) { - var b [4]byte - binary.BigEndian.PutUint32(b[:], value) - return writer.Write(b[:]) -} - func ReadUint16(reader io.Reader) (uint16, error) { var b [2]byte if _, err := io.ReadFull(reader, b[:]); err != nil { @@ -24,3 +18,15 @@ func WriteUint16(writer io.Writer, value uint16) (int, error) { binary.BigEndian.PutUint16(b[:], value) return writer.Write(b[:]) } + +func WriteUint32(writer io.Writer, value uint32) (int, error) { + var b [4]byte + binary.BigEndian.PutUint32(b[:], value) + return writer.Write(b[:]) +} + +func WriteUint64(writer io.Writer, value uint64) (int, error) { + var b [8]byte + binary.BigEndian.PutUint64(b[:], value) + return writer.Write(b[:]) +} diff --git a/proxy/shadowsocks/ota.go b/proxy/shadowsocks/ota.go index 4e4b1a0f..8b2f1e21 100644 --- a/proxy/shadowsocks/ota.go +++ b/proxy/shadowsocks/ota.go @@ -10,7 +10,6 @@ import ( "v2ray.com/core/common" "v2ray.com/core/common/buf" "v2ray.com/core/common/bytespool" - "v2ray.com/core/common/serial" "v2ray.com/core/common/vio" ) @@ -54,7 +53,7 @@ func ChunkKeyGenerator(iv []byte) func() []byte { return func() []byte { newKey := make([]byte, len(iv)+4) copy(newKey, iv) - binary.BigEndian.PutUint32(newKey[len(iv):], newKey) + binary.BigEndian.PutUint32(newKey[len(iv):], chunkID) chunkID++ return newKey } @@ -121,7 +120,7 @@ func (w *ChunkWriter) WriteMultiBuffer(mb buf.MultiBuffer) error { for { payloadLen, _ := mb.Read(w.buffer[2+AuthSize:]) - serial.Uint16ToBytes(uint16(payloadLen), w.buffer[:0]) + binary.BigEndian.PutUint16(w.buffer, uint16(payloadLen)) w.auth.Authenticate(w.buffer[2+AuthSize : 2+AuthSize+payloadLen])(w.buffer[2:]) if err := buf.WriteAllBytes(w.writer, w.buffer[:2+AuthSize+payloadLen]); err != nil { return err diff --git a/proxy/vmess/encoding/auth.go b/proxy/vmess/encoding/auth.go index 49df46b3..9a923157 100644 --- a/proxy/vmess/encoding/auth.go +++ b/proxy/vmess/encoding/auth.go @@ -6,7 +6,6 @@ import ( "hash/fnv" "v2ray.com/core/common" - "v2ray.com/core/common/serial" "golang.org/x/crypto/sha3" ) @@ -54,7 +53,8 @@ func (*FnvAuthenticator) Overhead() int { // Seal implements AEAD.Seal(). func (*FnvAuthenticator) Seal(dst, nonce, plaintext, additionalData []byte) []byte { - dst = serial.Uint32ToBytes(Authenticate(plaintext), dst) + dst = append(dst, 0, 0, 0, 0) + binary.BigEndian.PutUint32(dst, Authenticate(plaintext)) return append(dst, plaintext...) } @@ -106,7 +106,8 @@ func (s *ShakeSizeParser) Decode(b []byte) (uint16, error) { func (s *ShakeSizeParser) Encode(size uint16, b []byte) []byte { mask := s.next() - return serial.Uint16ToBytes(mask^size, b[:0]) + binary.BigEndian.PutUint16(b, mask^size) + return b[:2] } func (s *ShakeSizeParser) NextPaddingLen() uint16 { diff --git a/proxy/vmess/encoding/client.go b/proxy/vmess/encoding/client.go index 7005d175..d54c9e56 100644 --- a/proxy/vmess/encoding/client.go +++ b/proxy/vmess/encoding/client.go @@ -3,6 +3,8 @@ package encoding import ( "crypto/md5" "crypto/rand" + "encoding/binary" + "hash" "hash/fnv" "io" @@ -15,16 +17,16 @@ import ( "v2ray.com/core/common/dice" "v2ray.com/core/common/protocol" "v2ray.com/core/common/serial" + "v2ray.com/core/common/vio" "v2ray.com/core/proxy/vmess" ) -func hashTimestamp(t protocol.Timestamp) []byte { - bytes := make([]byte, 0, 32) - bytes = t.Bytes(bytes) - bytes = t.Bytes(bytes) - bytes = t.Bytes(bytes) - bytes = t.Bytes(bytes) - return bytes +func hashTimestamp(h hash.Hash, t protocol.Timestamp) []byte { + vio.WriteUint64(h, uint64(t)) + vio.WriteUint64(h, uint64(t)) + vio.WriteUint64(h, uint64(t)) + vio.WriteUint64(h, uint64(t)) + return h.Sum(nil) } // ClientSession stores connection session info for VMess client. @@ -58,7 +60,7 @@ func (c *ClientSession) EncodeRequestHeader(header *protocol.RequestHeader, writ timestamp := protocol.NewTimestampGenerator(protocol.NowTime(), 30)() account := header.User.Account.(*vmess.MemoryAccount) idHash := c.idHash(account.AnyValidID().Bytes()) - common.Must2(idHash.Write(timestamp.Bytes(nil))) + common.Must2(vio.WriteUint64(idHash, uint64(timestamp))) common.Must2(writer.Write(idHash.Sum(nil))) buffer := buf.New() @@ -89,7 +91,7 @@ func (c *ClientSession) EncodeRequestHeader(header *protocol.RequestHeader, writ common.Must(buffer.AppendSupplier(serial.WriteHash(fnv1a))) } - iv := md5.Sum(hashTimestamp(timestamp)) + iv := hashTimestamp(md5.New(), timestamp) aesStream := crypto.NewAesEncryptionStream(account.ID.CmdKey(), iv[:]) aesStream.XORKeyStream(buffer.Bytes(), buffer.Bytes()) common.Must2(writer.Write(buffer.Bytes())) @@ -258,7 +260,7 @@ func GenerateChunkNonce(nonce []byte, size uint32) crypto.BytesGenerator { c := append([]byte(nil), nonce...) count := uint16(0) return func() []byte { - serial.Uint16ToBytes(count, c[:0]) + binary.BigEndian.PutUint16(c, count) count++ return c[:size] } diff --git a/proxy/vmess/encoding/commands.go b/proxy/vmess/encoding/commands.go index 261e4716..0be8741a 100644 --- a/proxy/vmess/encoding/commands.go +++ b/proxy/vmess/encoding/commands.go @@ -8,7 +8,6 @@ import ( "v2ray.com/core/common/buf" "v2ray.com/core/common/net" "v2ray.com/core/common/protocol" - "v2ray.com/core/common/serial" "v2ray.com/core/common/uuid" "v2ray.com/core/common/vio" ) @@ -101,8 +100,7 @@ func (f *CommandSwitchAccountFactory) Marshal(command interface{}, writer io.Wri idBytes := cmd.ID.Bytes() common.Must2(writer.Write(idBytes)) - - common.Must2(writer.Write(serial.Uint16ToBytes(cmd.AlterIds, nil))) + common.Must2(vio.WriteUint16(writer, cmd.AlterIds)) common.Must2(writer.Write([]byte{byte(cmd.Level)})) common.Must2(writer.Write([]byte{cmd.ValidMin})) diff --git a/proxy/vmess/encoding/server.go b/proxy/vmess/encoding/server.go index f185fb47..5bf680b9 100644 --- a/proxy/vmess/encoding/server.go +++ b/proxy/vmess/encoding/server.go @@ -134,7 +134,7 @@ func (s *ServerSession) DecodeRequestHeader(reader io.Reader) (*protocol.Request return nil, newError("invalid user") } - iv := md5.Sum(hashTimestamp(timestamp)) + iv := hashTimestamp(md5.New(), timestamp) vmessAccount := user.Account.(*vmess.MemoryAccount) aesStream := crypto.NewAesDecryptionStream(vmessAccount.ID.CmdKey(), iv[:]) diff --git a/proxy/vmess/validator.go b/proxy/vmess/validator.go index dc244634..ea06ed5c 100644 --- a/proxy/vmess/validator.go +++ b/proxy/vmess/validator.go @@ -5,6 +5,8 @@ import ( "sync" "time" + "v2ray.com/core/common/vio" + "v2ray.com/core/common" "v2ray.com/core/common/protocol" "v2ray.com/core/common/task" @@ -64,7 +66,7 @@ func (v *TimedUserValidator) generateNewHashes(nowSec protocol.Timestamp, user * genBeginSec = nowSec - cacheDurationSec } for ts := genBeginSec; ts <= genEndSec; ts++ { - common.Must2(idHash.Write(ts.Bytes(nil))) + common.Must2(vio.WriteUint64(idHash, uint64(ts))) idHash.Sum(hashValue[:0]) idHash.Reset() diff --git a/proxy/vmess/validator_test.go b/proxy/vmess/validator_test.go index 08701421..a82ae1ef 100644 --- a/proxy/vmess/validator_test.go +++ b/proxy/vmess/validator_test.go @@ -5,9 +5,9 @@ import ( "time" "v2ray.com/core/common" - "v2ray.com/core/common/uuid" - "v2ray.com/core/common/protocol" + "v2ray.com/core/common/uuid" + "v2ray.com/core/common/vio" . "v2ray.com/core/proxy/vmess" . "v2ray.com/ext/assert" ) @@ -39,7 +39,7 @@ func TestUserValidator(t *testing.T) { testSmallLag := func(lag time.Duration) { ts := protocol.Timestamp(time.Now().Add(time.Second * lag).Unix()) idHash := hasher(id.Bytes()) - idHash.Write(ts.Bytes(nil)) + common.Must2(vio.WriteUint64(idHash, uint64(ts))) userHash := idHash.Sum(nil) euser, ets, found := v.Get(userHash) @@ -61,7 +61,7 @@ func TestUserValidator(t *testing.T) { testBigLag := func(lag time.Duration) { ts := protocol.Timestamp(time.Now().Add(time.Second * lag).Unix()) idHash := hasher(id.Bytes()) - idHash.Write(ts.Bytes(nil)) + common.Must2(vio.WriteUint64(idHash, uint64(ts))) userHash := idHash.Sum(nil) euser, _, found := v.Get(userHash) diff --git a/transport/internet/headers/srtp/srtp.go b/transport/internet/headers/srtp/srtp.go index 4d5cacf4..85fe9b08 100644 --- a/transport/internet/headers/srtp/srtp.go +++ b/transport/internet/headers/srtp/srtp.go @@ -2,10 +2,10 @@ package srtp import ( "context" + "encoding/binary" "v2ray.com/core/common" "v2ray.com/core/common/dice" - "v2ray.com/core/common/serial" ) type SRTP struct { @@ -20,8 +20,8 @@ func (*SRTP) Size() int32 { // Write implements io.Writer. func (s *SRTP) Write(b []byte) (int, error) { s.number++ - serial.Uint16ToBytes(s.number, b[:0]) - serial.Uint16ToBytes(s.number, b[:2]) + binary.BigEndian.PutUint16(b, s.number) + binary.BigEndian.PutUint16(b[2:], s.number) return 4, nil } diff --git a/transport/internet/headers/utp/utp.go b/transport/internet/headers/utp/utp.go index e556bf52..d3581160 100644 --- a/transport/internet/headers/utp/utp.go +++ b/transport/internet/headers/utp/utp.go @@ -2,10 +2,10 @@ package utp import ( "context" + "encoding/binary" "v2ray.com/core/common" "v2ray.com/core/common/dice" - "v2ray.com/core/common/serial" ) type UTP struct { @@ -20,7 +20,7 @@ func (*UTP) Size() int32 { // Write implements io.Writer. func (u *UTP) Write(b []byte) (int, error) { - serial.Uint16ToBytes(u.connectionId, b[:0]) + binary.BigEndian.PutUint16(b, u.connectionId) b[2] = u.header b[3] = u.extension return 4, nil diff --git a/transport/internet/kcp/crypt.go b/transport/internet/kcp/crypt.go index 028cc65c..66b7c1e3 100644 --- a/transport/internet/kcp/crypt.go +++ b/transport/internet/kcp/crypt.go @@ -6,7 +6,6 @@ import ( "hash/fnv" "v2ray.com/core/common" - "v2ray.com/core/common/serial" ) // SimpleAuthenticator is a legacy AEAD used for KCP encryption. @@ -29,8 +28,8 @@ func (*SimpleAuthenticator) Overhead() int { // Seal implements cipher.AEAD.Seal(). func (a *SimpleAuthenticator) Seal(dst, nonce, plain, extra []byte) []byte { - dst = append(dst, 0, 0, 0, 0) - dst = serial.Uint16ToBytes(uint16(len(plain)), dst) + dst = append(dst, 0, 0, 0, 0, 0, 0) // 4 bytes for hash, and then 2 bytes for length + binary.BigEndian.PutUint16(dst[4:], uint16(len(plain))) dst = append(dst, plain...) fnvHash := fnv.New32a() diff --git a/transport/internet/kcp/segment.go b/transport/internet/kcp/segment.go index 22fdef72..beaefecf 100755 --- a/transport/internet/kcp/segment.go +++ b/transport/internet/kcp/segment.go @@ -4,7 +4,6 @@ import ( "encoding/binary" "v2ray.com/core/common/buf" - "v2ray.com/core/common/serial" ) // Command is a KCP command that indicate the purpose of a Segment. @@ -107,14 +106,15 @@ func (s *DataSegment) Data() *buf.Buffer { func (s *DataSegment) Bytes() buf.Supplier { return func(b []byte) (int, error) { - b = serial.Uint16ToBytes(s.Conv, b[:0]) - b = append(b, byte(CommandData), byte(s.Option)) - b = serial.Uint32ToBytes(s.Timestamp, b) - b = serial.Uint32ToBytes(s.Number, b) - b = serial.Uint32ToBytes(s.SendingNext, b) - b = serial.Uint16ToBytes(uint16(s.payload.Len()), b) - b = append(b, s.payload.Bytes()...) - return len(b), nil + binary.BigEndian.PutUint16(b, s.Conv) + b[2] = byte(CommandData) + b[3] = byte(s.Option) + binary.BigEndian.PutUint32(b[4:], s.Timestamp) + binary.BigEndian.PutUint32(b[8:], s.Number) + binary.BigEndian.PutUint32(b[12:], s.SendingNext) + binary.BigEndian.PutUint16(b[16:], uint16(s.payload.Len())) + n := copy(b[18:], s.payload.Bytes()) + return 18 + n, nil } } @@ -204,17 +204,19 @@ func (s *AckSegment) ByteSize() int32 { func (s *AckSegment) Bytes() buf.Supplier { return func(b []byte) (int, error) { - b = serial.Uint16ToBytes(s.Conv, b[:0]) - b = append(b, byte(CommandACK), byte(s.Option)) - b = serial.Uint32ToBytes(s.ReceivingWindow, b) - b = serial.Uint32ToBytes(s.ReceivingNext, b) - b = serial.Uint32ToBytes(s.Timestamp, b) - count := byte(len(s.NumberList)) - b = append(b, count) + binary.BigEndian.PutUint16(b, s.Conv) + b[2] = byte(CommandACK) + b[3] = byte(s.Option) + binary.BigEndian.PutUint32(b[4:], s.ReceivingWindow) + binary.BigEndian.PutUint32(b[8:], s.ReceivingNext) + binary.BigEndian.PutUint32(b[12:], s.Timestamp) + b[16] = byte(len(s.NumberList)) + n := 17 for _, number := range s.NumberList { - b = serial.Uint32ToBytes(number, b) + binary.BigEndian.PutUint32(b[n:], number) + n += 4 } - return int(s.ByteSize()), nil + return n, nil } } @@ -268,12 +270,13 @@ func (*CmdOnlySegment) ByteSize() int32 { func (s *CmdOnlySegment) Bytes() buf.Supplier { return func(b []byte) (int, error) { - b = serial.Uint16ToBytes(s.Conv, b[:0]) - b = append(b, byte(s.Cmd), byte(s.Option)) - b = serial.Uint32ToBytes(s.SendingNext, b) - b = serial.Uint32ToBytes(s.ReceivingNext, b) - b = serial.Uint32ToBytes(s.PeerRTO, b) - return len(b), nil + binary.BigEndian.PutUint16(b, s.Conv) + b[2] = byte(s.Cmd) + b[3] = byte(s.Option) + binary.BigEndian.PutUint32(b[4:], s.SendingNext) + binary.BigEndian.PutUint32(b[8:], s.ReceivingNext) + binary.BigEndian.PutUint32(b[12:], s.PeerRTO) + return 16, nil } }