Skip to content

Commit 5c61142

Browse files
authored
Generate new key when nonce reaches max value
#4952 (comment)
1 parent ec1cc35 commit 5c61142

3 files changed

Lines changed: 58 additions & 51 deletions

File tree

proxy/vless/encryption/client.go

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55
"crypto/cipher"
66
"crypto/mlkem"
77
"crypto/rand"
8-
"crypto/sha256"
98
"io"
109
"net"
1110
"sync"
@@ -14,7 +13,6 @@ import (
1413
"github.com/xtls/xray-core/common/crypto"
1514
"github.com/xtls/xray-core/common/errors"
1615
"github.com/xtls/xray-core/common/protocol"
17-
"golang.org/x/crypto/hkdf"
1816
)
1917

2018
var ClientCipher byte
@@ -91,7 +89,7 @@ func (i *ClientInstance) Handshake(conn net.Conn) (net.Conn, error) {
9189
clientHello[0] = ClientCipher
9290
copy(clientHello[1:], pfsEKeyBytes)
9391
copy(clientHello[1185:], encapsulatedNfsKey)
94-
encodeHeader(clientHello[2273:], int(paddingLen))
92+
EncodeHeader(clientHello[2273:], int(paddingLen))
9593
rand.Read(clientHello[2278:])
9694

9795
if _, err := c.Conn.Write(clientHello); err != nil {
@@ -112,11 +110,9 @@ func (i *ClientInstance) Handshake(conn net.Conn) (net.Conn, error) {
112110
}
113111
c.baseKey = append(pfsKey, nfsKey...)
114112

115-
authKey := make([]byte, 32)
116-
hkdf.New(sha256.New, c.baseKey, encapsulatedPfsKey, encapsulatedNfsKey).Read(authKey)
117113
nonce := [12]byte{ClientCipher}
118-
VLESS, _ := newAead(ClientCipher, authKey).Open(nil, nonce[:], c.ticket, pfsEKeyBytes)
119-
if !bytes.Equal(VLESS, []byte("VLESS")) { // TODO: more message
114+
VLESS, _ := NewAead(ClientCipher, c.baseKey, encapsulatedPfsKey, encapsulatedNfsKey).Open(nil, nonce[:], c.ticket, pfsEKeyBytes)
115+
if !bytes.Equal(VLESS, []byte("VLESS")) { // TODO: more messages
120116
return nil, errors.New("invalid server").AtError()
121117
}
122118

@@ -135,32 +131,32 @@ func (c *ClientConn) Write(b []byte) (int, error) {
135131
if len(b) == 0 {
136132
return 0, nil
137133
}
134+
var data []byte
138135
for n := 0; n < len(b); {
139136
b := b[n:]
140137
if len(b) > 8192 {
141138
b = b[:8192] // for avoiding another copy() in server's Read()
142139
}
143140
n += len(b)
144-
var data []byte
145141
if c.aead == nil {
146142
c.random = make([]byte, 32)
147143
rand.Read(c.random)
148-
key := make([]byte, 32)
149-
hkdf.New(sha256.New, c.baseKey, c.random, c.ticket).Read(key)
150-
c.aead = newAead(ClientCipher, key)
144+
c.aead = NewAead(ClientCipher, c.baseKey, c.random, c.ticket)
151145
c.nonce = make([]byte, 12)
152-
153146
data = make([]byte, 21+32+5+len(b)+16)
154147
copy(data, c.ticket)
155148
copy(data[21:], c.random)
156-
encodeHeader(data[53:], len(b)+16)
149+
EncodeHeader(data[53:], len(b)+16)
157150
c.aead.Seal(data[:58], c.nonce, b, data[53:58])
158151
} else {
159152
data = make([]byte, 5+len(b)+16)
160-
encodeHeader(data, len(b)+16)
153+
EncodeHeader(data, len(b)+16)
161154
c.aead.Seal(data[:5], c.nonce, b, data[:5])
155+
if bytes.Equal(c.nonce, MaxNonce) {
156+
c.aead = NewAead(ClientCipher, c.baseKey, data[5:], data[:5])
157+
}
162158
}
163-
increaseNonce(c.nonce)
159+
IncreaseNonce(c.nonce)
164160
if _, err := c.Conn.Write(data); err != nil {
165161
return 0, err
166162
}
@@ -179,7 +175,7 @@ func (c *ClientConn) Read(b []byte) (int, error) {
179175
if _, err := io.ReadFull(c.Conn, peerHeader); err != nil {
180176
return 0, err
181177
}
182-
peerPaddingLen, _ := decodeHeader(peerHeader)
178+
peerPaddingLen, _ := DecodeHeader(peerHeader)
183179
if peerPaddingLen == 0 {
184180
break
185181
}
@@ -200,9 +196,7 @@ func (c *ClientConn) Read(b []byte) (int, error) {
200196
if c.random == nil {
201197
return 0, errors.New("empty c.random")
202198
}
203-
peerKey := make([]byte, 32)
204-
hkdf.New(sha256.New, c.baseKey, peerRandom, c.random).Read(peerKey)
205-
c.peerAead = newAead(ClientCipher, peerKey)
199+
c.peerAead = NewAead(ClientCipher, c.baseKey, peerRandom, c.random)
206200
c.peerNonce = make([]byte, 12)
207201
}
208202
if len(c.peerCache) != 0 {
@@ -213,7 +207,7 @@ func (c *ClientConn) Read(b []byte) (int, error) {
213207
if _, err := io.ReadFull(c.Conn, peerHeader); err != nil {
214208
return 0, err
215209
}
216-
peerLength, err := decodeHeader(peerHeader) // 17~17000
210+
peerLength, err := DecodeHeader(peerHeader) // 17~17000
217211
if err != nil {
218212
if c.instance != nil {
219213
c.instance.Lock()
@@ -232,8 +226,15 @@ func (c *ClientConn) Read(b []byte) (int, error) {
232226
if len(dst) <= len(b) {
233227
dst = b[:len(dst)] // avoids another copy()
234228
}
229+
var peerAead cipher.AEAD
230+
if bytes.Equal(c.peerNonce, MaxNonce) {
231+
peerAead = NewAead(ClientCipher, c.baseKey, peerData, peerHeader)
232+
}
235233
_, err = c.peerAead.Open(dst[:0], c.peerNonce, peerData, peerHeader)
236-
increaseNonce(c.peerNonce)
234+
if peerAead != nil {
235+
c.peerAead = peerAead
236+
}
237+
IncreaseNonce(c.peerNonce)
237238
if err != nil {
238239
return 0, err
239240
}

proxy/vless/encryption/common.go

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,55 @@
11
package encryption
22

33
import (
4+
"bytes"
45
"crypto/aes"
56
"crypto/cipher"
7+
"crypto/sha256"
68
"strconv"
79

810
"github.com/xtls/xray-core/common/errors"
911
"golang.org/x/crypto/chacha20poly1305"
12+
"golang.org/x/crypto/hkdf"
1013
)
1114

12-
func encodeHeader(b []byte, l int) {
15+
var MaxNonce = bytes.Repeat([]byte{255}, 12)
16+
17+
func EncodeHeader(b []byte, l int) {
1318
b[0] = 23
1419
b[1] = 3
1520
b[2] = 3
1621
b[3] = byte(l >> 8)
1722
b[4] = byte(l)
1823
}
1924

20-
func decodeHeader(b []byte) (int, error) {
25+
func DecodeHeader(b []byte) (int, error) {
2126
if b[0] == 23 && b[1] == 3 && b[2] == 3 {
2227
l := int(b[3])<<8 | int(b[4])
23-
if l < 17 || l > 17000 { // TODO
28+
if l < 17 || l > 17000 { // TODO: TLSv1.3 max length
2429
return 0, errors.New("invalid length in record's header: " + strconv.Itoa(l))
2530
}
2631
return l, nil
2732
}
2833
return 0, errors.New("invalid record's header")
2934
}
3035

31-
func newAead(c byte, k []byte) (aead cipher.AEAD) {
36+
func NewAead(c byte, secret, salt, info []byte) (aead cipher.AEAD) {
37+
key := make([]byte, 32)
38+
hkdf.New(sha256.New, secret, salt, info).Read(key)
3239
if c&1 == 1 {
33-
block, _ := aes.NewCipher(k)
40+
block, _ := aes.NewCipher(key)
3441
aead, _ = cipher.NewGCM(block)
3542
} else {
36-
aead, _ = chacha20poly1305.New(k)
43+
aead, _ = chacha20poly1305.New(key)
3744
}
3845
return
3946
}
4047

41-
func increaseNonce(nonce []byte) {
48+
func IncreaseNonce(nonce []byte) {
4249
for i := range 12 {
4350
nonce[11-i]++
4451
if nonce[11-i] != 0 {
4552
break
4653
}
47-
if i == 11 {
48-
// TODO
49-
}
5054
}
5155
}

proxy/vless/encryption/server.go

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,13 @@ import (
55
"crypto/cipher"
66
"crypto/mlkem"
77
"crypto/rand"
8-
"crypto/sha256"
98
"io"
109
"net"
1110
"sync"
1211
"time"
1312

1413
"github.com/xtls/xray-core/common/crypto"
1514
"github.com/xtls/xray-core/common/errors"
16-
"golang.org/x/crypto/hkdf"
1715
)
1816

1917
type ServerSession struct {
@@ -103,7 +101,7 @@ func (i *ServerInstance) Handshake(conn net.Conn) (net.Conn, error) {
103101
if _, err := io.ReadFull(c.Conn, peerHeader); err != nil {
104102
return nil, err
105103
}
106-
if l, _ := decodeHeader(peerHeader); l != 0 {
104+
if l, _ := DecodeHeader(peerHeader); l != 0 {
107105
noise := make([]byte, crypto.RandBetween(100, 1000))
108106
rand.Read(noise)
109107
c.Conn.Write(noise) // make client do new handshake
@@ -131,17 +129,15 @@ func (i *ServerInstance) Handshake(conn net.Conn) (net.Conn, error) {
131129
pfsKey, encapsulatedPfsKey := pfsEKey.Encapsulate()
132130
c.baseKey = append(pfsKey, nfsKey...)
133131

134-
authKey := make([]byte, 32)
135-
hkdf.New(sha256.New, c.baseKey, encapsulatedPfsKey, encapsulatedNfsKey).Read(authKey)
136132
nonce := [12]byte{c.cipher}
137-
c.ticket = newAead(c.cipher, authKey).Seal(nil, nonce[:], []byte("VLESS"), pfsEKeyBytes)
133+
c.ticket = NewAead(c.cipher, c.baseKey, encapsulatedPfsKey, encapsulatedNfsKey).Seal(nil, nonce[:], []byte("VLESS"), pfsEKeyBytes)
138134

139135
paddingLen := crypto.RandBetween(100, 1000)
140136

141137
serverHello := make([]byte, 1088+21+5+paddingLen)
142138
copy(serverHello, encapsulatedPfsKey)
143139
copy(serverHello[1088:], c.ticket)
144-
encodeHeader(serverHello[1109:], int(paddingLen))
140+
EncodeHeader(serverHello[1109:], int(paddingLen))
145141
rand.Read(serverHello[1114:])
146142

147143
if _, err := c.Conn.Write(serverHello); err != nil {
@@ -173,7 +169,7 @@ func (c *ServerConn) Read(b []byte) (int, error) {
173169
if _, err := io.ReadFull(c.Conn, peerHeader); err != nil {
174170
return 0, err
175171
}
176-
peerPaddingLen, _ := decodeHeader(peerHeader)
172+
peerPaddingLen, _ := DecodeHeader(peerHeader)
177173
if peerPaddingLen == 0 {
178174
break
179175
}
@@ -194,9 +190,7 @@ func (c *ServerConn) Read(b []byte) (int, error) {
194190
return 0, err
195191
}
196192
}
197-
peerKey := make([]byte, 32)
198-
hkdf.New(sha256.New, c.baseKey, c.peerRandom, c.ticket).Read(peerKey)
199-
c.peerAead = newAead(c.cipher, peerKey)
193+
c.peerAead = NewAead(c.cipher, c.baseKey, c.peerRandom, c.ticket)
200194
c.peerNonce = make([]byte, 12)
201195
}
202196
if len(c.peerCache) != 0 {
@@ -207,7 +201,7 @@ func (c *ServerConn) Read(b []byte) (int, error) {
207201
if _, err := io.ReadFull(c.Conn, peerHeader); err != nil {
208202
return 0, err
209203
}
210-
peerLength, err := decodeHeader(peerHeader) // 17~17000
204+
peerLength, err := DecodeHeader(peerHeader) // 17~17000
211205
if err != nil {
212206
return 0, err
213207
}
@@ -219,8 +213,15 @@ func (c *ServerConn) Read(b []byte) (int, error) {
219213
if len(dst) <= len(b) {
220214
dst = b[:len(dst)] // avoids another copy()
221215
}
216+
var peerAead cipher.AEAD
217+
if bytes.Equal(c.peerNonce, MaxNonce) {
218+
peerAead = NewAead(ClientCipher, c.baseKey, peerData, peerHeader)
219+
}
222220
_, err = c.peerAead.Open(dst[:0], c.peerNonce, peerData, peerHeader)
223-
increaseNonce(c.peerNonce)
221+
if peerAead != nil {
222+
c.peerAead = peerAead
223+
}
224+
IncreaseNonce(c.peerNonce)
224225
if err != nil {
225226
return 0, errors.New("error")
226227
}
@@ -235,31 +236,32 @@ func (c *ServerConn) Write(b []byte) (int, error) {
235236
if len(b) == 0 {
236237
return 0, nil
237238
}
239+
var data []byte
238240
for n := 0; n < len(b); {
239241
b := b[n:]
240242
if len(b) > 8192 {
241243
b = b[:8192] // for avoiding another copy() in client's Read()
242244
}
243245
n += len(b)
244-
var data []byte
245246
if c.aead == nil {
246247
if c.peerRandom == nil {
247248
return 0, errors.New("empty c.peerRandom")
248249
}
249250
data = make([]byte, 32+5+len(b)+16)
250251
rand.Read(data[:32])
251-
key := make([]byte, 32)
252-
hkdf.New(sha256.New, c.baseKey, data[:32], c.peerRandom).Read(key)
253-
c.aead = newAead(c.cipher, key)
252+
c.aead = NewAead(c.cipher, c.baseKey, data[:32], c.peerRandom)
254253
c.nonce = make([]byte, 12)
255-
encodeHeader(data[32:], len(b)+16)
254+
EncodeHeader(data[32:], len(b)+16)
256255
c.aead.Seal(data[:37], c.nonce, b, data[32:37])
257256
} else {
258257
data = make([]byte, 5+len(b)+16)
259-
encodeHeader(data, len(b)+16)
258+
EncodeHeader(data, len(b)+16)
260259
c.aead.Seal(data[:5], c.nonce, b, data[:5])
260+
if bytes.Equal(c.nonce, MaxNonce) {
261+
c.aead = NewAead(ClientCipher, c.baseKey, data[5:], data[:5])
262+
}
261263
}
262-
increaseNonce(c.nonce)
264+
IncreaseNonce(c.nonce)
263265
if _, err := c.Conn.Write(data); err != nil {
264266
return 0, err
265267
}

0 commit comments

Comments
 (0)