diff --git a/proxy/vmess/client.go b/proxy/vmess/client.go index b22a89a..c8abcda 100644 --- a/proxy/vmess/client.go +++ b/proxy/vmess/client.go @@ -129,29 +129,12 @@ func (c *Client) EncodeRequest() ([]byte, error) { fnv1a.Write(buf.Bytes()) buf.Write(fnv1a.Sum(nil)) - // AES-128-CFB crypt the request: - // Key:MD5(UUID + []byte('c48619fe-8f02-49e0-b9e9-edf763e17e21')) - // IV:MD5(X + X + X + X),X = []byte(timestamp.now) (8 bytes, Big Endian) - md5hash := md5.New() - md5hash.Write(c.user.UUID[:]) - md5hash.Write([]byte("c48619fe-8f02-49e0-b9e9-edf763e17e21")) - key := md5hash.Sum(nil) - - md5hash.Reset() - ts := make([]byte, 8) - binary.BigEndian.PutUint64(ts, uint64(time.Now().UTC().Unix())) - md5hash.Write(ts) - md5hash.Write(ts) - md5hash.Write(ts) - md5hash.Write(ts) - iv := md5hash.Sum(nil) - - block, err := aes.NewCipher(key) + block, err := aes.NewCipher(c.user.CmdKey[:]) if err != nil { return nil, err } - stream := cipher.NewCFBEncrypter(block, iv) + stream := cipher.NewCFBEncrypter(block, TimestampHash(time.Now().UTC())) stream.XORKeyStream(buf.Bytes(), buf.Bytes()) return buf.Bytes(), nil diff --git a/proxy/vmess/user.go b/proxy/vmess/user.go index 4fb4c4e..bd57b9a 100644 --- a/proxy/vmess/user.go +++ b/proxy/vmess/user.go @@ -1,14 +1,18 @@ package vmess import ( + "crypto/md5" + "encoding/binary" "encoding/hex" "errors" "strings" + "time" ) // User of vmess client type User struct { - UUID [16]byte + UUID [16]byte + CmdKey [16]byte } // NewUser . @@ -18,9 +22,8 @@ func NewUser(uuidStr string) (*User, error) { return nil, err } - u := &User{ - UUID: uuid, - } + u := &User{UUID: uuid} + copy(u.CmdKey[:], GetKey(uuid)) return u, nil } @@ -35,3 +38,26 @@ func StrToUUID(s string) (uuid [16]byte, err error) { _, err = hex.Decode(uuid[:], b) return } + +// GetKey returns the key of AES-128-CFB encrypter +// Key:MD5(UUID + []byte('c48619fe-8f02-49e0-b9e9-edf763e17e21')) +func GetKey(uuid [16]byte) []byte { + md5hash := md5.New() + md5hash.Write(uuid[:]) + md5hash.Write([]byte("c48619fe-8f02-49e0-b9e9-edf763e17e21")) + return md5hash.Sum(nil) +} + +// TimestampHash returns the iv of AES-128-CFB encrypter +// IV:MD5(X + X + X + X),X = []byte(timestamp.now) (8 bytes, Big Endian) +func TimestampHash(t time.Time) []byte { + md5hash := md5.New() + + ts := make([]byte, 8) + binary.BigEndian.PutUint64(ts, uint64(t.UTC().Unix())) + md5hash.Write(ts) + md5hash.Write(ts) + md5hash.Write(ts) + md5hash.Write(ts) + return md5hash.Sum(nil) +} diff --git a/proxy/vmess/vmess.go b/proxy/vmess/vmess.go index 0a78ddd..1dc43f6 100644 --- a/proxy/vmess/vmess.go +++ b/proxy/vmess/vmess.go @@ -90,9 +90,7 @@ func (s *VMess) Dial(network, addr string) (net.Conn, error) { return nil, err } - rc, err = client.NewConn(rc) - - return rc, nil + return client.NewConn(rc) } // DialUDP connects to the given address via the proxy.