glider/proxy/vmess/user.go
2022-01-08 15:05:55 +08:00

99 lines
2.2 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package vmess
import (
"bytes"
"crypto/md5"
"crypto/sha1"
"encoding/binary"
"encoding/hex"
"errors"
"strings"
"time"
"github.com/nadoo/glider/pkg/pool"
)
// User of vmess client.
type User struct {
UUID [16]byte
CmdKey [16]byte
}
// NewUser returns a new user.
func NewUser(uuid [16]byte) *User {
u := &User{UUID: uuid}
copy(u.CmdKey[:], GetKey(uuid))
return u
}
func nextID(oldID [16]byte) (newID [16]byte) {
md5hash := md5.New()
md5hash.Write(oldID[:])
md5hash.Write([]byte("16167dc8-16b6-4e6d-b8bb-65dd68113a81"))
for {
md5hash.Sum(newID[:0])
if !bytes.Equal(oldID[:], newID[:]) {
return
}
md5hash.Write([]byte("533eff8a-4113-4b10-b5ce-0f5d76b98cd2"))
}
}
// GenAlterIDUsers generates users according to primary user's id and alterID.
func (u *User) GenAlterIDUsers(alterID int) []*User {
users := make([]*User, alterID)
preID := u.UUID
for i := 0; i < alterID; i++ {
newID := nextID(preID)
// NOTE: alterID user is a user which have a different uuid but a same cmdkey with the primary user.
users[i] = &User{UUID: newID, CmdKey: u.CmdKey}
preID = newID
}
return users
}
// StrToUUID converts string to uuid.
func StrToUUID(s string) (uuid [16]byte, err error) {
if len(s) >= 1 && len(s) <= 30 {
h := sha1.New()
h.Write(uuid[:])
h.Write([]byte(s))
u := h.Sum(nil)[:16]
u[6] = (u[6] & 0x0f) | (5 << 4)
u[8] = (u[8]&(0xff>>2) | (0x02 << 6))
copy(uuid[:], u)
return
}
b := []byte(strings.Replace(s, "-", "", -1))
if len(b) != 32 {
return uuid, errors.New("invalid UUID: " + s)
}
_, err = hex.Decode(uuid[:], b)
return
}
// GetKey returns the key of AES-128-CFB encrypter.
// KeyMD5(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.
// IVMD5(X + X + X + X)X = []byte(timestamp.now) (8 bytes, Big Endian)
func TimestampHash(t time.Time) []byte {
ts := pool.GetBuffer(8)
defer pool.PutBuffer(ts)
binary.BigEndian.PutUint64(ts, uint64(t.UTC().Unix()))
md5hash := md5.New()
md5hash.Write(ts)
md5hash.Write(ts)
md5hash.Write(ts)
md5hash.Write(ts)
return md5hash.Sum(nil)
}