mirror of
https://github.com/XTLS/Xray-core.git
synced 2025-08-22 09:36:49 +08:00
Use SHA3-256 instead of SHA2-256; Support XTLS Vision for random appearance
https://github.com/XTLS/Xray-core/pull/4952#issuecomment-3197163816
This commit is contained in:
@@ -15,6 +15,14 @@ type XorConn struct {
|
||||
peerCtr cipher.Stream
|
||||
isHeader bool
|
||||
skipNext bool
|
||||
|
||||
out_after0 bool
|
||||
out_header []byte
|
||||
out_skip int
|
||||
|
||||
in_after0 bool
|
||||
in_header []byte
|
||||
in_skip int
|
||||
}
|
||||
|
||||
func NewXorConn(conn net.Conn, key []byte) *XorConn {
|
||||
@@ -26,29 +34,56 @@ func (c *XorConn) Write(b []byte) (int, error) { // whole one/two records
|
||||
if len(b) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
var iv []byte
|
||||
if c.ctr == nil {
|
||||
block, _ := aes.NewCipher(c.key)
|
||||
iv = make([]byte, 16)
|
||||
rand.Read(iv)
|
||||
c.ctr = cipher.NewCTR(block, iv)
|
||||
if !c.out_after0 {
|
||||
var iv []byte
|
||||
if c.ctr == nil {
|
||||
block, _ := aes.NewCipher(c.key)
|
||||
iv = make([]byte, 16)
|
||||
rand.Read(iv)
|
||||
c.ctr = cipher.NewCTR(block, iv)
|
||||
}
|
||||
t, l, _ := DecodeHeader(b)
|
||||
if t == 23 { // single 23
|
||||
l = 5
|
||||
} else { // 1/0 + 23, or noises only
|
||||
l += 10
|
||||
if t == 0 {
|
||||
c.out_after0 = true
|
||||
}
|
||||
}
|
||||
c.ctr.XORKeyStream(b[:l], b[:l]) // caller MUST discard b
|
||||
if iv != nil {
|
||||
b = append(iv, b...)
|
||||
}
|
||||
if _, err := c.Conn.Write(b); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if iv != nil {
|
||||
b = b[16:] // for len(b)
|
||||
}
|
||||
return len(b), nil
|
||||
}
|
||||
t, l, _ := DecodeHeader(b)
|
||||
if t == 23 { // single 23
|
||||
l = 5
|
||||
} else { // 1/0 + 23, or noises only
|
||||
l += 10
|
||||
}
|
||||
c.ctr.XORKeyStream(b[:l], b[:l]) // caller MUST discard b
|
||||
if iv != nil {
|
||||
b = append(iv, b...)
|
||||
for p := b; ; { // for XTLS
|
||||
if len(p) <= c.out_skip {
|
||||
c.out_skip -= len(p)
|
||||
break
|
||||
}
|
||||
p = p[c.out_skip:]
|
||||
c.out_skip = 0
|
||||
need := 5 - len(c.out_header)
|
||||
if len(p) < need {
|
||||
c.out_header = append(c.out_header, p...)
|
||||
c.ctr.XORKeyStream(p, p)
|
||||
break
|
||||
}
|
||||
_, c.out_skip, _ = DecodeHeader(append(c.out_header, p[:need]...))
|
||||
c.out_header = make([]byte, 0, 5) // DO NOT CHANGE
|
||||
c.ctr.XORKeyStream(p[:need], p[:need])
|
||||
p = p[need:]
|
||||
}
|
||||
if _, err := c.Conn.Write(b); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if iv != nil {
|
||||
b = b[16:] // for len(b)
|
||||
}
|
||||
return len(b), nil
|
||||
}
|
||||
|
||||
@@ -56,31 +91,56 @@ func (c *XorConn) Read(b []byte) (int, error) { // 5-bytes, data, 5-bytes...
|
||||
if len(b) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
if c.peerCtr == nil {
|
||||
peerIv := make([]byte, 16)
|
||||
if _, err := io.ReadFull(c.Conn, peerIv); err != nil {
|
||||
if !c.in_after0 || !c.isHeader {
|
||||
if c.peerCtr == nil {
|
||||
peerIv := make([]byte, 16)
|
||||
if _, err := io.ReadFull(c.Conn, peerIv); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
block, _ := aes.NewCipher(c.key)
|
||||
c.peerCtr = cipher.NewCTR(block, peerIv)
|
||||
c.isHeader = true
|
||||
}
|
||||
if _, err := io.ReadFull(c.Conn, b); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
block, _ := aes.NewCipher(c.key)
|
||||
c.peerCtr = cipher.NewCTR(block, peerIv)
|
||||
c.isHeader = true
|
||||
}
|
||||
if _, err := io.ReadFull(c.Conn, b); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if c.skipNext {
|
||||
c.skipNext = false
|
||||
if c.skipNext {
|
||||
c.skipNext = false
|
||||
return len(b), nil
|
||||
}
|
||||
c.peerCtr.XORKeyStream(b, b)
|
||||
if c.isHeader { // always 5-bytes
|
||||
if t, _, _ := DecodeHeader(b); t == 23 {
|
||||
c.skipNext = true
|
||||
} else {
|
||||
c.isHeader = false
|
||||
if t == 0 {
|
||||
c.in_after0 = true
|
||||
}
|
||||
}
|
||||
} else {
|
||||
c.isHeader = true
|
||||
}
|
||||
return len(b), nil
|
||||
}
|
||||
c.peerCtr.XORKeyStream(b, b)
|
||||
if c.isHeader { // always 5-bytes
|
||||
if t, _, _ := DecodeHeader(b); t == 23 {
|
||||
c.skipNext = true
|
||||
} else {
|
||||
c.isHeader = false
|
||||
n, err := c.Conn.Read(b)
|
||||
for p := b[:n]; ; { // for XTLS
|
||||
if len(p) <= c.in_skip {
|
||||
c.in_skip -= len(p)
|
||||
break
|
||||
}
|
||||
} else {
|
||||
c.isHeader = true
|
||||
p = p[c.in_skip:]
|
||||
c.in_skip = 0
|
||||
need := 5 - len(c.in_header)
|
||||
if len(p) < need {
|
||||
c.peerCtr.XORKeyStream(p, p)
|
||||
c.in_header = append(c.in_header, p...)
|
||||
break
|
||||
}
|
||||
c.peerCtr.XORKeyStream(p[:need], p[:need])
|
||||
_, c.in_skip, _ = DecodeHeader(append(c.in_header, p[:need]...))
|
||||
c.in_header = make([]byte, 0, 5) // DO NOT CHANGE
|
||||
p = p[need:]
|
||||
}
|
||||
return len(b), nil
|
||||
return n, err
|
||||
}
|
||||
|
Reference in New Issue
Block a user