@@ -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}
0 commit comments