Add REALITY ChaCha20-Poly1305 auth mode support
This commit is contained in:
parent
ea9a082c04
commit
969ddd88c8
1 changed files with 19 additions and 10 deletions
|
@ -25,6 +25,7 @@ import (
|
||||||
|
|
||||||
utls "github.com/sagernet/utls"
|
utls "github.com/sagernet/utls"
|
||||||
"github.com/zhangyunhao116/fastrand"
|
"github.com/zhangyunhao116/fastrand"
|
||||||
|
"golang.org/x/crypto/chacha20poly1305"
|
||||||
"golang.org/x/crypto/curve25519"
|
"golang.org/x/crypto/curve25519"
|
||||||
"golang.org/x/crypto/hkdf"
|
"golang.org/x/crypto/hkdf"
|
||||||
"golang.org/x/net/http2"
|
"golang.org/x/net/http2"
|
||||||
|
@ -37,6 +38,9 @@ type RealityConfig struct {
|
||||||
ShortID [RealityMaxShortIDLen]byte
|
ShortID [RealityMaxShortIDLen]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//go:linkname aesgcmPreferred crypto/tls.aesgcmPreferred
|
||||||
|
func aesgcmPreferred(ciphers []uint16) bool
|
||||||
|
|
||||||
func GetRealityConn(ctx context.Context, conn net.Conn, ClientFingerprint string, tlsConfig *tls.Config, realityConfig *RealityConfig) (net.Conn, error) {
|
func GetRealityConn(ctx context.Context, conn net.Conn, ClientFingerprint string, tlsConfig *tls.Config, realityConfig *RealityConfig) (net.Conn, error) {
|
||||||
if fingerprint, exists := GetFingerprint(ClientFingerprint); exists {
|
if fingerprint, exists := GetFingerprint(ClientFingerprint); exists {
|
||||||
verifier := &realityVerifier{
|
verifier := &realityVerifier{
|
||||||
|
@ -61,17 +65,17 @@ func GetRealityConn(ctx context.Context, conn net.Conn, ClientFingerprint string
|
||||||
}
|
}
|
||||||
|
|
||||||
hello := uConn.HandshakeState.Hello
|
hello := uConn.HandshakeState.Hello
|
||||||
for i := range hello.SessionId { // https://github.com/golang/go/issues/5373
|
rawSessionID := hello.Raw[39 : 39+32] // the location of session ID
|
||||||
hello.SessionId[i] = 0
|
for i := range rawSessionID { // https://github.com/golang/go/issues/5373
|
||||||
|
rawSessionID[i] = 0
|
||||||
}
|
}
|
||||||
copy(hello.Raw[39:], hello.SessionId)
|
|
||||||
|
|
||||||
binary.BigEndian.PutUint64(hello.SessionId, uint64(time.Now().Unix()))
|
binary.BigEndian.PutUint64(hello.SessionId, uint64(time.Now().Unix()))
|
||||||
|
|
||||||
|
copy(hello.SessionId[8:], realityConfig.ShortID[:])
|
||||||
hello.SessionId[0] = 1
|
hello.SessionId[0] = 1
|
||||||
hello.SessionId[1] = 8
|
hello.SessionId[1] = 8
|
||||||
hello.SessionId[2] = 0
|
hello.SessionId[2] = 2
|
||||||
copy(hello.SessionId[8:], realityConfig.ShortID[:])
|
|
||||||
|
|
||||||
//log.Debugln("REALITY hello.sessionId[:16]: %v", hello.SessionId[:16])
|
//log.Debugln("REALITY hello.sessionId[:16]: %v", hello.SessionId[:16])
|
||||||
|
|
||||||
|
@ -84,9 +88,14 @@ func GetRealityConn(ctx context.Context, conn net.Conn, ClientFingerprint string
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
aesBlock, _ := aes.NewCipher(authKey)
|
var aeadCipher cipher.AEAD
|
||||||
aesGcmCipher, _ := cipher.NewGCM(aesBlock)
|
if aesgcmPreferred(hello.CipherSuites) {
|
||||||
aesGcmCipher.Seal(hello.SessionId[:0], hello.Random[20:], hello.SessionId[:16], hello.Raw)
|
aesBlock, _ := aes.NewCipher(authKey)
|
||||||
|
aeadCipher, _ = cipher.NewGCM(aesBlock)
|
||||||
|
} else {
|
||||||
|
aeadCipher, _ = chacha20poly1305.New(authKey)
|
||||||
|
}
|
||||||
|
aeadCipher.Seal(hello.SessionId[:0], hello.Random[20:], hello.SessionId[:16], hello.Raw)
|
||||||
copy(hello.Raw[39:], hello.SessionId)
|
copy(hello.Raw[39:], hello.SessionId)
|
||||||
//log.Debugln("REALITY hello.sessionId: %v", hello.SessionId)
|
//log.Debugln("REALITY hello.sessionId: %v", hello.SessionId)
|
||||||
//log.Debugln("REALITY uConn.AuthKey: %v", authKey)
|
//log.Debugln("REALITY uConn.AuthKey: %v", authKey)
|
||||||
|
@ -96,7 +105,7 @@ func GetRealityConn(ctx context.Context, conn net.Conn, ClientFingerprint string
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debugln("REALITY Authentication: %v", verifier.verified)
|
log.Debugln("REALITY Authentication: %v, AEAD: %T", verifier.verified, aeadCipher)
|
||||||
|
|
||||||
if !verifier.verified {
|
if !verifier.verified {
|
||||||
go realityClientFallback(uConn, uConfig.ServerName, clientID)
|
go realityClientFallback(uConn, uConfig.ServerName, clientID)
|
||||||
|
@ -137,7 +146,7 @@ type realityVerifier struct {
|
||||||
verified bool
|
verified bool
|
||||||
}
|
}
|
||||||
|
|
||||||
var pOffset = utils.MustOK(reflect.TypeOf((*utls.UConn)(nil)).Elem().FieldByName("peerCertificates")).Offset
|
var pOffset = utils.MustOK(reflect.TypeOf((*utls.Conn)(nil)).Elem().FieldByName("peerCertificates")).Offset
|
||||||
|
|
||||||
func (c *realityVerifier) VerifyPeerCertificate(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
|
func (c *realityVerifier) VerifyPeerCertificate(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
|
||||||
//p, _ := reflect.TypeOf(c.Conn).Elem().FieldByName("peerCertificates")
|
//p, _ := reflect.TypeOf(c.Conn).Elem().FieldByName("peerCertificates")
|
||||||
|
|
Loading…
Reference in a new issue