github.com/moqsien/xraycore@v1.8.5/proxy/vmess/validator.go (about) 1 package vmess 2 3 import ( 4 "crypto/hmac" 5 "crypto/sha256" 6 "hash/crc64" 7 "strings" 8 "sync" 9 10 "github.com/moqsien/xraycore/common/dice" 11 "github.com/moqsien/xraycore/common/protocol" 12 "github.com/moqsien/xraycore/proxy/vmess/aead" 13 ) 14 15 // TimedUserValidator is a user Validator based on time. 16 type TimedUserValidator struct { 17 sync.RWMutex 18 users []*protocol.MemoryUser 19 20 behaviorSeed uint64 21 behaviorFused bool 22 23 aeadDecoderHolder *aead.AuthIDDecoderHolder 24 } 25 26 // NewTimedUserValidator creates a new TimedUserValidator. 27 func NewTimedUserValidator() *TimedUserValidator { 28 tuv := &TimedUserValidator{ 29 users: make([]*protocol.MemoryUser, 0, 16), 30 aeadDecoderHolder: aead.NewAuthIDDecoderHolder(), 31 } 32 return tuv 33 } 34 35 func (v *TimedUserValidator) Add(u *protocol.MemoryUser) error { 36 v.Lock() 37 defer v.Unlock() 38 39 v.users = append(v.users, u) 40 41 account := u.Account.(*MemoryAccount) 42 if !v.behaviorFused { 43 hashkdf := hmac.New(sha256.New, []byte("VMESSBSKDF")) 44 hashkdf.Write(account.ID.Bytes()) 45 v.behaviorSeed = crc64.Update(v.behaviorSeed, crc64.MakeTable(crc64.ECMA), hashkdf.Sum(nil)) 46 } 47 48 var cmdkeyfl [16]byte 49 copy(cmdkeyfl[:], account.ID.CmdKey()) 50 v.aeadDecoderHolder.AddUser(cmdkeyfl, u) 51 52 return nil 53 } 54 55 func (v *TimedUserValidator) GetAEAD(userHash []byte) (*protocol.MemoryUser, bool, error) { 56 v.RLock() 57 defer v.RUnlock() 58 59 var userHashFL [16]byte 60 copy(userHashFL[:], userHash) 61 62 userd, err := v.aeadDecoderHolder.Match(userHashFL) 63 if err != nil { 64 return nil, false, err 65 } 66 return userd.(*protocol.MemoryUser), true, err 67 } 68 69 func (v *TimedUserValidator) Remove(email string) bool { 70 v.Lock() 71 defer v.Unlock() 72 73 email = strings.ToLower(email) 74 idx := -1 75 for i, u := range v.users { 76 if strings.EqualFold(u.Email, email) { 77 idx = i 78 var cmdkeyfl [16]byte 79 copy(cmdkeyfl[:], u.Account.(*MemoryAccount).ID.CmdKey()) 80 v.aeadDecoderHolder.RemoveUser(cmdkeyfl) 81 break 82 } 83 } 84 if idx == -1 { 85 return false 86 } 87 ulen := len(v.users) 88 89 v.users[idx] = v.users[ulen-1] 90 v.users[ulen-1] = nil 91 v.users = v.users[:ulen-1] 92 93 return true 94 } 95 96 func (v *TimedUserValidator) GetBehaviorSeed() uint64 { 97 v.Lock() 98 defer v.Unlock() 99 100 v.behaviorFused = true 101 if v.behaviorSeed == 0 { 102 v.behaviorSeed = dice.RollUint64() 103 } 104 return v.behaviorSeed 105 } 106 107 var ErrNotFound = newError("Not Found") 108 109 var ErrTainted = newError("ErrTainted")