Skip to content

Commit 4eaf792

Browse files
authored
REALITY protocol: Add optional Post-Quantum ML-DSA-65 signature to cert's ExtraExtensions
1 parent ebbbf46 commit 4eaf792

File tree

4 files changed

+58
-15
lines changed

4 files changed

+58
-15
lines changed

common.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -562,6 +562,8 @@ type Config struct {
562562
MaxTimeDiff time.Duration
563563
ShortIds map[[8]byte]bool
564564

565+
Mldsa65Key []byte
566+
565567
LimitFallbackUpload LimitFallback
566568
LimitFallbackDownload LimitFallback
567569

go.mod

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,16 @@ module github.com/xtls/reality
33
go 1.24
44

55
require (
6+
github.com/cloudflare/circl v1.6.1
67
github.com/juju/ratelimit v1.0.2
78
github.com/pires/go-proxyproto v0.8.1
8-
github.com/refraction-networking/utls v1.7.3
9-
golang.org/x/crypto v0.39.0
10-
golang.org/x/sys v0.33.0
9+
github.com/refraction-networking/utls v1.8.0
10+
golang.org/x/crypto v0.40.0
11+
golang.org/x/sys v0.34.0
12+
)
13+
14+
require (
15+
github.com/andybalholm/brotli v1.0.6 // indirect
16+
github.com/klauspost/compress v1.17.4 // indirect
17+
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
1118
)

go.sum

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,23 @@
1+
github.com/andybalholm/brotli v1.0.6 h1:Yf9fFpf49Zrxb9NlQaluyE92/+X7UVHlhMNJN2sxfOI=
2+
github.com/andybalholm/brotli v1.0.6/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
3+
github.com/cloudflare/circl v1.6.1 h1:zqIqSPIndyBh1bjLVVDHMPpVKqp8Su/V+6MeDzzQBQ0=
4+
github.com/cloudflare/circl v1.6.1/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
15
github.com/juju/ratelimit v1.0.2 h1:sRxmtRiajbvrcLQT7S+JbqU0ntsb9W2yhSdNN8tWfaI=
26
github.com/juju/ratelimit v1.0.2/go.mod h1:qapgC/Gy+xNh9UxzV13HGGl/6UXNN+ct+vwSgWNm/qk=
7+
github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4=
8+
github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
9+
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
10+
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
11+
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
12+
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
13+
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
314
github.com/pires/go-proxyproto v0.8.1 h1:9KEixbdJfhrbtjpz/ZwCdWDD2Xem0NZ38qMYaASJgp0=
415
github.com/pires/go-proxyproto v0.8.1/go.mod h1:ZKAAyp3cgy5Y5Mo4n9AlScrkCZwUy0g3Jf+slqQVcuU=
5-
github.com/refraction-networking/utls v1.7.3 h1:L0WRhHY7Oq1T0zkdzVZMR6zWZv+sXbHB9zcuvsAEqCo=
6-
github.com/refraction-networking/utls v1.7.3/go.mod h1:TUhh27RHMGtQvjQq+RyO11P6ZNQNBb3N0v7wsEjKAIQ=
7-
golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM=
8-
golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U=
9-
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
10-
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
16+
github.com/refraction-networking/utls v1.8.0 h1:L38krhiTAyj9EeiQQa2sg+hYb4qwLCqdMcpZrRfbONE=
17+
github.com/refraction-networking/utls v1.8.0/go.mod h1:jkSOEkLqn+S/jtpEHPOsVv/4V4EVnelwbMQl4vCWXAM=
18+
golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM=
19+
golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY=
20+
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
21+
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
22+
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
23+
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=

handshake_server_tls13.go

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
"crypto/rsa"
1717
"crypto/sha512"
1818
"crypto/x509"
19+
"crypto/x509/pkix"
1920
"encoding/binary"
2021
"errors"
2122
"fmt"
@@ -26,6 +27,7 @@ import (
2627
"sort"
2728
"time"
2829

30+
"github.com/cloudflare/circl/sign/mldsa/mldsa65"
2931
"github.com/xtls/reality/fips140tls"
3032
"github.com/xtls/reality/hpke"
3133
"github.com/xtls/reality/tls13"
@@ -70,19 +72,26 @@ type serverHandshakeStateTLS13 struct {
7072
}
7173

7274
var (
73-
ed25519Priv ed25519.PrivateKey
74-
signedCert []byte
75+
ed25519Priv ed25519.PrivateKey
76+
signedCert []byte
77+
signedCertMldsa65 []byte
7578
)
7679

7780
func init() {
7881
certificate := x509.Certificate{SerialNumber: &big.Int{}}
82+
certificateMldsa65 := x509.Certificate{SerialNumber: &big.Int{}, ExtraExtensions: []pkix.Extension{{Id: []int{0, 0}, Value: empty[:3309]}}}
7983
_, ed25519Priv, _ = ed25519.GenerateKey(rand.Reader)
8084
signedCert, _ = x509.CreateCertificate(rand.Reader, &certificate, &certificate, ed25519.PublicKey(ed25519Priv[32:]), ed25519Priv)
85+
signedCertMldsa65, _ = x509.CreateCertificate(rand.Reader, &certificateMldsa65, &certificateMldsa65, ed25519.PublicKey(ed25519Priv[32:]), ed25519Priv)
8186
}
8287

8388
func (hs *serverHandshakeStateTLS13) handshake() error {
8489
c := hs.c
85-
90+
if c.config.Show {
91+
remoteAddr := c.RemoteAddr().String()
92+
fmt.Printf("REALITY remoteAddr: %v\tis using X25519MLKEM768 for TLS' communication: %v\n", remoteAddr, hs.hello.serverShare.group == X25519MLKEM768)
93+
fmt.Printf("REALITY remoteAddr: %v\tis using ML-DSA-65 for cert's extra signature: %v\n", remoteAddr, len(c.config.Mldsa65Key) > 0)
94+
}
8695
// For an overview of the TLS 1.3 handshake, see RFC 8446, Section 2.
8796
/*
8897
if err := hs.processClientHello(); err != nil {
@@ -130,14 +139,26 @@ func (hs *serverHandshakeStateTLS13) handshake() error {
130139
}
131140
*/
132141
{
133-
signedCert := append([]byte{}, signedCert...)
142+
var cert []byte
143+
if len(c.config.Mldsa65Key) > 0 {
144+
cert = bytes.Clone(signedCertMldsa65)
145+
} else {
146+
cert = bytes.Clone(signedCert)
147+
}
134148

135149
h := hmac.New(sha512.New, c.AuthKey)
136150
h.Write(ed25519Priv[32:])
137-
h.Sum(signedCert[:len(signedCert)-64])
151+
h.Sum(cert[:len(cert)-64])
152+
153+
if len(c.config.Mldsa65Key) > 0 {
154+
h.Write(hs.clientHello.original)
155+
h.Write(hs.hello.original)
156+
key, _ := mldsa65.Scheme().UnmarshalBinaryPrivateKey(c.config.Mldsa65Key)
157+
mldsa65.SignTo(key.(*mldsa65.PrivateKey), h.Sum(nil), nil, false, cert[126:]) // fixed location
158+
}
138159

139160
hs.cert = &Certificate{
140-
Certificate: [][]byte{signedCert},
161+
Certificate: [][]byte{cert},
141162
PrivateKey: ed25519Priv,
142163
}
143164
hs.sigAlg = Ed25519

0 commit comments

Comments
 (0)