Skip to content

Commit 770d4d8

Browse files
authored
Upgrade to go 1.26
1 parent 12ee51e commit 770d4d8

File tree

4 files changed

+98
-80
lines changed

4 files changed

+98
-80
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module github.com/xtls/xray-core
22

3-
go 1.25.7
3+
go 1.26
44

55
require (
66
github.com/apernet/quic-go v0.57.2-0.20260111184307-eec823306178

main/commands/all/tls/ech.go

Lines changed: 90 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
package tls
22

33
import (
4+
"crypto/ecdh"
5+
"crypto/hpke"
6+
"crypto/rand"
47
"encoding/base64"
58
"encoding/pem"
9+
"io"
610
"os"
711

8-
"github.com/xtls/reality/hpke"
912
"github.com/xtls/xray-core/common"
1013
"github.com/xtls/xray-core/main/commands/base"
1114
"github.com/xtls/xray-core/transport/internet/tls"
@@ -40,15 +43,15 @@ func executeECH(cmd *base.Command, args []string) {
4043
// if *input_pqSignatureSchemesEnabled {
4144
// kem = 0x30 // hpke.KEM_X25519_KYBER768_DRAFT00
4245
// } else {
43-
kem = hpke.DHKEM_X25519_HKDF_SHA256
46+
kem = hpke.DHKEM(ecdh.X25519()).ID()
4447
// }
4548

46-
echConfig, priv, err := tls.GenerateECHKeySet(0, *input_serverName, kem)
49+
echConfig, priv, err := generateECHKeySet(0, *input_serverName, kem)
4750
common.Must(err)
4851

4952
var configBuffer, keyBuffer []byte
5053
if *input_echServerKeys == "" {
51-
configBytes, _ := tls.MarshalBinary(echConfig)
54+
configBytes, _ := marshalBinary(echConfig)
5255
var b cryptobyte.Builder
5356
b.AddUint16LengthPrefixed(func(child *cryptobyte.Builder) {
5457
child.AddBytes(configBytes)
@@ -91,3 +94,86 @@ func executeECH(cmd *base.Command, args []string) {
9194
os.Stdout.WriteString("ECH server keys: \n" + base64.StdEncoding.EncodeToString(keyBuffer) + "\n")
9295
}
9396
}
97+
98+
type EchConfig struct {
99+
Version uint16
100+
ConfigID uint8
101+
KemID uint16
102+
PublicKey []byte
103+
SymmetricCipherSuite []EchCipher
104+
MaxNameLength uint8
105+
PublicName []byte
106+
Extensions []Extension
107+
}
108+
109+
type EchCipher struct {
110+
KDFID uint16
111+
AEADID uint16
112+
}
113+
114+
type Extension struct {
115+
Type uint16
116+
Data []byte
117+
}
118+
119+
// reference github.com/OmarTariq612/goech
120+
func marshalBinary(ech EchConfig) ([]byte, error) {
121+
var b cryptobyte.Builder
122+
b.AddUint16(ech.Version)
123+
b.AddUint16LengthPrefixed(func(child *cryptobyte.Builder) {
124+
child.AddUint8(ech.ConfigID)
125+
child.AddUint16(ech.KemID)
126+
child.AddUint16(uint16(len(ech.PublicKey)))
127+
child.AddBytes(ech.PublicKey)
128+
child.AddUint16LengthPrefixed(func(child *cryptobyte.Builder) {
129+
for _, cipherSuite := range ech.SymmetricCipherSuite {
130+
child.AddUint16(cipherSuite.KDFID)
131+
child.AddUint16(cipherSuite.AEADID)
132+
}
133+
})
134+
child.AddUint8(ech.MaxNameLength)
135+
child.AddUint8(uint8(len(ech.PublicName)))
136+
child.AddBytes(ech.PublicName)
137+
child.AddUint16LengthPrefixed(func(child *cryptobyte.Builder) {
138+
for _, extention := range ech.Extensions {
139+
child.AddUint16(extention.Type)
140+
child.AddBytes(extention.Data)
141+
}
142+
})
143+
})
144+
return b.Bytes()
145+
}
146+
147+
const ExtensionEncryptedClientHello = 0xfe0d
148+
149+
func generateECHKeySet(configID uint8, domain string, kem uint16) (EchConfig, []byte, error) {
150+
config := EchConfig{
151+
Version: ExtensionEncryptedClientHello,
152+
ConfigID: configID,
153+
PublicName: []byte(domain),
154+
KemID: kem,
155+
SymmetricCipherSuite: []EchCipher{
156+
{KDFID: hpke.HKDFSHA256().ID(), AEADID: hpke.AES128GCM().ID()},
157+
{KDFID: hpke.HKDFSHA256().ID(), AEADID: hpke.AES256GCM().ID()},
158+
{KDFID: hpke.HKDFSHA256().ID(), AEADID: hpke.ChaCha20Poly1305().ID()},
159+
{KDFID: hpke.HKDFSHA384().ID(), AEADID: hpke.AES128GCM().ID()},
160+
{KDFID: hpke.HKDFSHA384().ID(), AEADID: hpke.AES256GCM().ID()},
161+
{KDFID: hpke.HKDFSHA384().ID(), AEADID: hpke.ChaCha20Poly1305().ID()},
162+
{KDFID: hpke.HKDFSHA512().ID(), AEADID: hpke.AES128GCM().ID()},
163+
{KDFID: hpke.HKDFSHA512().ID(), AEADID: hpke.AES256GCM().ID()},
164+
{KDFID: hpke.HKDFSHA512().ID(), AEADID: hpke.ChaCha20Poly1305().ID()},
165+
},
166+
MaxNameLength: 0,
167+
Extensions: nil,
168+
}
169+
// if kem == hpke.DHKEM_X25519_HKDF_SHA256 {
170+
curve := ecdh.X25519()
171+
priv := make([]byte, 32)
172+
_, err := io.ReadFull(rand.Reader, priv)
173+
if err != nil {
174+
return config, nil, err
175+
}
176+
privKey, _ := curve.NewPrivateKey(priv)
177+
config.PublicKey = privKey.PublicKey().Bytes()
178+
return config, priv, nil
179+
}

transport/internet/tls/config.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -524,11 +524,13 @@ func ConfigFromStreamSettings(settings *internet.MemoryStreamConfig) *Config {
524524

525525
func ParseCurveName(curveNames []string) []tls.CurveID {
526526
curveMap := map[string]tls.CurveID{
527-
"curvep256": tls.CurveP256,
528-
"curvep384": tls.CurveP384,
529-
"curvep521": tls.CurveP521,
530-
"x25519": tls.X25519,
531-
"x25519mlkem768": tls.X25519MLKEM768,
527+
"curvep256": tls.CurveP256,
528+
"curvep384": tls.CurveP384,
529+
"curvep521": tls.CurveP521,
530+
"x25519": tls.X25519,
531+
"x25519mlkem768": tls.X25519MLKEM768,
532+
"secp256r1mlkem768": tls.SecP256r1MLKEM768,
533+
"secp384r1mlkem1024": tls.SecP384r1MLKEM1024,
532534
}
533535

534536
var curveIDs []tls.CurveID

transport/internet/tls/ech.go

Lines changed: 0 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@ package tls
33
import (
44
"bytes"
55
"context"
6-
"crypto/ecdh"
7-
"crypto/rand"
86
"crypto/tls"
97
"encoding/base64"
108
"encoding/binary"
@@ -23,8 +21,6 @@ import (
2321
"golang.org/x/net/http2"
2422

2523
"github.com/miekg/dns"
26-
"github.com/xtls/reality"
27-
"github.com/xtls/reality/hpke"
2824
"github.com/xtls/xray-core/common/errors"
2925
"github.com/xtls/xray-core/common/net"
3026
"github.com/xtls/xray-core/common/utils"
@@ -330,34 +326,6 @@ func dnsQuery(server string, domain string, sockopt *internet.SocketConfig) ([]b
330326
return nil, dns2.DefaultTTL, nil
331327
}
332328

333-
// reference github.com/OmarTariq612/goech
334-
func MarshalBinary(ech reality.EchConfig) ([]byte, error) {
335-
var b cryptobyte.Builder
336-
b.AddUint16(ech.Version)
337-
b.AddUint16LengthPrefixed(func(child *cryptobyte.Builder) {
338-
child.AddUint8(ech.ConfigID)
339-
child.AddUint16(ech.KemID)
340-
child.AddUint16(uint16(len(ech.PublicKey)))
341-
child.AddBytes(ech.PublicKey)
342-
child.AddUint16LengthPrefixed(func(child *cryptobyte.Builder) {
343-
for _, cipherSuite := range ech.SymmetricCipherSuite {
344-
child.AddUint16(cipherSuite.KDFID)
345-
child.AddUint16(cipherSuite.AEADID)
346-
}
347-
})
348-
child.AddUint8(ech.MaxNameLength)
349-
child.AddUint8(uint8(len(ech.PublicName)))
350-
child.AddBytes(ech.PublicName)
351-
child.AddUint16LengthPrefixed(func(child *cryptobyte.Builder) {
352-
for _, extention := range ech.Extensions {
353-
child.AddUint16(extention.Type)
354-
child.AddBytes(extention.Data)
355-
}
356-
})
357-
})
358-
return b.Bytes()
359-
}
360-
361329
var ErrInvalidLen = errors.New("goech: invalid length")
362330

363331
func ConvertToGoECHKeys(data []byte) ([]tls.EncryptedClientHelloKey, error) {
@@ -392,41 +360,3 @@ func ConvertToGoECHKeys(data []byte) ([]tls.EncryptedClientHelloKey, error) {
392360
}
393361
return keys, nil
394362
}
395-
396-
const ExtensionEncryptedClientHello = 0xfe0d
397-
const KDF_HKDF_SHA384 = 0x0002
398-
const KDF_HKDF_SHA512 = 0x0003
399-
400-
func GenerateECHKeySet(configID uint8, domain string, kem uint16) (reality.EchConfig, []byte, error) {
401-
config := reality.EchConfig{
402-
Version: ExtensionEncryptedClientHello,
403-
ConfigID: configID,
404-
PublicName: []byte(domain),
405-
KemID: kem,
406-
SymmetricCipherSuite: []reality.EchCipher{
407-
{KDFID: hpke.KDF_HKDF_SHA256, AEADID: hpke.AEAD_AES_128_GCM},
408-
{KDFID: hpke.KDF_HKDF_SHA256, AEADID: hpke.AEAD_AES_256_GCM},
409-
{KDFID: hpke.KDF_HKDF_SHA256, AEADID: hpke.AEAD_ChaCha20Poly1305},
410-
{KDFID: KDF_HKDF_SHA384, AEADID: hpke.AEAD_AES_128_GCM},
411-
{KDFID: KDF_HKDF_SHA384, AEADID: hpke.AEAD_AES_256_GCM},
412-
{KDFID: KDF_HKDF_SHA384, AEADID: hpke.AEAD_ChaCha20Poly1305},
413-
{KDFID: KDF_HKDF_SHA512, AEADID: hpke.AEAD_AES_128_GCM},
414-
{KDFID: KDF_HKDF_SHA512, AEADID: hpke.AEAD_AES_256_GCM},
415-
{KDFID: KDF_HKDF_SHA512, AEADID: hpke.AEAD_ChaCha20Poly1305},
416-
},
417-
MaxNameLength: 0,
418-
Extensions: nil,
419-
}
420-
// if kem == hpke.DHKEM_X25519_HKDF_SHA256 {
421-
curve := ecdh.X25519()
422-
priv := make([]byte, 32) //x25519
423-
_, err := io.ReadFull(rand.Reader, priv)
424-
if err != nil {
425-
return config, nil, err
426-
}
427-
privKey, _ := curve.NewPrivateKey(priv)
428-
config.PublicKey = privKey.PublicKey().Bytes()
429-
return config, priv, nil
430-
// }
431-
// TODO: add mlkem768 (former kyber768 draft00). The golang mlkem private key is 64 bytes seed?
432-
}

0 commit comments

Comments
 (0)