Parcourir la source

authenticator

v2ray il y a 9 ans
Parent
commit
06b92bddcf
4 fichiers modifiés avec 59 ajouts et 0 suppressions
  1. 6 0
      common/alloc/buffer.go
  2. 6 0
      common/crypto/authenticator.go
  3. 39 0
      common/net/transport.go
  4. 8 0
      common/serial/bytes.go

+ 6 - 0
common/alloc/buffer.go

@@ -5,6 +5,12 @@ import (
 	"sync"
 )
 
+func Release(buffer *Buffer) {
+	if buffer != nil {
+		buffer.Release()
+	}
+}
+
 // Buffer is a recyclable allocation of a byte array. Buffer.Release() recycles
 // the buffer into an internal buffer pool, in order to recreate a buffer more
 // quickly.

+ 6 - 0
common/crypto/authenticator.go

@@ -0,0 +1,6 @@
+package crypto
+
+type Authenticator interface {
+	AuthBytes() int
+	Authenticate(auth []byte, data []byte) []byte
+}

+ 39 - 0
common/net/transport.go

@@ -4,6 +4,9 @@ import (
 	"io"
 
 	"github.com/v2ray/v2ray-core/common/alloc"
+	"github.com/v2ray/v2ray-core/common/crypto"
+	"github.com/v2ray/v2ray-core/common/serial"
+	"github.com/v2ray/v2ray-core/transport"
 )
 
 // ReadFrom reads from a reader and put all content to a buffer.
@@ -17,6 +20,42 @@ func ReadFrom(reader io.Reader, buffer *alloc.Buffer) (*alloc.Buffer, error) {
 	return buffer, err
 }
 
+func ReadChunk(reader io.Reader, buffer *alloc.Buffer) (*alloc.Buffer, error) {
+	if buffer == nil {
+		buffer = alloc.NewBuffer()
+	}
+	if _, err := io.ReadFull(reader, buffer.Value[:2]); err != nil {
+		alloc.Release(buffer)
+		return nil, err
+	}
+	length := serial.BytesLiteral(buffer.Value[:2]).Uint16Value()
+	if _, err := io.ReadFull(reader, buffer.Value[:length]); err != nil {
+		alloc.Release(buffer)
+		return nil, err
+	}
+	buffer.Slice(0, int(length))
+	return buffer, nil
+}
+
+func ReadAuthenticatedChunk(reader io.Reader, auth crypto.Authenticator, buffer *alloc.Buffer) (*alloc.Buffer, error) {
+	buffer, err := ReadChunk(reader, buffer)
+	if err != nil {
+		alloc.Release(buffer)
+		return nil, err
+	}
+	authSize := auth.AuthBytes()
+
+	authBytes := auth.Authenticate(nil, buffer.Value[authSize:])
+
+	if !serial.BytesLiteral(authBytes).Equals(serial.BytesLiteral(buffer.Value[:authSize])) {
+		alloc.Release(buffer)
+		return nil, transport.CorruptedPacket
+	}
+	buffer.SliceFrom(authSize)
+
+	return buffer, nil
+}
+
 // ReaderToChan dumps all content from a given reader to a chan by constantly reading it until EOF.
 func ReaderToChan(stream chan<- *alloc.Buffer, reader io.Reader) error {
 	allocate := alloc.NewBuffer

+ 8 - 0
common/serial/bytes.go

@@ -1,5 +1,9 @@
 package serial
 
+import (
+	"bytes"
+)
+
 type Bytes interface {
 	Bytes() []byte
 }
@@ -10,6 +14,10 @@ func (this BytesLiteral) Value() []byte {
 	return []byte(this)
 }
 
+func (this BytesLiteral) Equals(another BytesLiteral) bool {
+	return bytes.Equal(this.Value(), another.Value())
+}
+
 func (this BytesLiteral) Uint8Value() uint8 {
 	return this.Value()[0]
 }