Skip to content

Commit b305a1d

Browse files
committed
gost
1 parent d51a501 commit b305a1d

8 files changed

Lines changed: 224 additions & 25 deletions

File tree

common/crypto/gost/gost_x509.go

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,8 @@ import (
1212
"github.com/pedroalbanese/gogost/gost3410"
1313
)
1414

15-
// GOST signature algorithm constants
16-
const (
17-
GOST256 = 0x0601 // GOST R 34.10-2012 256-bit
18-
GOST512 = 0x0602 // GOST R 34.10-2012 512-bit
19-
)
20-
2115
// GenerateGOSTSelfSignedCert создает самоподписанный X.509 сертификат GOST2012 (256 или 512)
22-
func GenerateGOSTSelfSignedCert(curve *gost3410.Curve, sigAlg x509.SignatureAlgorithm, cn string, expireDays int) ([]byte, []byte, error) {
16+
func GenerateGOSTSelfSignedCert(curve *gost3410.Curve, cn string, expireDays int) ([]byte, []byte, error) {
2317
fmt.Printf("DEBUG: Starting GenerateGOSTSelfSignedCert\n")
2418

2519
prvRaw := make([]byte, curve.PointSize())
@@ -42,18 +36,27 @@ func GenerateGOSTSelfSignedCert(curve *gost3410.Curve, sigAlg x509.SignatureAlgo
4236
notBefore := time.Now()
4337
notAfter := notBefore.Add(time.Duration(expireDays) * 24 * time.Hour)
4438
serial := big.NewInt(time.Now().UnixNano())
39+
40+
// Determine the correct signature algorithm based on curve size
41+
var signatureAlgorithm x509.SignatureAlgorithm
42+
if curve.PointSize() == 32 {
43+
signatureAlgorithm = x509.GOST256
44+
} else {
45+
signatureAlgorithm = x509.GOST512
46+
}
47+
4548
template := x509.Certificate{
4649
SerialNumber: serial,
4750
NotBefore: notBefore,
4851
NotAfter: notAfter,
49-
SignatureAlgorithm: sigAlg,
52+
SignatureAlgorithm: signatureAlgorithm,
5053
Subject: pkix.Name{CommonName: cn},
5154
KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment,
5255
BasicConstraintsValid: true,
5356
IsCA: false,
5457
}
5558

56-
fmt.Printf("DEBUG: About to call CreateCertificate\n")
59+
fmt.Printf("DEBUG: About to call CreateCertificate with signature algorithm: %d\n", signatureAlgorithm)
5760
certDER, err := x509.CreateCertificate(
5861
rand.Reader,
5962
&template, &template, pub,
@@ -94,11 +97,20 @@ func GenerateGOSTCAChildCert(curve *gost3410.Curve, sigAlg x509.SignatureAlgorit
9497
notBefore := time.Now()
9598
notAfter := notBefore.Add(time.Duration(expireDays) * 24 * time.Hour)
9699
serial := big.NewInt(time.Now().UnixNano())
100+
101+
// Determine the correct signature algorithm based on curve size
102+
var signatureAlgorithm x509.SignatureAlgorithm
103+
if curve.PointSize() == 32 {
104+
signatureAlgorithm = x509.GOST256
105+
} else {
106+
signatureAlgorithm = x509.GOST512
107+
}
108+
97109
template := x509.Certificate{
98110
SerialNumber: serial,
99111
NotBefore: notBefore,
100112
NotAfter: notAfter,
101-
SignatureAlgorithm: sigAlg,
113+
SignatureAlgorithm: signatureAlgorithm,
102114
Subject: pkix.Name{CommonName: cn},
103115
KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment,
104116
BasicConstraintsValid: true,

common/crypto/x509/x509.go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,8 @@ func createTBSCertificate(template *Certificate, pub interface{}, sigAlg Signatu
318318
// Create a basic ASN.1 DER encoding of the To-Be-Signed certificate
319319
// This is a simplified implementation for testing purposes
320320

321+
fmt.Printf("DEBUG: createTBSCertificate called with signature algorithm: %d\n", sigAlg)
322+
321323
// Determine OIDs based on signature algorithm
322324
var signatureOID asn1.ObjectIdentifier
323325
var publicKeyOID asn1.ObjectIdentifier
@@ -368,6 +370,71 @@ func createTBSCertificate(template *Certificate, pub interface{}, sigAlg Signatu
368370
return nil, fmt.Errorf("unsupported public key type: %T", pub)
369371
}
370372

373+
// For GOST certificates, we need to use a different approach
374+
// GOST certificates have a specific ASN.1 structure that's different from standard X.509
375+
if sigAlg == GOST256 || sigAlg == GOST512 {
376+
fmt.Printf("DEBUG: Using GOST-specific certificate structure\n")
377+
// Create GOST-specific certificate structure
378+
gostCert := struct {
379+
Version int `asn1:"optional,explicit,default:0,tag:0"`
380+
SerialNumber *big.Int
381+
SignatureAlgorithm pkix.AlgorithmIdentifier
382+
Issuer pkix.Name
383+
Validity struct {
384+
NotBefore time.Time
385+
NotAfter time.Time
386+
}
387+
Subject pkix.Name
388+
SubjectPublicKeyInfo struct {
389+
Algorithm pkix.AlgorithmIdentifier
390+
PublicKey asn1.BitString
391+
}
392+
IssuerUniqueID asn1.BitString `asn1:"optional,tag:1"`
393+
SubjectUniqueID asn1.BitString `asn1:"optional,tag:2"`
394+
Extensions []pkix.Extension `asn1:"optional,tag:3"`
395+
}{
396+
Version: template.Version,
397+
SerialNumber: template.SerialNumber,
398+
SignatureAlgorithm: pkix.AlgorithmIdentifier{
399+
Algorithm: signatureOID,
400+
},
401+
Issuer: template.Issuer,
402+
Validity: struct {
403+
NotBefore time.Time
404+
NotAfter time.Time
405+
}{
406+
NotBefore: template.NotBefore,
407+
NotAfter: template.NotAfter,
408+
},
409+
Subject: template.Subject,
410+
SubjectPublicKeyInfo: struct {
411+
Algorithm pkix.AlgorithmIdentifier
412+
PublicKey asn1.BitString
413+
}{
414+
Algorithm: pkix.AlgorithmIdentifier{
415+
Algorithm: publicKeyOID,
416+
},
417+
PublicKey: asn1.BitString{
418+
Bytes: publicKeyBytes,
419+
BitLength: bitLength,
420+
},
421+
},
422+
IssuerUniqueID: asn1.BitString{},
423+
SubjectUniqueID: asn1.BitString{},
424+
Extensions: template.Extensions,
425+
}
426+
427+
// Encode to ASN.1 DER
428+
der, err := asn1.Marshal(gostCert)
429+
if err != nil {
430+
return nil, fmt.Errorf("failed to marshal GOST TBS certificate: %w", err)
431+
}
432+
433+
fmt.Printf("DEBUG: GOST TBS certificate marshaled successfully, length: %d\n", len(der))
434+
return der, nil
435+
}
436+
437+
fmt.Printf("DEBUG: Using standard X.509 certificate structure\n")
371438
// Create the basic certificate structure with proper ASN.1 tags
372439
tbs := struct {
373440
Version int `asn1:"optional,explicit,default:0,tag:0"`

common/protocol/tls/cert/cert.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,6 @@ func GenerateGOST2012_256(parent *Certificate, opts ...SM2Option) (*Certificate,
207207

208208
certPEM, keyPEM, err := gost.GenerateGOSTSelfSignedCert(
209209
gost3410.CurveIdtc26gost34102012256paramSetA(),
210-
gost.GOST256,
211210
commonName,
212211
expireDays,
213212
)
@@ -243,7 +242,6 @@ func GenerateGOST2012_512(parent *Certificate, opts ...SM2Option) (*Certificate,
243242

244243
certPEM, keyPEM, err := gost.GenerateGOSTSelfSignedCert(
245244
gost3410.CurveIdtc26gost34102012512paramSetA(),
246-
gost.GOST512,
247245
commonName,
248246
expireDays,
249247
)

connect_local.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
#!/bin/bash
22

3-
echo "openssl s_client -connect 127.0.0.1:443 -servername 127.0.0.1 "
4-
openssl s_client -connect 127.0.0.1:443 -servername 127.0.0.1
3+
echo "openssl s_client -connect 127.0.0.1:443 -servername example.com "
4+
openssl s_client -connect 127.0.0.1:443 -servername example.com

run_vmess_rsa.sh

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
#!/bin/bash
2+
3+
set -e
4+
5+
CERT_FILE="test_cert_rsa.crt"
6+
KEY_FILE="test_cert_rsa.key"
7+
CONFIG_FILE="vmess_rsa.json"
8+
DOMAIN="localhost"
9+
ORG="Test Organization"
10+
CLIENT_ID="b831381d-6324-4d53-ad4f-8cda48b30811"
11+
12+
# 1. Генерация RSA сертификата, если его нет
13+
if [ ! -f "$CERT_FILE" ] || [ ! -f "$KEY_FILE" ]; then
14+
echo "📝 Generating RSA certificate..."
15+
openssl req -x509 -newkey rsa:2048 -keyout "$KEY_FILE" -out "$CERT_FILE" -days 365 -nodes \
16+
-subj "/CN=$DOMAIN/O=$ORG"
17+
echo "✅ RSA certificate generated."
18+
else
19+
echo "✅ RSA certificate already exists."
20+
fi
21+
22+
echo
23+
# 2. Создание VMess server config
24+
cat > "$CONFIG_FILE" << EOF
25+
{
26+
"log": {
27+
"loglevel": "debug"
28+
},
29+
"inbounds": [
30+
{
31+
"port": 443,
32+
"protocol": "vmess",
33+
"settings": {
34+
"clients": [
35+
{
36+
"id": "$CLIENT_ID",
37+
"alterId": 0
38+
}
39+
]
40+
},
41+
"streamSettings": {
42+
"network": "tcp",
43+
"security": "tls",
44+
"tlsSettings": {
45+
"certificates": [
46+
{
47+
"certificateFile": "$CERT_FILE",
48+
"keyFile": "$KEY_FILE"
49+
}
50+
]
51+
}
52+
}
53+
}
54+
],
55+
"outbounds": [
56+
{
57+
"protocol": "freedom"
58+
}
59+
]
60+
}
61+
EOF
62+
63+
echo "✅ Configuration file created: $CONFIG_FILE"
64+
echo
65+
# 3. Запуск Xray
66+
67+
echo "🚀 Starting VMess server with RSA certificate..."
68+
echo "📋 Server details:"
69+
echo " - Port: 443"
70+
echo " - Protocol: VMess"
71+
echo " - Security: TLS with RSA certificate"
72+
echo " - Client ID: $CLIENT_ID"
73+
echo
74+
echo "Press Ctrl+C to stop the server"
75+
echo
76+
77+
./xray -c "$CONFIG_FILE"

transport/internet/tls/config.go

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"crypto/x509"
1010
"encoding/base64"
1111
"encoding/pem"
12+
"fmt"
1213
"os"
1314
"slices"
1415
"strings"
@@ -65,6 +66,7 @@ func (c *Config) BuildCertificates() []*tls.Certificate {
6566
getX509KeyPair := func() *tls.Certificate {
6667
// Check if this is an SM2 certificate by trying to parse it with SM2 library first
6768
if isSM2Certificate(entry.Certificate) {
69+
fmt.Printf("DEBUG: Processing SM2 certificate\n")
6870
keyPair, err := buildSM2KeyPair(entry.Certificate, entry.Key)
6971
if err != nil {
7072
errors.LogWarningInner(context.Background(), err, "ignoring invalid SM2 key pair")
@@ -74,16 +76,20 @@ func (c *Config) BuildCertificates() []*tls.Certificate {
7476
}
7577

7678
// Fall back to standard X509 processing
79+
fmt.Printf("DEBUG: Processing standard X509 certificate\n")
7780
keyPair, err := tls.X509KeyPair(entry.Certificate, entry.Key)
7881
if err != nil {
82+
fmt.Printf("DEBUG: X509KeyPair error: %v\n", err)
7983
errors.LogWarningInner(context.Background(), err, "ignoring invalid X509 key pair")
8084
return nil
8185
}
8286
keyPair.Leaf, err = x509.ParseCertificate(keyPair.Certificate[0])
8387
if err != nil {
88+
fmt.Printf("DEBUG: ParseCertificate error: %v\n", err)
8489
errors.LogWarningInner(context.Background(), err, "ignoring invalid certificate")
8590
return nil
8691
}
92+
fmt.Printf("DEBUG: Successfully loaded X509 certificate\n")
8793
return &keyPair
8894
}
8995
if keyPair := getX509KeyPair(); keyPair != nil {
@@ -122,22 +128,22 @@ func isSM2Certificate(certPEM []byte) bool {
122128
return false
123129
}
124130

125-
// Try to parse with SM2 x509 library
126-
_, err := sm2x509.ParseCertificate(block.Bytes)
131+
// First, try to parse as standard x509 to see if it's a regular certificate
132+
_, err := x509.ParseCertificate(block.Bytes)
127133
if err == nil {
128-
return true
129-
}
130-
131-
// Also check if it's a standard x509 certificate that might be SM2
132-
// by looking for SM2 OIDs or curve parameters
133-
if len(block.Bytes) > 0 {
134-
// Check if certificate contains SM2 curve OID
134+
// It's a valid standard x509 certificate, check if it contains SM2-specific OIDs
135135
if bytes.Contains(block.Bytes, []byte{0x06, 0x08, 0x2A, 0x81, 0x1C, 0xCF, 0x55, 0x01, 0x82, 0x2D}) {
136-
return true
136+
// Contains SM2 curve OID, try SM2 parsing
137+
_, err := sm2x509.ParseCertificate(block.Bytes)
138+
return err == nil
137139
}
140+
// Standard x509 certificate without SM2 OIDs - not SM2
141+
return false
138142
}
139143

140-
return false
144+
// If standard x509 parsing failed, try SM2 parsing
145+
_, err = sm2x509.ParseCertificate(block.Bytes)
146+
return err == nil
141147
}
142148

143149
// buildSM2KeyPair creates a tls.Certificate from SM2 certificate and key

verify_cert_rsa.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/bin/bash
2+
3+
openssl x509 -in test_cert_rsa.crt -text -noout

vmess_rsa.json

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
{
2+
"log": {
3+
"loglevel": "debug"
4+
},
5+
"inbounds": [
6+
{
7+
"port": 443,
8+
"protocol": "vmess",
9+
"settings": {
10+
"clients": [
11+
{
12+
"id": "b831381d-6324-4d53-ad4f-8cda48b30811",
13+
"alterId": 0
14+
}
15+
]
16+
},
17+
"streamSettings": {
18+
"network": "tcp",
19+
"security": "tls",
20+
"tlsSettings": {
21+
"certificates": [
22+
{
23+
"certificateFile": "test_cert_rsa.crt",
24+
"keyFile": "test_cert_rsa.key"
25+
}
26+
]
27+
}
28+
}
29+
}
30+
],
31+
"outbounds": [
32+
{
33+
"protocol": "freedom"
34+
}
35+
]
36+
}

0 commit comments

Comments
 (0)