github.com/emmansun/gmsm@v0.29.1/smx509/pkcs8.go (about)

     1  package smx509
     2  
     3  import (
     4  	"crypto/ecdsa"
     5  	"crypto/x509"
     6  	"crypto/x509/pkix"
     7  	"encoding/asn1"
     8  	"errors"
     9  
    10  	"github.com/emmansun/gmsm/ecdh"
    11  	"github.com/emmansun/gmsm/sm2"
    12  	"github.com/emmansun/gmsm/sm9"
    13  )
    14  
    15  var (
    16  	oidSM9     = asn1.ObjectIdentifier{1, 2, 156, 10197, 1, 302}
    17  	oidSM9Sign = asn1.ObjectIdentifier{1, 2, 156, 10197, 1, 302, 1}
    18  	oidSM9Enc  = asn1.ObjectIdentifier{1, 2, 156, 10197, 1, 302, 3}
    19  )
    20  
    21  // pkcs8 reflects an ASN.1, PKCS #8 PrivateKey. See
    22  // ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-8/pkcs-8v1_2.asn
    23  // and RFC 5208.
    24  type pkcs8 struct {
    25  	Version    int
    26  	Algo       pkix.AlgorithmIdentifier
    27  	PrivateKey []byte
    28  	// optional attributes omitted.
    29  }
    30  
    31  // ParsePKCS8PrivateKey parses an unencrypted private key in PKCS #8, ASN.1 DER form.
    32  //
    33  // It returns a *rsa.PrivateKey, a *ecdsa.PrivateKey, a *sm2.PrivateKey, a *sm9.SignMasterPrivateKey,
    34  // a *sm9.SignPrivateKey, a *sm9.EncryptMasterPrivateKey, a *sm9.EncryptPrivateKey or a ed25519.PrivateKey.
    35  // More types might be supported in the future.
    36  //
    37  // This kind of key is commonly encoded in PEM blocks of type "PRIVATE KEY".
    38  func ParsePKCS8PrivateKey(der []byte) (key any, err error) {
    39  	var privKey pkcs8
    40  	if _, err := asn1.Unmarshal(der, &privKey); err != nil {
    41  		if _, err := asn1.Unmarshal(der, &ecPrivateKey{}); err == nil {
    42  			return nil, errors.New("x509: failed to parse private key (use ParseECPrivateKey instead for this key format)")
    43  		}
    44  		if _, err := asn1.Unmarshal(der, &pkcs1PrivateKey{}); err == nil {
    45  			return nil, errors.New("x509: failed to parse private key (use ParsePKCS1PrivateKey instead for this key format)")
    46  		}
    47  		return nil, err
    48  	}
    49  	switch {
    50  	case privKey.Algo.Algorithm.Equal(oidPublicKeySM2):
    51  		bytes := privKey.Algo.Parameters.FullBytes
    52  		namedCurveOID := new(asn1.ObjectIdentifier)
    53  		if _, err := asn1.Unmarshal(bytes, namedCurveOID); err != nil {
    54  			namedCurveOID = nil
    55  		}
    56  		ecKey, err := parseECPrivateKey(namedCurveOID, privKey.PrivateKey)
    57  		if err != nil {
    58  			return nil, errors.New("x509: failed to parse SM2 private key embedded in PKCS#8: " + err.Error())
    59  		}
    60  		if ecKey.Curve != sm2.P256() {
    61  			return nil, errors.New("x509: unsupported SM2 curve")
    62  		}
    63  		return new(sm2.PrivateKey).FromECPrivateKey(ecKey)
    64  	case privKey.Algo.Algorithm.Equal(oidSM9), privKey.Algo.Algorithm.Equal(oidSM9Sign), privKey.Algo.Algorithm.Equal(oidSM9Enc):
    65  		return parseSM9PrivateKey(privKey)
    66  	case privKey.Algo.Algorithm.Equal(oidPublicKeyECDSA):
    67  		bytes := privKey.Algo.Parameters.FullBytes
    68  		namedCurveOID := new(asn1.ObjectIdentifier)
    69  		if _, err := asn1.Unmarshal(bytes, namedCurveOID); err != nil {
    70  			namedCurveOID = nil
    71  		}
    72  		ecKey, err := parseECPrivateKey(namedCurveOID, privKey.PrivateKey)
    73  		if err != nil {
    74  			return nil, errors.New("x509: failed to parse EC private key embedded in PKCS#8: " + err.Error())
    75  		}
    76  		// convert *ecdsa.PrivateKey to *sm2.PrivateKey
    77  		if ecKey.Curve == sm2.P256() {
    78  			return new(sm2.PrivateKey).FromECPrivateKey(ecKey)
    79  		}
    80  		return ecKey, err
    81  	default:
    82  		// fallback to golang sdk
    83  		return x509.ParsePKCS8PrivateKey(der)
    84  	}
    85  }
    86  
    87  func parseSM9PrivateKey(privKey pkcs8) (key any, err error) {
    88  	switch {
    89  	case privKey.Algo.Algorithm.Equal(oidSM9Sign):
    90  		sm9SignKey := new(sm9.SignPrivateKey)
    91  		err = sm9SignKey.UnmarshalASN1(privKey.PrivateKey)
    92  		if err != nil {
    93  			return
    94  		}
    95  		key = sm9SignKey
    96  		return
    97  	case privKey.Algo.Algorithm.Equal(oidSM9Enc):
    98  		sm9EncKey := new(sm9.EncryptPrivateKey)
    99  		err = sm9EncKey.UnmarshalASN1(privKey.PrivateKey)
   100  		if err != nil {
   101  			return
   102  		}
   103  		key = sm9EncKey
   104  		return
   105  	default:
   106  		bytes := privKey.Algo.Parameters.FullBytes
   107  		detailOID := new(asn1.ObjectIdentifier)
   108  		_, err = asn1.Unmarshal(bytes, detailOID)
   109  		if err != nil {
   110  			return
   111  		}
   112  		switch {
   113  		case oidSM9Sign.Equal(*detailOID):
   114  			sm9SignMasterKey := new(sm9.SignMasterPrivateKey)
   115  			err = sm9SignMasterKey.UnmarshalASN1(privKey.PrivateKey)
   116  			if err != nil {
   117  				return
   118  			}
   119  			key = sm9SignMasterKey
   120  			return
   121  		case oidSM9Enc.Equal(*detailOID):
   122  			sm9EncMasterKey := new(sm9.EncryptMasterPrivateKey)
   123  			err = sm9EncMasterKey.UnmarshalASN1(privKey.PrivateKey)
   124  			if err != nil {
   125  				return
   126  			}
   127  			key = sm9EncMasterKey
   128  			return
   129  		}
   130  		return nil, errors.New("not support yet")
   131  	}
   132  }
   133  
   134  // MarshalPKCS8PrivateKey converts a private key to PKCS #8, ASN.1 DER form.
   135  //
   136  // The following key types are currently supported: *rsa.PrivateKey, *ecdsa.PrivateKey, a *sm2.PrivateKey, a *ecdh.PrivateKey
   137  // a *sm9.SignMasterPrivateKey, a *sm9.SignPrivateKey, a *sm9.EncryptMasterPrivateKey, a *sm9.EncryptPrivateKey
   138  // and ed25519.PrivateKey. Unsupported key types result in an error.
   139  //
   140  // This kind of key is commonly encoded in PEM blocks of type "PRIVATE KEY".
   141  func MarshalPKCS8PrivateKey(key any) ([]byte, error) {
   142  	switch k := key.(type) {
   143  	case *sm2.PrivateKey:
   144  		return marshalPKCS8ECPrivateKey(&k.PrivateKey)
   145  	case *ecdh.PrivateKey:
   146  		return marshalPKCS8ECDHPrivateKey(k)
   147  	case *sm9.SignPrivateKey:
   148  		return marshalPKCS8SM9SignPrivateKey(k)
   149  	case *sm9.EncryptPrivateKey:
   150  		return marshalPKCS8SM9EncPrivateKey(k)
   151  	case *sm9.SignMasterPrivateKey:
   152  		return marshalPKCS8SM9SignMasterPrivateKey(k)
   153  	case *sm9.EncryptMasterPrivateKey:
   154  		return marshalPKCS8SM9EncMasterPrivateKey(k)
   155  	}
   156  	return x509.MarshalPKCS8PrivateKey(key)
   157  }
   158  
   159  type sm9PrivateKey struct {
   160  	PrivateKey asn1.RawValue
   161  	PublicKey  asn1.RawValue
   162  }
   163  
   164  func marshalPKCS8SM9SignPrivateKey(k *sm9.SignPrivateKey) ([]byte, error) {
   165  	var privKey pkcs8
   166  	privKey.Algo = pkix.AlgorithmIdentifier{
   167  		Algorithm:  oidSM9Sign,
   168  		Parameters: asn1.NullRawValue,
   169  	}
   170  
   171  	key := sm9PrivateKey{}
   172  	privans1, err := k.MarshalASN1()
   173  	if err != nil {
   174  		return nil, err
   175  	}
   176  	pubasn1, err := k.MasterPublic().MarshalASN1()
   177  	if err != nil {
   178  		return nil, err
   179  	}
   180  	key.PrivateKey.FullBytes = privans1
   181  	key.PublicKey.FullBytes = pubasn1
   182  
   183  	if privKey.PrivateKey, err = asn1.Marshal(key); err != nil {
   184  		return nil, errors.New("x509: failed to marshal sm9 sign private key while building PKCS#8: " + err.Error())
   185  	}
   186  	return asn1.Marshal(privKey)
   187  }
   188  
   189  func marshalPKCS8SM9EncPrivateKey(k *sm9.EncryptPrivateKey) ([]byte, error) {
   190  	var privKey pkcs8
   191  	privKey.Algo = pkix.AlgorithmIdentifier{
   192  		Algorithm:  oidSM9Enc,
   193  		Parameters: asn1.NullRawValue,
   194  	}
   195  	key := sm9PrivateKey{}
   196  	privans1, err := k.MarshalASN1()
   197  	if err != nil {
   198  		return nil, err
   199  	}
   200  	pubasn1, err := k.MasterPublic().MarshalASN1()
   201  	if err != nil {
   202  		return nil, err
   203  	}
   204  	key.PrivateKey.FullBytes = privans1
   205  	key.PublicKey.FullBytes = pubasn1
   206  
   207  	if privKey.PrivateKey, err = asn1.Marshal(key); err != nil {
   208  		return nil, errors.New("x509: failed to marshal sm9 encrypt private key while building PKCS#8: " + err.Error())
   209  	}
   210  	return asn1.Marshal(privKey)
   211  }
   212  
   213  func marshalPKCS8SM9SignMasterPrivateKey(k *sm9.SignMasterPrivateKey) ([]byte, error) {
   214  	var privKey pkcs8
   215  	oidBytes, err := asn1.Marshal(oidSM9Sign)
   216  	if err != nil {
   217  		return nil, errors.New("x509: failed to marshal SM9 OID: " + err.Error())
   218  	}
   219  
   220  	privKey.Algo = pkix.AlgorithmIdentifier{
   221  		Algorithm: oidSM9,
   222  		Parameters: asn1.RawValue{
   223  			FullBytes: oidBytes,
   224  		},
   225  	}
   226  
   227  	key := sm9PrivateKey{}
   228  	privans1, err := k.MarshalASN1()
   229  	if err != nil {
   230  		return nil, err
   231  	}
   232  	pubasn1, err := k.Public().MarshalASN1()
   233  	if err != nil {
   234  		return nil, err
   235  	}
   236  	key.PrivateKey.FullBytes = privans1
   237  	key.PublicKey.FullBytes = pubasn1
   238  
   239  	if privKey.PrivateKey, err = asn1.Marshal(key); err != nil {
   240  		return nil, errors.New("x509: failed to marshal sm9 sign master private key while building PKCS#8: " + err.Error())
   241  	}
   242  	return asn1.Marshal(privKey)
   243  }
   244  
   245  func marshalPKCS8SM9EncMasterPrivateKey(k *sm9.EncryptMasterPrivateKey) ([]byte, error) {
   246  	var privKey pkcs8
   247  	oidBytes, err := asn1.Marshal(oidSM9Enc)
   248  	if err != nil {
   249  		return nil, errors.New("x509: failed to marshal SM9 OID: " + err.Error())
   250  	}
   251  
   252  	privKey.Algo = pkix.AlgorithmIdentifier{
   253  		Algorithm: oidSM9,
   254  		Parameters: asn1.RawValue{
   255  			FullBytes: oidBytes,
   256  		},
   257  	}
   258  
   259  	key := sm9PrivateKey{}
   260  	privans1, err := k.MarshalASN1()
   261  	if err != nil {
   262  		return nil, err
   263  	}
   264  	pubasn1, err := k.Public().MarshalASN1()
   265  	if err != nil {
   266  		return nil, err
   267  	}
   268  	key.PrivateKey.FullBytes = privans1
   269  	key.PublicKey.FullBytes = pubasn1
   270  
   271  	if privKey.PrivateKey, err = asn1.Marshal(key); err != nil {
   272  		return nil, errors.New("x509: failed to marshal sm9 encrypt master private key while building PKCS#8: " + err.Error())
   273  	}
   274  	return asn1.Marshal(privKey)
   275  }
   276  
   277  func marshalPKCS8ECPrivateKey(k *ecdsa.PrivateKey) ([]byte, error) {
   278  	var privKey pkcs8
   279  	oid, ok := oidFromNamedCurve(k.Curve)
   280  	if !ok {
   281  		return nil, errors.New("x509: unknown curve while marshaling to PKCS#8")
   282  	}
   283  
   284  	oidBytes, err := asn1.Marshal(oid)
   285  	if err != nil {
   286  		return nil, errors.New("x509: failed to marshal curve OID: " + err.Error())
   287  	}
   288  
   289  	privKey.Algo = pkix.AlgorithmIdentifier{
   290  		Algorithm: oidPublicKeyECDSA,
   291  		Parameters: asn1.RawValue{
   292  			FullBytes: oidBytes,
   293  		},
   294  	}
   295  
   296  	if privKey.PrivateKey, err = marshalECPrivateKeyWithOID(k, nil); err != nil {
   297  		return nil, errors.New("x509: failed to marshal EC private key while building PKCS#8: " + err.Error())
   298  	}
   299  	return asn1.Marshal(privKey)
   300  }
   301  
   302  func marshalPKCS8ECDHPrivateKey(k *ecdh.PrivateKey) ([]byte, error) {
   303  	var privKey pkcs8
   304  	oid, ok := oidFromECDHCurve(k.Curve())
   305  	if !ok {
   306  		return nil, errors.New("x509: unknown curve while marshaling to PKCS#8")
   307  	}
   308  	oidBytes, err := asn1.Marshal(oid)
   309  	if err != nil {
   310  		return nil, errors.New("x509: failed to marshal curve OID: " + err.Error())
   311  	}
   312  	privKey.Algo = pkix.AlgorithmIdentifier{
   313  		Algorithm: oidPublicKeyECDSA,
   314  		Parameters: asn1.RawValue{
   315  			FullBytes: oidBytes,
   316  		},
   317  	}
   318  	if privKey.PrivateKey, err = marshalECDHPrivateKey(k); err != nil {
   319  		return nil, errors.New("x509: failed to marshal EC private key while building PKCS#8: " + err.Error())
   320  	}
   321  	return asn1.Marshal(privKey)
   322  }