diff --git a/transport/vless/encryption/client.go b/transport/vless/encryption/client.go index dfa4fa63..0a4f899f 100644 --- a/transport/vless/encryption/client.go +++ b/transport/vless/encryption/client.go @@ -57,7 +57,7 @@ type ClientConn struct { random []byte aead cipher.AEAD nonce []byte - peerAead cipher.AEAD + peerAEAD cipher.AEAD peerNonce []byte input bytes.Reader // peerCache } @@ -108,21 +108,23 @@ func (i *ClientInstance) Handshake(conn net.Conn) (*ClientConn, error) { pfsDKey, _ := mlkem.NewDecapsulationKey768(pfsDKeySeed) pfsEKeyBytes := pfsDKey.EncapsulationKey().Bytes() nfsKey, encapsulatedNfsKey := i.nfsEKey.Encapsulate() - paddingLen := randBetween(100, 1000) + nfsAEAD := NewAEAD(ClientCipher, nfsKey, pfsEKeyBytes, encapsulatedNfsKey) - clientHello := make([]byte, 5+11+1+1184+1088+5+paddingLen) + clientHello := make([]byte, 5+11+1+1184+1088+randBetween(100, 1000)) EncodeHeader(clientHello, 1, 11+1+1184+1088) copy(clientHello[5:], i.hash11[:]) clientHello[5+11] = ClientCipher copy(clientHello[5+11+1:], pfsEKeyBytes) copy(clientHello[5+11+1+1184:], encapsulatedNfsKey) - EncodeHeader(clientHello[5+11+1+1184+1088:], 23, int(paddingLen)) - rand.Read(clientHello[5+11+1+1184+1088+5:]) + padding := clientHello[5+11+1+1184+1088:] + rand.Read(padding) // important + EncodeHeader(padding, 23, len(padding)-5) + nfsAEAD.Seal(padding[:5], clientHello[5:5+11+1], padding[5:len(padding)-16], padding[:5]) if _, err := c.Conn.Write(clientHello); err != nil { return nil, err } - // client can send more paddings / NFS AEAD messages if needed + // client can send more NFS AEAD paddings / messages if needed _, t, l, err := ReadAndDiscardPaddings(c.Conn) // allow paddings before server hello if err != nil { @@ -206,7 +208,7 @@ func (c *ClientConn) Read(b []byte) (int, error) { if len(b) == 0 { return 0, nil } - if c.peerAead == nil { + if c.peerAEAD == nil { _, t, l, err := ReadAndDiscardPaddings(c.Conn) // allow paddings before random hello if err != nil { if c.instance != nil && strings.HasPrefix(err.Error(), "invalid header: ") { // 0-RTT's 0-RTT @@ -232,7 +234,7 @@ func (c *ClientConn) Read(b []byte) (int, error) { if c.random == nil { return 0, errors.New("empty c.random") } - c.peerAead = NewAEAD(ClientCipher, c.baseKey, peerRandomHello, c.random) + c.peerAEAD = NewAEAD(ClientCipher, c.baseKey, peerRandomHello, c.random) c.peerNonce = make([]byte, 12) } if c.input.Len() > 0 { @@ -253,13 +255,13 @@ func (c *ClientConn) Read(b []byte) (int, error) { if len(dst) <= len(b) { dst = b[:len(dst)] // avoids another copy() } - var peerAead cipher.AEAD + var peerAEAD cipher.AEAD if bytes.Equal(c.peerNonce, MaxNonce) { - peerAead = NewAEAD(ClientCipher, c.baseKey, peerData, h) + peerAEAD = NewAEAD(ClientCipher, c.baseKey, peerData, h) } - _, err = c.peerAead.Open(dst[:0], c.peerNonce, peerData, h) - if peerAead != nil { - c.peerAead = peerAead + _, err = c.peerAEAD.Open(dst[:0], c.peerNonce, peerData, h) + if peerAEAD != nil { + c.peerAEAD = peerAEAD } IncreaseNonce(c.peerNonce) if err != nil { diff --git a/transport/vless/encryption/doc.go b/transport/vless/encryption/doc.go index 10cd320b..1e6a09a0 100644 --- a/transport/vless/encryption/doc.go +++ b/transport/vless/encryption/doc.go @@ -15,4 +15,5 @@ // https://github.com/XTLS/Xray-core/commit/49580705f6029648399304b816a2737f991582a8 // https://github.com/XTLS/Xray-core/commit/84835bec7d0d8555d0dd30953ed26a272de814c4 // https://github.com/XTLS/Xray-core/commit/373558ed7abdbac3de41745cf30ec04c9adde604 +// https://github.com/XTLS/Xray-core/commit/38cc306c955c362f044e074049a5e67b6b9fb389 package encryption diff --git a/transport/vless/encryption/server.go b/transport/vless/encryption/server.go index baa8432c..5437b95f 100644 --- a/transport/vless/encryption/server.go +++ b/transport/vless/encryption/server.go @@ -40,7 +40,7 @@ type ServerConn struct { baseKey []byte ticket []byte peerRandom []byte - peerAead cipher.AEAD + peerAEAD cipher.AEAD peerNonce []byte input bytes.Reader // peerCache aead cipher.AEAD @@ -172,22 +172,23 @@ func (i *ServerInstance) Handshake(conn net.Conn) (*ServerConn, error) { } pfsKey, encapsulatedPfsKey := pfsEKey.Encapsulate() c.baseKey = append(pfsKey, nfsKey...) + pfsAEAD := NewAEAD(c.cipher, c.baseKey, encapsulatedPfsKey, encapsulatedNfsKey) + c.ticket = append(i.hash11[:], pfsAEAD.Seal(nil, peerClientHello[:11+1], []byte("VLESS"), pfsEKeyBytes)...) + IncreaseNonce(peerClientHello[:11+1]) - c.ticket = append(i.hash11[:], NewAEAD(c.cipher, c.baseKey, encapsulatedPfsKey, encapsulatedNfsKey).Seal(nil, peerClientHello[:12], []byte("VLESS"), pfsEKeyBytes)...) - - paddingLen := randBetween(100, 1000) - - serverHello := make([]byte, 5+1088+21+5+paddingLen) + serverHello := make([]byte, 5+1088+21+randBetween(100, 1000)) EncodeHeader(serverHello, 1, 1088+21) copy(serverHello[5:], encapsulatedPfsKey) copy(serverHello[5+1088:], c.ticket[11:]) - EncodeHeader(serverHello[5+1088+21:], 23, int(paddingLen)) - rand.Read(serverHello[5+1088+21+5:]) + padding := serverHello[5+1088+21:] + rand.Read(padding) // important + EncodeHeader(padding, 23, len(padding)-5) + pfsAEAD.Seal(padding[:5], peerClientHello[:11+1], padding[5:len(padding)-16], padding[:5]) if _, err := c.Conn.Write(serverHello); err != nil { return nil, err } - // server can send more paddings / PFS AEAD messages if needed + // server can send more PFS AEAD paddings / messages if needed if i.minutes > 0 { i.Lock() @@ -206,7 +207,7 @@ func (c *ServerConn) Read(b []byte) (int, error) { if len(b) == 0 { return 0, nil } - if c.peerAead == nil { + if c.peerAEAD == nil { if c.peerRandom == nil { // 1-RTT's 0-RTT _, t, l, err := ReadAndDiscardPaddings(c.Conn) // allow paddings before ticket hello if err != nil { @@ -227,7 +228,7 @@ func (c *ServerConn) Read(b []byte) (int, error) { } c.peerRandom = peerTicketHello[32:] } - c.peerAead = NewAEAD(c.cipher, c.baseKey, c.peerRandom, c.ticket) + c.peerAEAD = NewAEAD(c.cipher, c.baseKey, c.peerRandom, c.ticket) c.peerNonce = make([]byte, 12) } if c.input.Len() > 0 { @@ -248,13 +249,13 @@ func (c *ServerConn) Read(b []byte) (int, error) { if len(dst) <= len(b) { dst = b[:len(dst)] // avoids another copy() } - var peerAead cipher.AEAD + var peerAEAD cipher.AEAD if bytes.Equal(c.peerNonce, MaxNonce) { - peerAead = NewAEAD(c.cipher, c.baseKey, peerData, h) + peerAEAD = NewAEAD(c.cipher, c.baseKey, peerData, h) } - _, err = c.peerAead.Open(dst[:0], c.peerNonce, peerData, h) - if peerAead != nil { - c.peerAead = peerAead + _, err = c.peerAEAD.Open(dst[:0], c.peerNonce, peerData, h) + if peerAEAD != nil { + c.peerAEAD = peerAEAD } IncreaseNonce(c.peerNonce) if err != nil { diff --git a/transport/vless/encryption/xor.go b/transport/vless/encryption/xor.go index 88bd7698..a97bb871 100644 --- a/transport/vless/encryption/xor.go +++ b/transport/vless/encryption/xor.go @@ -57,7 +57,7 @@ func NewXorConn(conn net.Conn, mode uint32, pKey *ecdh.PublicKey, sKey *ecdh.Pri if pKey != nil { c.head = make([]byte, 16+32) rand.Read(c.head) - eSKey, _ := ecdh.X25519().GenerateKey(rand.Reader) + eSKey, _ := ecdh.X25519().NewPrivateKey(c.head[16:]) NewCTR(pKey.Bytes(), c.head[:16], false).XORKeyStream(c.head[16:], eSKey.PublicKey().Bytes()) // make X25519 public key distinguishable from random bytes c.key, _ = eSKey.ECDH(pKey) c.ctr = NewCTR(c.key, c.head[:16], false)