Chore: Migrate to Go 1.26 (#5680)

This commit is contained in:
风扇滑翔翼
2026-02-12 12:08:59 +08:00
committed by GitHub
parent 7dc3f87cd8
commit d100be5ad5
4 changed files with 98 additions and 80 deletions

2
go.mod
View File

@@ -1,6 +1,6 @@
module github.com/xtls/xray-core
go 1.25.7
go 1.26
require (
github.com/apernet/quic-go v0.57.2-0.20260111184307-eec823306178

View File

@@ -1,11 +1,14 @@
package tls
import (
"crypto/ecdh"
"crypto/hpke"
"crypto/rand"
"encoding/base64"
"encoding/pem"
"io"
"os"
"github.com/xtls/reality/hpke"
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/main/commands/base"
"github.com/xtls/xray-core/transport/internet/tls"
@@ -40,15 +43,15 @@ func executeECH(cmd *base.Command, args []string) {
// if *input_pqSignatureSchemesEnabled {
// kem = 0x30 // hpke.KEM_X25519_KYBER768_DRAFT00
// } else {
kem = hpke.DHKEM_X25519_HKDF_SHA256
kem = hpke.DHKEM(ecdh.X25519()).ID()
// }
echConfig, priv, err := tls.GenerateECHKeySet(0, *input_serverName, kem)
echConfig, priv, err := generateECHKeySet(0, *input_serverName, kem)
common.Must(err)
var configBuffer, keyBuffer []byte
if *input_echServerKeys == "" {
configBytes, _ := tls.MarshalBinary(echConfig)
configBytes, _ := marshalBinary(echConfig)
var b cryptobyte.Builder
b.AddUint16LengthPrefixed(func(child *cryptobyte.Builder) {
child.AddBytes(configBytes)
@@ -91,3 +94,86 @@ func executeECH(cmd *base.Command, args []string) {
os.Stdout.WriteString("ECH server keys: \n" + base64.StdEncoding.EncodeToString(keyBuffer) + "\n")
}
}
type EchConfig struct {
Version uint16
ConfigID uint8
KemID uint16
PublicKey []byte
SymmetricCipherSuite []EchCipher
MaxNameLength uint8
PublicName []byte
Extensions []Extension
}
type EchCipher struct {
KDFID uint16
AEADID uint16
}
type Extension struct {
Type uint16
Data []byte
}
// reference github.com/OmarTariq612/goech
func marshalBinary(ech EchConfig) ([]byte, error) {
var b cryptobyte.Builder
b.AddUint16(ech.Version)
b.AddUint16LengthPrefixed(func(child *cryptobyte.Builder) {
child.AddUint8(ech.ConfigID)
child.AddUint16(ech.KemID)
child.AddUint16(uint16(len(ech.PublicKey)))
child.AddBytes(ech.PublicKey)
child.AddUint16LengthPrefixed(func(child *cryptobyte.Builder) {
for _, cipherSuite := range ech.SymmetricCipherSuite {
child.AddUint16(cipherSuite.KDFID)
child.AddUint16(cipherSuite.AEADID)
}
})
child.AddUint8(ech.MaxNameLength)
child.AddUint8(uint8(len(ech.PublicName)))
child.AddBytes(ech.PublicName)
child.AddUint16LengthPrefixed(func(child *cryptobyte.Builder) {
for _, extention := range ech.Extensions {
child.AddUint16(extention.Type)
child.AddBytes(extention.Data)
}
})
})
return b.Bytes()
}
const ExtensionEncryptedClientHello = 0xfe0d
func generateECHKeySet(configID uint8, domain string, kem uint16) (EchConfig, []byte, error) {
config := EchConfig{
Version: ExtensionEncryptedClientHello,
ConfigID: configID,
PublicName: []byte(domain),
KemID: kem,
SymmetricCipherSuite: []EchCipher{
{KDFID: hpke.HKDFSHA256().ID(), AEADID: hpke.AES128GCM().ID()},
{KDFID: hpke.HKDFSHA256().ID(), AEADID: hpke.AES256GCM().ID()},
{KDFID: hpke.HKDFSHA256().ID(), AEADID: hpke.ChaCha20Poly1305().ID()},
{KDFID: hpke.HKDFSHA384().ID(), AEADID: hpke.AES128GCM().ID()},
{KDFID: hpke.HKDFSHA384().ID(), AEADID: hpke.AES256GCM().ID()},
{KDFID: hpke.HKDFSHA384().ID(), AEADID: hpke.ChaCha20Poly1305().ID()},
{KDFID: hpke.HKDFSHA512().ID(), AEADID: hpke.AES128GCM().ID()},
{KDFID: hpke.HKDFSHA512().ID(), AEADID: hpke.AES256GCM().ID()},
{KDFID: hpke.HKDFSHA512().ID(), AEADID: hpke.ChaCha20Poly1305().ID()},
},
MaxNameLength: 0,
Extensions: nil,
}
// if kem == hpke.DHKEM_X25519_HKDF_SHA256 {
curve := ecdh.X25519()
priv := make([]byte, 32)
_, err := io.ReadFull(rand.Reader, priv)
if err != nil {
return config, nil, err
}
privKey, _ := curve.NewPrivateKey(priv)
config.PublicKey = privKey.PublicKey().Bytes()
return config, priv, nil
}

View File

@@ -529,6 +529,8 @@ func ParseCurveName(curveNames []string) []tls.CurveID {
"curvep521": tls.CurveP521,
"x25519": tls.X25519,
"x25519mlkem768": tls.X25519MLKEM768,
"secp256r1mlkem768": tls.SecP256r1MLKEM768,
"secp384r1mlkem1024": tls.SecP384r1MLKEM1024,
}
var curveIDs []tls.CurveID

View File

@@ -3,8 +3,6 @@ package tls
import (
"bytes"
"context"
"crypto/ecdh"
"crypto/rand"
"crypto/tls"
"encoding/base64"
"encoding/binary"
@@ -23,8 +21,6 @@ import (
"golang.org/x/net/http2"
"github.com/miekg/dns"
"github.com/xtls/reality"
"github.com/xtls/reality/hpke"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/utils"
@@ -330,34 +326,6 @@ func dnsQuery(server string, domain string, sockopt *internet.SocketConfig) ([]b
return nil, dns2.DefaultTTL, nil
}
// reference github.com/OmarTariq612/goech
func MarshalBinary(ech reality.EchConfig) ([]byte, error) {
var b cryptobyte.Builder
b.AddUint16(ech.Version)
b.AddUint16LengthPrefixed(func(child *cryptobyte.Builder) {
child.AddUint8(ech.ConfigID)
child.AddUint16(ech.KemID)
child.AddUint16(uint16(len(ech.PublicKey)))
child.AddBytes(ech.PublicKey)
child.AddUint16LengthPrefixed(func(child *cryptobyte.Builder) {
for _, cipherSuite := range ech.SymmetricCipherSuite {
child.AddUint16(cipherSuite.KDFID)
child.AddUint16(cipherSuite.AEADID)
}
})
child.AddUint8(ech.MaxNameLength)
child.AddUint8(uint8(len(ech.PublicName)))
child.AddBytes(ech.PublicName)
child.AddUint16LengthPrefixed(func(child *cryptobyte.Builder) {
for _, extention := range ech.Extensions {
child.AddUint16(extention.Type)
child.AddBytes(extention.Data)
}
})
})
return b.Bytes()
}
var ErrInvalidLen = errors.New("goech: invalid length")
func ConvertToGoECHKeys(data []byte) ([]tls.EncryptedClientHelloKey, error) {
@@ -392,41 +360,3 @@ func ConvertToGoECHKeys(data []byte) ([]tls.EncryptedClientHelloKey, error) {
}
return keys, nil
}
const ExtensionEncryptedClientHello = 0xfe0d
const KDF_HKDF_SHA384 = 0x0002
const KDF_HKDF_SHA512 = 0x0003
func GenerateECHKeySet(configID uint8, domain string, kem uint16) (reality.EchConfig, []byte, error) {
config := reality.EchConfig{
Version: ExtensionEncryptedClientHello,
ConfigID: configID,
PublicName: []byte(domain),
KemID: kem,
SymmetricCipherSuite: []reality.EchCipher{
{KDFID: hpke.KDF_HKDF_SHA256, AEADID: hpke.AEAD_AES_128_GCM},
{KDFID: hpke.KDF_HKDF_SHA256, AEADID: hpke.AEAD_AES_256_GCM},
{KDFID: hpke.KDF_HKDF_SHA256, AEADID: hpke.AEAD_ChaCha20Poly1305},
{KDFID: KDF_HKDF_SHA384, AEADID: hpke.AEAD_AES_128_GCM},
{KDFID: KDF_HKDF_SHA384, AEADID: hpke.AEAD_AES_256_GCM},
{KDFID: KDF_HKDF_SHA384, AEADID: hpke.AEAD_ChaCha20Poly1305},
{KDFID: KDF_HKDF_SHA512, AEADID: hpke.AEAD_AES_128_GCM},
{KDFID: KDF_HKDF_SHA512, AEADID: hpke.AEAD_AES_256_GCM},
{KDFID: KDF_HKDF_SHA512, AEADID: hpke.AEAD_ChaCha20Poly1305},
},
MaxNameLength: 0,
Extensions: nil,
}
// if kem == hpke.DHKEM_X25519_HKDF_SHA256 {
curve := ecdh.X25519()
priv := make([]byte, 32) //x25519
_, err := io.ReadFull(rand.Reader, priv)
if err != nil {
return config, nil, err
}
privKey, _ := curve.NewPrivateKey(priv)
config.PublicKey = privKey.PublicKey().Bytes()
return config, priv, nil
// }
// TODO: add mlkem768 (former kyber768 draft00). The golang mlkem private key is 64 bytes seed?
}