Skip to content

Commit b4c3bbf

Browse files
committed
chore: sync vless encryption code
1 parent 6c726d6 commit b4c3bbf

File tree

5 files changed

+146
-125
lines changed

5 files changed

+146
-125
lines changed

transport/vless/encryption/client.go

Lines changed: 69 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -30,19 +30,20 @@ var (
3030
var ClientCipher byte
3131

3232
func init() {
33-
if !HasAESGCMHardwareSupport {
33+
if HasAESGCMHardwareSupport {
3434
ClientCipher = 1
3535
}
3636
}
3737

3838
type ClientInstance struct {
3939
sync.RWMutex
40-
eKeyNfs *mlkem.EncapsulationKey768
41-
xor uint32
42-
minutes time.Duration
43-
expire time.Time
44-
baseKey []byte
45-
ticket []byte
40+
nfsEKey *mlkem.EncapsulationKey768
41+
nfsEKeyBytes []byte
42+
xor uint32
43+
minutes time.Duration
44+
expire time.Time
45+
baseKey []byte
46+
ticket []byte
4647
}
4748

4849
type ClientConn struct {
@@ -58,19 +59,22 @@ type ClientConn struct {
5859
peerCache []byte
5960
}
6061

61-
func (i *ClientInstance) Init(eKeyNfsData []byte, xor uint32, minutes time.Duration) (err error) {
62-
i.eKeyNfs, err = mlkem.NewEncapsulationKey768(eKeyNfsData)
63-
i.xor = xor
62+
func (i *ClientInstance) Init(nfsEKeyBytes []byte, xor uint32, minutes time.Duration) (err error) {
63+
i.nfsEKey, err = mlkem.NewEncapsulationKey768(nfsEKeyBytes)
64+
if xor > 0 {
65+
i.nfsEKeyBytes = nfsEKeyBytes
66+
i.xor = xor
67+
}
6468
i.minutes = minutes
6569
return
6670
}
6771

6872
func (i *ClientInstance) Handshake(conn net.Conn) (net.Conn, error) {
69-
if i.eKeyNfs == nil {
73+
if i.nfsEKey == nil {
7074
return nil, errors.New("uninitialized")
7175
}
72-
if i.xor == 1 {
73-
conn = NewXorConn(conn, i.eKeyNfs.Bytes())
76+
if i.xor > 0 {
77+
conn = NewXorConn(conn, i.nfsEKeyBytes)
7478
}
7579
c := &ClientConn{Conn: conn}
7680

@@ -86,18 +90,19 @@ func (i *ClientInstance) Handshake(conn net.Conn) (net.Conn, error) {
8690
i.RUnlock()
8791
}
8892

89-
nfsKey, encapsulatedNfsKey := i.eKeyNfs.Encapsulate()
90-
seed := make([]byte, 64)
91-
rand.Read(seed)
92-
dKeyPfs, _ := mlkem.NewDecapsulationKey768(seed)
93-
eKeyPfs := dKeyPfs.EncapsulationKey().Bytes()
94-
padding := randBetween(100, 1000)
93+
pfsDKeySeed := make([]byte, 64)
94+
rand.Read(pfsDKeySeed)
95+
pfsDKey, _ := mlkem.NewDecapsulationKey768(pfsDKeySeed)
96+
pfsEKeyBytes := pfsDKey.EncapsulationKey().Bytes()
97+
nfsKey, encapsulatedNfsKey := i.nfsEKey.Encapsulate()
98+
paddingLen := randBetween(100, 1000)
9599

96-
clientHello := make([]byte, 1088+1184+1+5+padding)
97-
copy(clientHello, encapsulatedNfsKey)
98-
copy(clientHello[1088:], eKeyPfs)
99-
clientHello[2272] = ClientCipher
100-
encodeHeader(clientHello[2273:], int(padding))
100+
clientHello := make([]byte, 1+1184+1088+5+paddingLen)
101+
clientHello[0] = ClientCipher
102+
copy(clientHello[1:], pfsEKeyBytes)
103+
copy(clientHello[1185:], encapsulatedNfsKey)
104+
encodeHeader(clientHello[2273:], int(paddingLen))
105+
rand.Read(clientHello[2278:])
101106

102107
if _, err := c.Conn.Write(clientHello); err != nil {
103108
return nil, err
@@ -111,16 +116,16 @@ func (i *ClientInstance) Handshake(conn net.Conn) (net.Conn, error) {
111116
encapsulatedPfsKey := peerServerHello[:1088]
112117
c.ticket = peerServerHello[1088:]
113118

114-
pfsKey, err := dKeyPfs.Decapsulate(encapsulatedPfsKey)
119+
pfsKey, err := pfsDKey.Decapsulate(encapsulatedPfsKey)
115120
if err != nil {
116121
return nil, err
117122
}
118-
c.baseKey = append(nfsKey, pfsKey...)
123+
c.baseKey = append(pfsKey, nfsKey...)
119124

120125
authKey := make([]byte, 32)
121-
hkdf.New(sha256.New, c.baseKey, encapsulatedNfsKey, eKeyPfs).Read(authKey)
122-
nonce := make([]byte, 12)
123-
VLESS, _ := newAead(ClientCipher, authKey).Open(nil, nonce, c.ticket, encapsulatedPfsKey)
126+
hkdf.New(sha256.New, c.baseKey, encapsulatedPfsKey, encapsulatedNfsKey).Read(authKey)
127+
nonce := [12]byte{ClientCipher}
128+
VLESS, _ := newAead(ClientCipher, authKey).Open(nil, nonce[:], c.ticket, pfsEKeyBytes)
124129
if !bytes.Equal(VLESS, []byte("VLESS")) { // TODO: more message
125130
return nil, errors.New("invalid server")
126131
}
@@ -140,33 +145,40 @@ func (c *ClientConn) Write(b []byte) (int, error) {
140145
if len(b) == 0 {
141146
return 0, nil
142147
}
143-
var data []byte
144-
if c.aead == nil {
145-
c.random = make([]byte, 32)
146-
rand.Read(c.random)
147-
key := make([]byte, 32)
148-
hkdf.New(sha256.New, c.baseKey, c.random, c.ticket).Read(key)
149-
c.aead = newAead(ClientCipher, key)
150-
c.nonce = make([]byte, 12)
151-
152-
data = make([]byte, 21+32+5+len(b)+16)
153-
copy(data, c.ticket)
154-
copy(data[21:], c.random)
155-
encodeHeader(data[53:], len(b)+16)
156-
c.aead.Seal(data[:58], c.nonce, b, data[53:58])
157-
} else {
158-
data = make([]byte, 5+len(b)+16)
159-
encodeHeader(data, len(b)+16)
160-
c.aead.Seal(data[:5], c.nonce, b, data[:5])
161-
}
162-
increaseNonce(c.nonce)
163-
if _, err := c.Conn.Write(data); err != nil {
164-
return 0, err
148+
for n := 0; n < len(b); {
149+
b := b[n:]
150+
if len(b) > 8192 {
151+
b = b[:8192] // for avoiding another copy() in server's Read()
152+
}
153+
n += len(b)
154+
var data []byte
155+
if c.aead == nil {
156+
c.random = make([]byte, 32)
157+
rand.Read(c.random)
158+
key := make([]byte, 32)
159+
hkdf.New(sha256.New, c.baseKey, c.random, c.ticket).Read(key)
160+
c.aead = newAead(ClientCipher, key)
161+
c.nonce = make([]byte, 12)
162+
163+
data = make([]byte, 21+32+5+len(b)+16)
164+
copy(data, c.ticket)
165+
copy(data[21:], c.random)
166+
encodeHeader(data[53:], len(b)+16)
167+
c.aead.Seal(data[:58], c.nonce, b, data[53:58])
168+
} else {
169+
data = make([]byte, 5+len(b)+16)
170+
encodeHeader(data, len(b)+16)
171+
c.aead.Seal(data[:5], c.nonce, b, data[:5])
172+
}
173+
increaseNonce(c.nonce)
174+
if _, err := c.Conn.Write(data); err != nil {
175+
return 0, err
176+
}
165177
}
166178
return len(b), nil
167179
}
168180

169-
func (c *ClientConn) Read(b []byte) (int, error) { // after first Write()
181+
func (c *ClientConn) Read(b []byte) (int, error) {
170182
if len(b) == 0 {
171183
return 0, nil
172184
}
@@ -177,11 +189,11 @@ func (c *ClientConn) Read(b []byte) (int, error) { // after first Write()
177189
if _, err := io.ReadFull(c.Conn, peerHeader); err != nil {
178190
return 0, err
179191
}
180-
peerPadding, _ := decodeHeader(peerHeader)
181-
if peerPadding == 0 {
192+
peerPaddingLen, _ := decodeHeader(peerHeader)
193+
if peerPaddingLen == 0 {
182194
break
183195
}
184-
if _, err := io.ReadFull(c.Conn, make([]byte, peerPadding)); err != nil {
196+
if _, err := io.ReadFull(c.Conn, make([]byte, peerPaddingLen)); err != nil {
185197
return 0, err
186198
}
187199
}
@@ -196,7 +208,7 @@ func (c *ClientConn) Read(b []byte) (int, error) { // after first Write()
196208
return 0, err
197209
}
198210
if c.random == nil {
199-
return 0, errors.New("can not Read() first")
211+
return 0, errors.New("empty c.random")
200212
}
201213
peerKey := make([]byte, 32)
202214
hkdf.New(sha256.New, c.baseKey, peerRandom, c.random).Read(peerKey)
@@ -228,7 +240,7 @@ func (c *ClientConn) Read(b []byte) (int, error) { // after first Write()
228240
}
229241
dst := peerData[:peerLength-16]
230242
if len(dst) <= len(b) {
231-
dst = b[:len(dst)] // max=8192 is recommended for peer
243+
dst = b[:len(dst)] // avoids another copy()
232244
}
233245
_, err = c.peerAead.Open(dst[:0], c.peerNonce, peerData, peerHeader)
234246
increaseNonce(c.peerNonce)

transport/vless/encryption/common.go

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -30,18 +30,14 @@ func decodeHeader(b []byte) (int, error) {
3030
return 0, errors.New("invalid record's header")
3131
}
3232

33-
func newAead(c byte, k []byte) cipher.AEAD {
34-
switch c {
35-
case 0:
36-
if block, err := aes.NewCipher(k); err == nil {
37-
aead, _ := cipher.NewGCM(block)
38-
return aead
39-
}
40-
case 1:
41-
aead, _ := chacha20poly1305.New(k)
42-
return aead
33+
func newAead(c byte, k []byte) (aead cipher.AEAD) {
34+
if c&1 == 1 {
35+
block, _ := aes.NewCipher(k)
36+
aead, _ = cipher.NewGCM(block)
37+
} else {
38+
aead, _ = chacha20poly1305.New(k)
4339
}
44-
return nil
40+
return
4541
}
4642

4743
func increaseNonce(nonce []byte) {

transport/vless/encryption/doc.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@
22
// https://github.com/XTLS/Xray-core/commit/f61c14e9c63dc41a8a09135db3aea337974f3f37
33
// https://github.com/XTLS/Xray-core/commit/3e19bf9233bdd9bafc073a71c65b737cc1ffba5e
44
// https://github.com/XTLS/Xray-core/commit/7ffb555fc8ec51bd1e3e60f26f1d6957984dba80
5+
// https://github.com/XTLS/Xray-core/commit/ec1cc35188c1a5f38a2ff75e88b5d043ffdc59da
56
package encryption

0 commit comments

Comments
 (0)