Skip to content

Commit d51a501

Browse files
committed
x509
1 parent ddfe987 commit d51a501

File tree

6 files changed

+114
-13
lines changed

6 files changed

+114
-13
lines changed

common/crypto/x509/x509.go

Lines changed: 106 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
"github.com/pedroalbanese/gogost/gost34112012256"
1818
"github.com/tjfoc/gmsm/sm2"
1919
"github.com/tjfoc/gmsm/sm3"
20+
"crypto/elliptic"
2021
)
2122

2223
// SignatureAlgorithm represents the algorithm used to sign the certificate
@@ -223,7 +224,7 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub interf
223224
}
224225

225226
// Create TBS certificate
226-
tbsCert, err := createTBSCertificate(template, sigAlg)
227+
tbsCert, err := createTBSCertificate(template, pub, sigAlg)
227228
if err != nil {
228229
return nil, fmt.Errorf("failed to create TBS certificate: %w", err)
229230
}
@@ -313,24 +314,58 @@ func ParsePKCS1PrivateKey(der []byte) (*rsa.PrivateKey, error) {
313314
}
314315

315316
// Helper functions
316-
func createTBSCertificate(template *Certificate, sigAlg SignatureAlgorithm) ([]byte, error) {
317+
func createTBSCertificate(template *Certificate, pub interface{}, sigAlg SignatureAlgorithm) ([]byte, error) {
317318
// Create a basic ASN.1 DER encoding of the To-Be-Signed certificate
318319
// This is a simplified implementation for testing purposes
319320

320-
// Determine GOST OID based on signature algorithm
321+
// Determine OIDs based on signature algorithm
321322
var signatureOID asn1.ObjectIdentifier
322323
var publicKeyOID asn1.ObjectIdentifier
323324

324325
switch sigAlg {
326+
case SHA256WithRSA:
327+
signatureOID = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 11} // SHA256WithRSA
328+
publicKeyOID = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1} // RSA
329+
case ECDSAWithSHA256:
330+
signatureOID = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 2} // ECDSAWithSHA256
331+
publicKeyOID = asn1.ObjectIdentifier{1, 2, 840, 10045, 2, 1} // EC
325332
case GOST256:
326333
signatureOID = asn1.ObjectIdentifier{1, 2, 643, 7, 1, 1, 3, 2} // GOST R 34.10-2012 256-bit
327334
publicKeyOID = asn1.ObjectIdentifier{1, 2, 643, 7, 1, 1, 1, 1} // GOST R 34.10-2012 256-bit
328335
case GOST512:
329336
signatureOID = asn1.ObjectIdentifier{1, 2, 643, 7, 1, 1, 3, 3} // GOST R 34.10-2012 512-bit
330337
publicKeyOID = asn1.ObjectIdentifier{1, 2, 643, 7, 1, 1, 1, 2} // GOST R 34.10-2012 512-bit
331338
default:
332-
signatureOID = asn1.ObjectIdentifier{1, 2, 643, 7, 1, 1, 3, 2} // Default to 256-bit
333-
publicKeyOID = asn1.ObjectIdentifier{1, 2, 643, 7, 1, 1, 1, 1}
339+
signatureOID = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 2} // Default to ECDSAWithSHA256
340+
publicKeyOID = asn1.ObjectIdentifier{1, 2, 840, 10045, 2, 1} // EC
341+
}
342+
343+
// Encode the public key based on its type
344+
var publicKeyBytes []byte
345+
var bitLength int
346+
347+
switch p := pub.(type) {
348+
case *rsa.PublicKey:
349+
// For RSA, we need to encode the modulus and exponent
350+
publicKeyBytes = []byte{0x04} // Placeholder for RSA public key
351+
bitLength = p.N.BitLen()
352+
case *ecdsa.PublicKey:
353+
// For ECDSA, encode the point in uncompressed format
354+
publicKeyBytes = append([]byte{0x04}, p.X.Bytes()...)
355+
publicKeyBytes = append(publicKeyBytes, p.Y.Bytes()...)
356+
bitLength = len(publicKeyBytes) * 8
357+
case *sm2.PublicKey:
358+
// For SM2, encode the point in uncompressed format
359+
publicKeyBytes = append([]byte{0x04}, p.X.Bytes()...)
360+
publicKeyBytes = append(publicKeyBytes, p.Y.Bytes()...)
361+
bitLength = len(publicKeyBytes) * 8
362+
case *gost3410.PublicKey:
363+
// For GOST, encode the point in uncompressed format (like ECDSA)
364+
publicKeyBytes = append([]byte{0x04}, p.X.Bytes()...)
365+
publicKeyBytes = append(publicKeyBytes, p.Y.Bytes()...)
366+
bitLength = len(publicKeyBytes) * 8
367+
default:
368+
return nil, fmt.Errorf("unsupported public key type: %T", pub)
334369
}
335370

336371
// Create the basic certificate structure with proper ASN.1 tags
@@ -374,8 +409,8 @@ func createTBSCertificate(template *Certificate, sigAlg SignatureAlgorithm) ([]b
374409
Algorithm: publicKeyOID,
375410
},
376411
PublicKey: asn1.BitString{
377-
Bytes: []byte{0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // Placeholder GOST public key
378-
BitLength: 256,
412+
Bytes: publicKeyBytes,
413+
BitLength: bitLength,
379414
},
380415
},
381416
IssuerUniqueID: asn1.BitString{},
@@ -549,4 +584,68 @@ func marshalGOSTPKCS8PrivateKey(key *gost3410.PrivateKey) ([]byte, error) {
549584
}
550585

551586
return der, nil
587+
}
588+
589+
// encodeSubjectPublicKeyInfo формирует ASN.1 DER SubjectPublicKeyInfo и возвращает AlgorithmIdentifier и BitString
590+
func encodeSubjectPublicKeyInfo(pub interface{}, sigAlg SignatureAlgorithm) (pkix.AlgorithmIdentifier, asn1.BitString, error) {
591+
var algo pkix.AlgorithmIdentifier
592+
var pubKeyBytes []byte
593+
var bitLength int
594+
595+
switch p := pub.(type) {
596+
case *rsa.PublicKey:
597+
algo = pkix.AlgorithmIdentifier{
598+
Algorithm: asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1},
599+
}
600+
type rsaPub struct {
601+
N *big.Int
602+
E int
603+
}
604+
pubASN1, err := asn1.Marshal(rsaPub{p.N, p.E})
605+
if err != nil {
606+
return algo, asn1.BitString{}, err
607+
}
608+
pubKeyBytes = pubASN1
609+
bitLength = len(pubKeyBytes) * 8
610+
case *ecdsa.PublicKey:
611+
curveOID := asn1.ObjectIdentifier{1, 2, 840, 10045, 3, 1, 7} // secp256r1
612+
curveOIDBytes, _ := asn1.Marshal(curveOID)
613+
algo = pkix.AlgorithmIdentifier{
614+
Algorithm: asn1.ObjectIdentifier{1, 2, 840, 10045, 2, 1},
615+
Parameters: asn1.RawValue{
616+
FullBytes: curveOIDBytes,
617+
},
618+
}
619+
pubKeyBytes = ellipticMarshal(p.Curve, p.X, p.Y)
620+
bitLength = len(pubKeyBytes) * 8
621+
case *sm2.PublicKey:
622+
sm2OID := asn1.ObjectIdentifier{1, 2, 156, 10197, 1, 301, 1}
623+
sm2OIDBytes, _ := asn1.Marshal(sm2OID)
624+
algo = pkix.AlgorithmIdentifier{
625+
Algorithm: sm2OID,
626+
Parameters: asn1.RawValue{
627+
FullBytes: sm2OIDBytes,
628+
},
629+
}
630+
pubKeyBytes = ellipticMarshal(p.Curve, p.X, p.Y)
631+
bitLength = len(pubKeyBytes) * 8
632+
case *gost3410.PublicKey:
633+
gostOID := asn1.ObjectIdentifier{1, 2, 643, 7, 1, 1, 1, 1}
634+
gostOIDBytes, _ := asn1.Marshal(gostOID)
635+
algo = pkix.AlgorithmIdentifier{
636+
Algorithm: gostOID,
637+
Parameters: asn1.RawValue{FullBytes: gostOIDBytes},
638+
}
639+
pubKeyBytes = append([]byte{0x04}, p.X.Bytes()...)
640+
pubKeyBytes = append(pubKeyBytes, p.Y.Bytes()...)
641+
bitLength = len(pubKeyBytes) * 8
642+
default:
643+
return algo, asn1.BitString{}, fmt.Errorf("unsupported public key type: %T", pub)
644+
}
645+
return algo, asn1.BitString{Bytes: pubKeyBytes, BitLength: bitLength}, nil
646+
}
647+
648+
// ellipticMarshal — стандартная функция для маршалинга точки на кривой
649+
func ellipticMarshal(curve elliptic.Curve, x, y *big.Int) []byte {
650+
return append([]byte{0x04}, append(x.Bytes(), y.Bytes()...)...)
552651
}

connect_local.sh

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

3-
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 127.0.0.1 "
4+
openssl s_client -connect 127.0.0.1:443 -servername 127.0.0.1

run_vless_sm2.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ echo "🔧 Creating VLESS server configuration..."
2424
cat > vless_sm2.json << 'EOF'
2525
{
2626
"log": {
27-
"loglevel": "info"
27+
"loglevel": "debug"
2828
},
2929
"inbounds": [
3030
{

run_vmess_gost2012_512.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ echo "🔧 Creating VMess server configuration..."
2424
cat > vmess_gost2012_512.json << 'EOF'
2525
{
2626
"log": {
27-
"loglevel": "info"
27+
"loglevel": "debug"
2828
},
2929
"inbounds": [
3030
{

vless_sm2.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"log": {
3-
"loglevel": "info"
3+
"loglevel": "debug"
44
},
55
"inbounds": [
66
{

vmess_gost2012_512.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"log": {
3-
"loglevel": "info"
3+
"loglevel": "debug"
44
},
55
"inbounds": [
66
{
@@ -21,7 +21,8 @@
2121
"certificates": [
2222
{
2323
"certificateFile": "test_cert_gost2012_512.crt",
24-
"keyFile": "test_cert_gost2012_512.key"
24+
"keyFile": "test_cert_gost2012_512.key",
25+
"certificateType": "gost2012_512"
2526
}
2627
]
2728
}

0 commit comments

Comments
 (0)