Skip to content

Commit

Permalink
Refactor AES encryption/decryption
Browse files Browse the repository at this point in the history
  • Loading branch information
DarienRaymond committed Nov 3, 2015
1 parent 3f884ed commit a46db06
Show file tree
Hide file tree
Showing 7 changed files with 90 additions and 109 deletions.
62 changes: 62 additions & 0 deletions common/crypto/aes.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package crypto

import (
"crypto/aes"
"crypto/cipher"
"io"
)

func NewAesDecryptionStream(key []byte, iv []byte) (cipher.Stream, error) {
aesBlock, err := aes.NewCipher(key)
if err != nil {
return nil, err
}

return cipher.NewCFBDecrypter(aesBlock, iv), nil
}

func NewAesEncryptionStream(key []byte, iv []byte) (cipher.Stream, error) {
aesBlock, err := aes.NewCipher(key)
if err != nil {
return nil, err
}

return cipher.NewCFBEncrypter(aesBlock, iv), nil
}

type cryptionReader struct {
stream cipher.Stream
reader io.Reader
}

func NewCryptionReader(stream cipher.Stream, reader io.Reader) io.Reader {
return &cryptionReader{
stream: stream,
reader: reader,
}
}

func (this *cryptionReader) Read(data []byte) (int, error) {
nBytes, err := this.reader.Read(data)
if nBytes > 0 {
this.stream.XORKeyStream(data[:nBytes], data[:nBytes])
}
return nBytes, err
}

type cryptionWriter struct {
stream cipher.Stream
writer io.Writer
}

func NewCryptionWriter(stream cipher.Stream, writer io.Writer) io.Writer {
return &cryptionWriter{
stream: stream,
writer: writer,
}
}

func (this *cryptionWriter) Write(data []byte) (int, error) {
this.stream.XORKeyStream(data, data)
return this.writer.Write(data)
}
27 changes: 0 additions & 27 deletions common/io/aes.go

This file was deleted.

54 changes: 0 additions & 54 deletions common/io/encryption.go

This file was deleted.

15 changes: 4 additions & 11 deletions proxy/vmess/protocol/vmess.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,13 @@
package protocol

import (
"crypto/aes"
"crypto/cipher"
"encoding/binary"
"hash/fnv"
"io"
"time"

"github.com/v2ray/v2ray-core/common/alloc"
v2io "github.com/v2ray/v2ray-core/common/io"
v2crypto "github.com/v2ray/v2ray-core/common/crypto"
"github.com/v2ray/v2ray-core/common/log"
v2net "github.com/v2ray/v2ray-core/common/net"
proxyerrors "github.com/v2ray/v2ray-core/proxy/common/errors"
Expand Down Expand Up @@ -80,16 +78,12 @@ func (r *VMessRequestReader) Read(reader io.Reader) (*VMessRequest, error) {
return nil, proxyerrors.InvalidAuthentication
}

aesCipher, err := aes.NewCipher(userObj.ID().CmdKey())
aesStream, err := v2crypto.NewAesDecryptionStream(userObj.ID().CmdKey(), user.Int64Hash(timeSec))
if err != nil {
return nil, err
}
aesStream := cipher.NewCFBDecrypter(aesCipher, user.Int64Hash(timeSec))
decryptor := v2io.NewCryptionReader(aesStream, reader)

if err != nil {
return nil, err
}
decryptor := v2crypto.NewCryptionReader(aesStream, reader)

nBytes, err = v2net.ReadAllBytes(decryptor, buffer.Value[:41])
if err != nil {
Expand Down Expand Up @@ -201,11 +195,10 @@ func (request *VMessRequest) ToBytes(idHash user.CounterHash, randomRangeInt64 u
buffer.AppendBytes(byte(fnvHash>>24), byte(fnvHash>>16), byte(fnvHash>>8), byte(fnvHash))
encryptionEnd += 4

aesCipher, err := aes.NewCipher(request.User.ID().CmdKey())
aesStream, err := v2crypto.NewAesEncryptionStream(request.User.ID().CmdKey(), user.Int64Hash(counter))
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
Expand Down
14 changes: 8 additions & 6 deletions proxy/vmess/vmessin.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (

"github.com/v2ray/v2ray-core/app"
"github.com/v2ray/v2ray-core/common/alloc"
v2io "github.com/v2ray/v2ray-core/common/io"
v2crypto "github.com/v2ray/v2ray-core/common/crypto"
"github.com/v2ray/v2ray-core/common/log"
v2net "github.com/v2ray/v2ray-core/common/net"
"github.com/v2ray/v2ray-core/common/retry"
Expand Down Expand Up @@ -98,12 +98,14 @@ func (handler *VMessInboundHandler) HandleConnection(connection *net.TCPConn) er
responseKey := md5.Sum(request.RequestKey)
responseIV := md5.Sum(request.RequestIV)

responseWriter, err := v2io.NewAesEncryptWriter(responseKey[:], responseIV[:], connection)
aesStream, err := v2crypto.NewAesEncryptionStream(responseKey[:], responseIV[:])
if err != nil {
log.Error("VMessIn: Failed to create encrypt writer: %v", err)
log.Error("VMessIn: Failed to create AES decryption stream: %v", err)
return err
}

responseWriter := v2crypto.NewCryptionWriter(aesStream, connection)

// Optimize for small response packet
buffer := alloc.NewLargeBuffer().Clear()
buffer.Append(request.ResponseHeader)
Expand All @@ -127,12 +129,12 @@ func handleInput(request *protocol.VMessRequest, reader io.Reader, input chan<-
defer close(input)
defer finish.Unlock()

requestReader, err := v2io.NewAesDecryptReader(request.RequestKey, request.RequestIV, reader)
aesStream, err := v2crypto.NewAesDecryptionStream(request.RequestKey, request.RequestIV)
if err != nil {
log.Error("VMessIn: Failed to create decrypt reader: %v", err)
log.Error("VMessIn: Failed to create AES decryption stream: %v", err)
return
}

requestReader := v2crypto.NewCryptionReader(aesStream, reader)
v2net.ReaderToChan(input, requestReader)
}

Expand Down
13 changes: 8 additions & 5 deletions proxy/vmess/vmessin_udp.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"net"

"github.com/v2ray/v2ray-core/common/alloc"
v2io "github.com/v2ray/v2ray-core/common/io"
v2crypto "github.com/v2ray/v2ray-core/common/crypto"
"github.com/v2ray/v2ray-core/common/log"
v2net "github.com/v2ray/v2ray-core/common/net"
"github.com/v2ray/v2ray-core/proxy/vmess/protocol"
Expand Down Expand Up @@ -54,12 +54,13 @@ func (handler *VMessInboundHandler) AcceptPackets(conn *net.UDPConn) {
}
log.Access(addr.String(), request.Address.String(), log.AccessAccepted, "")

cryptReader, err := v2io.NewAesDecryptReader(request.RequestKey, request.RequestIV, reader)
aesStream, err := v2crypto.NewAesDecryptionStream(request.RequestKey, request.RequestIV)
if err != nil {
log.Error("VMessIn: Failed to create decrypt reader: %v", err)
log.Error("VMessIn: Failed to AES decryption stream: %v", err)
buffer.Release()
continue
}
cryptReader := v2crypto.NewCryptionReader(aesStream, reader)

data := alloc.NewBuffer()
nBytes, err = cryptReader.Read(data.Value)
Expand All @@ -86,11 +87,13 @@ func (handler *VMessInboundHandler) handlePacket(conn *net.UDPConn, request *pro
buffer := alloc.NewBuffer().Clear()
defer buffer.Release()

responseWriter, err := v2io.NewAesEncryptWriter(responseKey[:], responseIV[:], buffer)
aesStream, err := v2crypto.NewAesEncryptionStream(responseKey[:], responseIV[:])
if err != nil {
log.Error("VMessIn: Failed to create encrypt writer: %v", err)
log.Error("VMessIn: Failed to create AES encryption stream: %v", err)
return
}
responseWriter := v2crypto.NewCryptionWriter(aesStream, buffer)

responseWriter.Write(request.ResponseHeader)

hasData := false
Expand Down
14 changes: 8 additions & 6 deletions proxy/vmess/vmessout.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
"sync"

"github.com/v2ray/v2ray-core/common/alloc"
v2io "github.com/v2ray/v2ray-core/common/io"
v2crypto "github.com/v2ray/v2ray-core/common/crypto"
"github.com/v2ray/v2ray-core/common/log"
v2net "github.com/v2ray/v2ray-core/common/net"
"github.com/v2ray/v2ray-core/proxy/common/connhandler"
Expand Down Expand Up @@ -114,11 +114,12 @@ func startCommunicate(request *protocol.VMessRequest, dest v2net.Destination, ra

func handleRequest(conn net.Conn, request *protocol.VMessRequest, firstPacket v2net.Packet, input <-chan *alloc.Buffer, finish *sync.Mutex) {
defer finish.Unlock()
encryptRequestWriter, err := v2io.NewAesEncryptWriter(request.RequestKey[:], request.RequestIV[:], conn)
aesStream, err := v2crypto.NewAesEncryptionStream(request.RequestKey[:], request.RequestIV[:])
if err != nil {
log.Error("VMessOut: Failed to create encrypt writer: %v", err)
log.Error("VMessOut: Failed to create AES encryption stream: %v", err)
return
}
encryptRequestWriter := v2crypto.NewCryptionWriter(aesStream, conn)

buffer := alloc.NewBuffer().Clear()
buffer, err = request.ToBytes(user.NewTimeHash(user.HMACHash{}), user.GenerateRandomInt64InRange, buffer)
Expand All @@ -136,7 +137,7 @@ func handleRequest(conn net.Conn, request *protocol.VMessRequest, firstPacket v2
}

if firstChunk != nil {
encryptRequestWriter.Crypt(firstChunk.Value)
aesStream.XORKeyStream(firstChunk.Value, firstChunk.Value)
buffer.Append(firstChunk.Value)
firstChunk.Release()

Expand All @@ -160,11 +161,12 @@ func handleResponse(conn net.Conn, request *protocol.VMessRequest, output chan<-
responseKey := md5.Sum(request.RequestKey[:])
responseIV := md5.Sum(request.RequestIV[:])

decryptResponseReader, err := v2io.NewAesDecryptReader(responseKey[:], responseIV[:], conn)
aesStream, err := v2crypto.NewAesDecryptionStream(responseKey[:], responseIV[:])
if err != nil {
log.Error("VMessOut: Failed to create decrypt reader: %v", err)
log.Error("VMessOut: Failed to create AES encryption stream: %v", err)
return
}
decryptResponseReader := v2crypto.NewCryptionReader(aesStream, conn)

buffer, err := v2net.ReadFrom(decryptResponseReader, nil)
if err != nil {
Expand Down

0 comments on commit a46db06

Please sign in to comment.