mirror of
https://github.com/MetaCubeX/mihomo.git
synced 2025-12-20 00:50:06 +08:00
chore: sync vless encryption code
This commit is contained in:
parent
7960bcae15
commit
b31664beeb
@ -57,7 +57,7 @@ type ClientConn struct {
|
|||||||
random []byte
|
random []byte
|
||||||
aead cipher.AEAD
|
aead cipher.AEAD
|
||||||
nonce []byte
|
nonce []byte
|
||||||
peerAead cipher.AEAD
|
peerAEAD cipher.AEAD
|
||||||
peerNonce []byte
|
peerNonce []byte
|
||||||
input bytes.Reader // peerCache
|
input bytes.Reader // peerCache
|
||||||
}
|
}
|
||||||
@ -108,21 +108,23 @@ func (i *ClientInstance) Handshake(conn net.Conn) (*ClientConn, error) {
|
|||||||
pfsDKey, _ := mlkem.NewDecapsulationKey768(pfsDKeySeed)
|
pfsDKey, _ := mlkem.NewDecapsulationKey768(pfsDKeySeed)
|
||||||
pfsEKeyBytes := pfsDKey.EncapsulationKey().Bytes()
|
pfsEKeyBytes := pfsDKey.EncapsulationKey().Bytes()
|
||||||
nfsKey, encapsulatedNfsKey := i.nfsEKey.Encapsulate()
|
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)
|
EncodeHeader(clientHello, 1, 11+1+1184+1088)
|
||||||
copy(clientHello[5:], i.hash11[:])
|
copy(clientHello[5:], i.hash11[:])
|
||||||
clientHello[5+11] = ClientCipher
|
clientHello[5+11] = ClientCipher
|
||||||
copy(clientHello[5+11+1:], pfsEKeyBytes)
|
copy(clientHello[5+11+1:], pfsEKeyBytes)
|
||||||
copy(clientHello[5+11+1+1184:], encapsulatedNfsKey)
|
copy(clientHello[5+11+1+1184:], encapsulatedNfsKey)
|
||||||
EncodeHeader(clientHello[5+11+1+1184+1088:], 23, int(paddingLen))
|
padding := clientHello[5+11+1+1184+1088:]
|
||||||
rand.Read(clientHello[5+11+1+1184+1088+5:])
|
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 {
|
if _, err := c.Conn.Write(clientHello); err != nil {
|
||||||
return nil, err
|
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
|
_, t, l, err := ReadAndDiscardPaddings(c.Conn) // allow paddings before server hello
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -206,7 +208,7 @@ func (c *ClientConn) Read(b []byte) (int, error) {
|
|||||||
if len(b) == 0 {
|
if len(b) == 0 {
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
if c.peerAead == nil {
|
if c.peerAEAD == nil {
|
||||||
_, t, l, err := ReadAndDiscardPaddings(c.Conn) // allow paddings before random hello
|
_, t, l, err := ReadAndDiscardPaddings(c.Conn) // allow paddings before random hello
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if c.instance != nil && strings.HasPrefix(err.Error(), "invalid header: ") { // 0-RTT's 0-RTT
|
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 {
|
if c.random == nil {
|
||||||
return 0, errors.New("empty c.random")
|
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)
|
c.peerNonce = make([]byte, 12)
|
||||||
}
|
}
|
||||||
if c.input.Len() > 0 {
|
if c.input.Len() > 0 {
|
||||||
@ -253,13 +255,13 @@ func (c *ClientConn) Read(b []byte) (int, error) {
|
|||||||
if len(dst) <= len(b) {
|
if len(dst) <= len(b) {
|
||||||
dst = b[:len(dst)] // avoids another copy()
|
dst = b[:len(dst)] // avoids another copy()
|
||||||
}
|
}
|
||||||
var peerAead cipher.AEAD
|
var peerAEAD cipher.AEAD
|
||||||
if bytes.Equal(c.peerNonce, MaxNonce) {
|
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)
|
_, err = c.peerAEAD.Open(dst[:0], c.peerNonce, peerData, h)
|
||||||
if peerAead != nil {
|
if peerAEAD != nil {
|
||||||
c.peerAead = peerAead
|
c.peerAEAD = peerAEAD
|
||||||
}
|
}
|
||||||
IncreaseNonce(c.peerNonce)
|
IncreaseNonce(c.peerNonce)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@ -15,4 +15,5 @@
|
|||||||
// https://github.com/XTLS/Xray-core/commit/49580705f6029648399304b816a2737f991582a8
|
// https://github.com/XTLS/Xray-core/commit/49580705f6029648399304b816a2737f991582a8
|
||||||
// https://github.com/XTLS/Xray-core/commit/84835bec7d0d8555d0dd30953ed26a272de814c4
|
// https://github.com/XTLS/Xray-core/commit/84835bec7d0d8555d0dd30953ed26a272de814c4
|
||||||
// https://github.com/XTLS/Xray-core/commit/373558ed7abdbac3de41745cf30ec04c9adde604
|
// https://github.com/XTLS/Xray-core/commit/373558ed7abdbac3de41745cf30ec04c9adde604
|
||||||
|
// https://github.com/XTLS/Xray-core/commit/38cc306c955c362f044e074049a5e67b6b9fb389
|
||||||
package encryption
|
package encryption
|
||||||
|
|||||||
@ -40,7 +40,7 @@ type ServerConn struct {
|
|||||||
baseKey []byte
|
baseKey []byte
|
||||||
ticket []byte
|
ticket []byte
|
||||||
peerRandom []byte
|
peerRandom []byte
|
||||||
peerAead cipher.AEAD
|
peerAEAD cipher.AEAD
|
||||||
peerNonce []byte
|
peerNonce []byte
|
||||||
input bytes.Reader // peerCache
|
input bytes.Reader // peerCache
|
||||||
aead cipher.AEAD
|
aead cipher.AEAD
|
||||||
@ -172,22 +172,23 @@ func (i *ServerInstance) Handshake(conn net.Conn) (*ServerConn, error) {
|
|||||||
}
|
}
|
||||||
pfsKey, encapsulatedPfsKey := pfsEKey.Encapsulate()
|
pfsKey, encapsulatedPfsKey := pfsEKey.Encapsulate()
|
||||||
c.baseKey = append(pfsKey, nfsKey...)
|
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)...)
|
serverHello := make([]byte, 5+1088+21+randBetween(100, 1000))
|
||||||
|
|
||||||
paddingLen := randBetween(100, 1000)
|
|
||||||
|
|
||||||
serverHello := make([]byte, 5+1088+21+5+paddingLen)
|
|
||||||
EncodeHeader(serverHello, 1, 1088+21)
|
EncodeHeader(serverHello, 1, 1088+21)
|
||||||
copy(serverHello[5:], encapsulatedPfsKey)
|
copy(serverHello[5:], encapsulatedPfsKey)
|
||||||
copy(serverHello[5+1088:], c.ticket[11:])
|
copy(serverHello[5+1088:], c.ticket[11:])
|
||||||
EncodeHeader(serverHello[5+1088+21:], 23, int(paddingLen))
|
padding := serverHello[5+1088+21:]
|
||||||
rand.Read(serverHello[5+1088+21+5:])
|
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 {
|
if _, err := c.Conn.Write(serverHello); err != nil {
|
||||||
return nil, err
|
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 {
|
if i.minutes > 0 {
|
||||||
i.Lock()
|
i.Lock()
|
||||||
@ -206,7 +207,7 @@ func (c *ServerConn) Read(b []byte) (int, error) {
|
|||||||
if len(b) == 0 {
|
if len(b) == 0 {
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
if c.peerAead == nil {
|
if c.peerAEAD == nil {
|
||||||
if c.peerRandom == nil { // 1-RTT's 0-RTT
|
if c.peerRandom == nil { // 1-RTT's 0-RTT
|
||||||
_, t, l, err := ReadAndDiscardPaddings(c.Conn) // allow paddings before ticket hello
|
_, t, l, err := ReadAndDiscardPaddings(c.Conn) // allow paddings before ticket hello
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -227,7 +228,7 @@ func (c *ServerConn) Read(b []byte) (int, error) {
|
|||||||
}
|
}
|
||||||
c.peerRandom = peerTicketHello[32:]
|
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)
|
c.peerNonce = make([]byte, 12)
|
||||||
}
|
}
|
||||||
if c.input.Len() > 0 {
|
if c.input.Len() > 0 {
|
||||||
@ -248,13 +249,13 @@ func (c *ServerConn) Read(b []byte) (int, error) {
|
|||||||
if len(dst) <= len(b) {
|
if len(dst) <= len(b) {
|
||||||
dst = b[:len(dst)] // avoids another copy()
|
dst = b[:len(dst)] // avoids another copy()
|
||||||
}
|
}
|
||||||
var peerAead cipher.AEAD
|
var peerAEAD cipher.AEAD
|
||||||
if bytes.Equal(c.peerNonce, MaxNonce) {
|
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)
|
_, err = c.peerAEAD.Open(dst[:0], c.peerNonce, peerData, h)
|
||||||
if peerAead != nil {
|
if peerAEAD != nil {
|
||||||
c.peerAead = peerAead
|
c.peerAEAD = peerAEAD
|
||||||
}
|
}
|
||||||
IncreaseNonce(c.peerNonce)
|
IncreaseNonce(c.peerNonce)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@ -57,7 +57,7 @@ func NewXorConn(conn net.Conn, mode uint32, pKey *ecdh.PublicKey, sKey *ecdh.Pri
|
|||||||
if pKey != nil {
|
if pKey != nil {
|
||||||
c.head = make([]byte, 16+32)
|
c.head = make([]byte, 16+32)
|
||||||
rand.Read(c.head)
|
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
|
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.key, _ = eSKey.ECDH(pKey)
|
||||||
c.ctr = NewCTR(c.key, c.head[:16], false)
|
c.ctr = NewCTR(c.key, c.head[:16], false)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user