gitee.com/ks-custle/core-gm@v0.0.0-20230922171213-b83bdd97b62c/x509/utils.go (about)

     1  // Copyright (c) 2022 zhaochun
     2  // core-gm is licensed under Mulan PSL v2.
     3  // You can use this software according to the terms and conditions of the Mulan PSL v2.
     4  // You may obtain a copy of Mulan PSL v2 at:
     5  //          http://license.coscl.org.cn/MulanPSL2
     6  // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
     7  // See the Mulan PSL v2 for more details.
     8  
     9  package x509
    10  
    11  /*
    12  x509/utils.go 提供gmx509常用操作的公开函数:
    13  ReadPrivateKeyFromPem : 将pem字节数组转为对应私钥
    14  ReadPrivateKeyFromPemFile : 将pem文件转为对应私钥
    15  WritePrivateKeyToPem : 将私钥转为pem字节数组
    16  WritePrivateKeytoPemFile : 将私钥转为pem文件
    17  ReadPublicKeyFromPem :  将pem字节数组转为对应公钥
    18  ReadPublicKeyFromPemFile : 将pem文件转为对应公钥
    19  WritePublicKeyToPem : 将公钥转为pem字节数组
    20  WritePublicKeytoPemFile : 将公钥转为pem文件
    21  ReadSm2PrivFromHex : 将hex字符串转为sm2私钥
    22  WriteSm2PrivToHex : 将sm2私钥D转为hex字符串
    23  ReadSm2PubFromHex : 将hex字符串转为sm2公钥
    24  WriteSm2PubToHex : 将sm2公钥转为hex字符串
    25  ReadCertificateRequestFromPem : 将pem字节数组转为证书申请
    26  ReadCertificateRequestFromPemFile : 将pem文件转为证书申请
    27  CreateCertificateRequestToPem : 创建证书申请并转为pem字节数组
    28  CreateCertificateRequestToPemFile : 创建证书申请并转为pem文件
    29  ReadCertificateFromPem : 将pem字节数组转为gmx509证书
    30  ReadCertificateFromPemFile : 将pem文件转为gmx509证书
    31  CreateCertificateToPem : 创建gmx509证书并转为pem字节数组
    32  CreateCertificateToPemFile : 创建gmx509证书并转为pem文件
    33  ParseGmx509DerToX509 : 将gmx509证书DER字节数组转为x509证书
    34  CreateEllipticSKI : 根据椭圆曲线公钥参数生成其SKI值
    35  GetRandBigInt : 随机生成序列号
    36  ReadKeyFromPem : 从pem读取对称加密密钥
    37  ReadKeyFromPemFile : 从pem文件读取对称加密密钥
    38  WriteKeyToPem : 将对称加密密钥写入pem
    39  WriteKeyToPemFile : 将对称加密密钥写入pem文件
    40  */
    41  
    42  import (
    43  	"crypto/ecdsa"
    44  	"crypto/ed25519"
    45  	"crypto/elliptic"
    46  	"crypto/rand"
    47  	"crypto/rsa"
    48  	"crypto/sha256"
    49  	"crypto/x509"
    50  	"encoding/pem"
    51  	"errors"
    52  	"fmt"
    53  	"gitee.com/ks-custle/core-gm/ecdsa_ext"
    54  	"io/ioutil"
    55  	"log"
    56  	"math/big"
    57  	"os"
    58  	"strings"
    59  
    60  	"gitee.com/ks-custle/core-gm/sm2"
    61  )
    62  
    63  // ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
    64  // 私钥与pem相互转换
    65  
    66  // ReadPrivateKeyFromPem 将pem字节数组转为对应私钥
    67  //   - 私钥类型: *sm2.PrivateKey, *rsa.PrivateKey, *ecdsa.PrivateKey, ed25519.PrivateKey
    68  //     @param privateKeyPem 私钥pem字节数组
    69  //     @param pwd pem解密口令
    70  //     @return interface{} 返回私钥
    71  //     @return error
    72  func ReadPrivateKeyFromPem(privateKeyPem []byte, pwd []byte) (interface{}, error) {
    73  	var block *pem.Block
    74  	block, _ = pem.Decode(privateKeyPem)
    75  	if block == nil {
    76  		return nil, errors.New("ReadPrivateKeyFromPem: pem decode failed")
    77  	}
    78  	blockType := strings.ToUpper(strings.TrimSpace(block.Type))
    79  	if block == nil || !strings.HasSuffix(blockType, "PRIVATE KEY") {
    80  		return nil, errors.New("failed to decode private key")
    81  	}
    82  	var der []byte
    83  	var err error
    84  	if pwd != nil {
    85  		der, err = DecryptPEMBlock(block, pwd)
    86  		if err != nil {
    87  			return nil, err
    88  		}
    89  	} else {
    90  		der = block.Bytes
    91  	}
    92  	privKey, err := ParsePKCS8PrivateKey(der)
    93  	if err != nil {
    94  		if err.Error() == ErrMsgUseParseECPrivateKey {
    95  			privKey, err = ParseECPrivateKey(der)
    96  		} else if err.Error() == ErrMsgUseParsePKCS1PrivateKey {
    97  			privKey, err = ParsePKCS1PrivateKey(der)
    98  		} else {
    99  			return nil, err
   100  		}
   101  	}
   102  	// 对于ECDSA_EXT,需要封装为`ecdsa_ext.PrivateKey`
   103  	if blockType == "ECDSA_EXT PRIVATE KEY" {
   104  		if priv, ok := privKey.(*ecdsa.PrivateKey); ok {
   105  			return &ecdsa_ext.PrivateKey{
   106  				PrivateKey: *priv,
   107  			}, nil
   108  		}
   109  	}
   110  	return privKey, err
   111  }
   112  
   113  // ReadPrivateKeyFromPemFile 将pem文件转为对应私钥
   114  //   - 私钥类型: *sm2.PrivateKey, *rsa.PrivateKey, *ecdsa.PrivateKey, ed25519.PrivateKey
   115  //     @param FileName pem文件路径
   116  //     @param pwd pem解密口令
   117  //     @return interface{} 返回私钥
   118  //     @return error
   119  func ReadPrivateKeyFromPemFile(FileName string, pwd []byte) (interface{}, error) {
   120  	data, err := ioutil.ReadFile(FileName)
   121  	if err != nil {
   122  		return nil, err
   123  	}
   124  	return ReadPrivateKeyFromPem(data, pwd)
   125  }
   126  
   127  // WritePrivateKeyToPem 将私钥转为pem字节数组
   128  //   - 私钥类型: *sm2.PrivateKey, *rsa.PrivateKey, *ecdsa.PrivateKey, ed25519.PrivateKey
   129  //     @param key 私钥
   130  //     @param pwd pem加密口令
   131  //     @return []byte 私钥pem字节数组
   132  //     @return error
   133  func WritePrivateKeyToPem(key interface{}, pwd []byte) ([]byte, error) {
   134  	var block *pem.Block
   135  	der, err := MarshalPKCS8PrivateKey(key)
   136  	if err != nil {
   137  		return nil, err
   138  	}
   139  	var pemType string
   140  	switch key.(type) {
   141  	case *sm2.PrivateKey:
   142  		pemType = "SM2 PRIVATE KEY"
   143  	case *ecdsa.PrivateKey:
   144  		pemType = "ECDSA PRIVATE KEY"
   145  	case *ecdsa_ext.PrivateKey:
   146  		pemType = "ECDSA_EXT PRIVATE KEY"
   147  	case ed25519.PrivateKey:
   148  		pemType = "ED25519 PRIVATE KEY"
   149  	case *rsa.PrivateKey:
   150  		pemType = "RSA PRIVATE KEY"
   151  	default:
   152  		return nil, fmt.Errorf("gmx509.WritePrivateKeyToPem : unsupported key: [%T]", key)
   153  	}
   154  	if pwd != nil {
   155  		block, err = EncryptPEMBlock(rand.Reader, "ENCRYPTED "+pemType, der, pwd, PEMCipherSM4)
   156  		if err != nil {
   157  			return nil, err
   158  		}
   159  	} else {
   160  		block = &pem.Block{
   161  			Type:  pemType,
   162  			Bytes: der,
   163  		}
   164  	}
   165  	certPem := pem.EncodeToMemory(block)
   166  	return certPem, nil
   167  }
   168  
   169  // WritePrivateKeytoPemFile 将私钥转为pem文件
   170  //   - 私钥类型: *sm2.PrivateKey, *rsa.PrivateKey, *ecdsa.PrivateKey, ed25519.PrivateKey
   171  //     @param FileName pem文件路径
   172  //     @param key 私钥
   173  //     @param pwd pem加密口令
   174  //     @return bool 成功与否
   175  //     @return error
   176  func WritePrivateKeytoPemFile(FileName string, key interface{}, pwd []byte) (bool, error) {
   177  	var block *pem.Block
   178  	der, err := MarshalPKCS8PrivateKey(key)
   179  	if err != nil {
   180  		return false, err
   181  	}
   182  	var pemType string
   183  	switch key.(type) {
   184  	case *sm2.PrivateKey:
   185  		pemType = "SM2 PRIVATE KEY"
   186  	case *ecdsa.PrivateKey:
   187  		pemType = "ECDSA PRIVATE KEY"
   188  	case *ecdsa_ext.PrivateKey:
   189  		pemType = "ECDSA_EXT PRIVATE KEY"
   190  	case ed25519.PrivateKey:
   191  		pemType = "ED25519 PRIVATE KEY"
   192  	case *rsa.PrivateKey:
   193  		pemType = "RSA PRIVATE KEY"
   194  	default:
   195  		return false, fmt.Errorf("gmx509.WritePrivateKeytoPemFile : unsupported key: [%T]", key)
   196  	}
   197  	if pwd != nil {
   198  		block, err = EncryptPEMBlock(rand.Reader, "ENCRYPTED "+pemType, der, pwd, PEMCipherSM4)
   199  		if err != nil {
   200  			return false, err
   201  		}
   202  	} else {
   203  		block = &pem.Block{
   204  			Type:  pemType,
   205  			Bytes: der,
   206  		}
   207  	}
   208  	file, err := os.Create(FileName)
   209  	if err != nil {
   210  		return false, err
   211  	}
   212  	defer func(file *os.File) {
   213  		err := file.Close()
   214  		if err != nil {
   215  			log.Fatal(err)
   216  		}
   217  	}(file)
   218  	err = pem.Encode(file, block)
   219  	if err != nil {
   220  		return false, err
   221  	}
   222  	return true, nil
   223  }
   224  
   225  // 私钥与pem相互转换
   226  // ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
   227  
   228  // ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
   229  // 公钥与pem相互转换
   230  
   231  // ReadPublicKeyFromPem 将pem字节数组转为对应公钥
   232  //   - 公钥类型: *sm2.PublicKey, *rsa.PublicKey, *dsa.PublicKey, *ecdsa.PublicKey, ed25519.PublicKey
   233  //     @param publicKeyPem
   234  //     @return interface{}
   235  //     @return error
   236  func ReadPublicKeyFromPem(publicKeyPem []byte) (interface{}, error) {
   237  	block, _ := pem.Decode(publicKeyPem)
   238  	if block == nil {
   239  		return nil, errors.New("ReadPublicKeyFromPem: pem decode failed")
   240  	}
   241  	blockType := strings.ToUpper(strings.TrimSpace(block.Type))
   242  	if block == nil || !strings.HasSuffix(blockType, "PUBLIC KEY") {
   243  		return nil, errors.New("failed to decode public key")
   244  	}
   245  	key, err := ParsePKIXPublicKey(block.Bytes)
   246  	if err != nil {
   247  		return nil, err
   248  	}
   249  	// 对于ECDSA_EXT需要包装为`ecdsa_ext.PublicKey`
   250  	if blockType == "ECDSA_EXT PUBLIC KEY" {
   251  		if pub, ok := key.(*ecdsa.PublicKey); ok {
   252  			return &ecdsa_ext.PublicKey{
   253  				PublicKey: *pub,
   254  			}, nil
   255  		}
   256  	}
   257  	return key, nil
   258  }
   259  
   260  // ReadPublicKeyFromPemFile 将pem文件转为对应公钥
   261  //   - 公钥类型: *sm2.PublicKey, *rsa.PublicKey, *dsa.PublicKey, *ecdsa.PublicKey, ed25519.PublicKey
   262  //     @param FileName
   263  //     @return interface{}
   264  //     @return error
   265  func ReadPublicKeyFromPemFile(FileName string) (interface{}, error) {
   266  	data, err := ioutil.ReadFile(FileName)
   267  	if err != nil {
   268  		return nil, err
   269  	}
   270  	return ReadPublicKeyFromPem(data)
   271  }
   272  
   273  // WritePublicKeyToPem 将公钥转为pem字节数组
   274  //
   275  //   - 公钥类型: *sm2.PublicKey, *rsa.PublicKey, *ecdsa.PublicKey, ed25519.PublicKey
   276  //
   277  //     @param key
   278  //     @return []byte
   279  //     @return error
   280  func WritePublicKeyToPem(key interface{}) ([]byte, error) {
   281  	der, err := MarshalPKIXPublicKey(key)
   282  	if err != nil {
   283  		return nil, err
   284  	}
   285  	var pemType string
   286  	switch key.(type) {
   287  	case *sm2.PublicKey:
   288  		pemType = "SM2 PUBLIC KEY"
   289  	case *ecdsa.PublicKey:
   290  		pemType = "ECDSA PUBLIC KEY"
   291  	case *ecdsa_ext.PublicKey:
   292  		pemType = "ECDSA_EXT PUBLIC KEY"
   293  	case ed25519.PublicKey:
   294  		pemType = "ED25519 PUBLIC KEY"
   295  	case *rsa.PublicKey:
   296  		pemType = "RSA PUBLIC KEY"
   297  	default:
   298  		return nil, fmt.Errorf("gmx509.WritePublicKeyToPem : unsupported key: [%T]", key)
   299  	}
   300  	block := &pem.Block{
   301  		Type:  pemType,
   302  		Bytes: der,
   303  	}
   304  	certPem := pem.EncodeToMemory(block)
   305  	return certPem, nil
   306  }
   307  
   308  // WritePublicKeytoPemFile 将公钥转为pem文件
   309  //
   310  //   - 公钥类型: *sm2.PublicKey, *rsa.PublicKey, *ecdsa.PublicKey, ed25519.PublicKey
   311  //
   312  //     @param FileName
   313  //     @param key
   314  //     @return bool
   315  //     @return error
   316  func WritePublicKeytoPemFile(FileName string, key interface{}) (bool, error) {
   317  	der, err := MarshalPKIXPublicKey(key)
   318  	if err != nil {
   319  		return false, err
   320  	}
   321  	var pemType string
   322  	switch key.(type) {
   323  	case *sm2.PublicKey:
   324  		pemType = "SM2 PUBLIC KEY"
   325  	case *ecdsa.PublicKey:
   326  		pemType = "ECDSA PUBLIC KEY"
   327  	case *ecdsa_ext.PublicKey:
   328  		pemType = "ECDSA_EXT PUBLIC KEY"
   329  	case ed25519.PublicKey:
   330  		pemType = "ED25519 PUBLIC KEY"
   331  	case *rsa.PublicKey:
   332  		pemType = "RSA PUBLIC KEY"
   333  	default:
   334  		return false, fmt.Errorf("gmx509.WritePublicKeytoPemFile : unsupported key: [%T]", key)
   335  	}
   336  	block := &pem.Block{
   337  		Type:  pemType,
   338  		Bytes: der,
   339  	}
   340  	file, err := os.Create(FileName)
   341  	if err != nil {
   342  		return false, err
   343  	}
   344  	defer func(file *os.File) {
   345  		err := file.Close()
   346  		if err != nil {
   347  			log.Fatal(err)
   348  		}
   349  	}(file)
   350  	err = pem.Encode(file, block)
   351  	if err != nil {
   352  		return false, err
   353  	}
   354  	return true, nil
   355  }
   356  
   357  // 公钥与pem相互转换
   358  // ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
   359  
   360  // ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
   361  // 证书申请与pem相互转换
   362  
   363  // ReadCertificateRequestFromPem 将pem字节数组转为证书申请
   364  //
   365  //	@param certPem
   366  //	@return *CertificateRequest
   367  //	@return error
   368  func ReadCertificateRequestFromPem(certPem []byte) (*CertificateRequest, error) {
   369  	block, _ := pem.Decode(certPem)
   370  	if block == nil {
   371  		return nil, errors.New("failed to decode certificate request")
   372  	}
   373  	return ParseCertificateRequest(block.Bytes)
   374  }
   375  
   376  // ReadCertificateRequestFromPemFile 将pem文件转为证书申请
   377  //
   378  //	@param FileName
   379  //	@return *CertificateRequest
   380  //	@return error
   381  func ReadCertificateRequestFromPemFile(FileName string) (*CertificateRequest, error) {
   382  	data, err := ioutil.ReadFile(FileName)
   383  	if err != nil {
   384  		return nil, err
   385  	}
   386  	return ReadCertificateRequestFromPem(data)
   387  }
   388  
   389  // CreateCertificateRequestToPem 创建证书申请并转为pem字节数组
   390  //
   391  //	@param template
   392  //	@param signer
   393  //	@return []byte
   394  //	@return error
   395  func CreateCertificateRequestToPem(template *CertificateRequest, signer interface{}) ([]byte, error) {
   396  	der, err := CreateCertificateRequest(rand.Reader, template, signer)
   397  	if err != nil {
   398  		return nil, err
   399  	}
   400  	block := &pem.Block{
   401  		Type:  "CERTIFICATE REQUEST",
   402  		Bytes: der,
   403  	}
   404  	certPem := pem.EncodeToMemory(block)
   405  	return certPem, nil
   406  }
   407  
   408  // CreateCertificateRequestToPemFile 创建证书申请并转为pem文件
   409  //
   410  //	@param FileName
   411  //	@param template
   412  //	@param signer
   413  //	@return bool
   414  //	@return error
   415  func CreateCertificateRequestToPemFile(FileName string, template *CertificateRequest, signer interface{}) (bool, error) {
   416  	der, err := CreateCertificateRequest(rand.Reader, template, signer)
   417  	if err != nil {
   418  		return false, err
   419  	}
   420  	block := &pem.Block{
   421  		Type:  "CERTIFICATE REQUEST",
   422  		Bytes: der,
   423  	}
   424  	file, err := os.Create(FileName)
   425  	if err != nil {
   426  		return false, err
   427  	}
   428  	defer func(file *os.File) {
   429  		err := file.Close()
   430  		if err != nil {
   431  			log.Fatal(err)
   432  		}
   433  	}(file)
   434  	err = pem.Encode(file, block)
   435  	if err != nil {
   436  		return false, err
   437  	}
   438  	return true, nil
   439  }
   440  
   441  // 证书申请与pem相互转换
   442  // ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
   443  
   444  // ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
   445  // gmx509证书与pem相互转换
   446  
   447  // ReadCertificateFromPem 将pem字节数组转为gmx509证书
   448  //
   449  //	@param certPem
   450  //	@return *Certificate
   451  //	@return error
   452  func ReadCertificateFromPem(certPem []byte) (*Certificate, error) {
   453  	block, _ := pem.Decode(certPem)
   454  	if block == nil {
   455  		return nil, errors.New("failed to decode certificate request")
   456  	}
   457  	return ParseCertificate(block.Bytes)
   458  }
   459  
   460  // ReadCertificateFromPemFile 将pem文件转为gmx509证书
   461  //
   462  //	@param FileName
   463  //	@return *Certificate
   464  //	@return error
   465  func ReadCertificateFromPemFile(FileName string) (*Certificate, error) {
   466  	data, err := ioutil.ReadFile(FileName)
   467  	if err != nil {
   468  		return nil, err
   469  	}
   470  	return ReadCertificateFromPem(data)
   471  }
   472  
   473  // CreateCertificateToPem 创建gmx509证书并转为pem字节数组
   474  //
   475  //	@param template
   476  //	@param parent
   477  //	@param pubKey
   478  //	@param signer
   479  //	@return []byte
   480  //	@return error
   481  func CreateCertificateToPem(template, parent *Certificate, pubKey, signer interface{}) ([]byte, error) {
   482  	der, err := CreateCertificate(rand.Reader, template, parent, pubKey, signer)
   483  	if err != nil {
   484  		return nil, err
   485  	}
   486  	block := &pem.Block{
   487  		Type:  "CERTIFICATE",
   488  		Bytes: der,
   489  	}
   490  	certPem := pem.EncodeToMemory(block)
   491  	return certPem, nil
   492  }
   493  
   494  // CreateCertificateToPemFile 创建gmx509证书并转为pem文件
   495  //
   496  //	@param FileName
   497  //	@param template
   498  //	@param parent
   499  //	@param pubKey
   500  //	@param privKey
   501  //	@return bool
   502  //	@return error
   503  func CreateCertificateToPemFile(FileName string, template, parent *Certificate, pubKey, privKey interface{}) (bool, error) {
   504  	der, err := CreateCertificate(rand.Reader, template, parent, pubKey, privKey)
   505  	if err != nil {
   506  		return false, err
   507  	}
   508  	block := &pem.Block{
   509  		Type:  "CERTIFICATE",
   510  		Bytes: der,
   511  	}
   512  	file, err := os.Create(FileName)
   513  	if err != nil {
   514  		return false, err
   515  	}
   516  	defer func(file *os.File) {
   517  		_ = file.Close()
   518  	}(file)
   519  	err = pem.Encode(file, block)
   520  	if err != nil {
   521  		return false, err
   522  	}
   523  	return true, nil
   524  }
   525  
   526  // WriteCertificateToPem 将x509证书转为pem字节数组
   527  //
   528  //	@param cert x509证书
   529  //	@return []byte pem字节数组
   530  //
   531  //goland:noinspection GoUnusedExportedFunction
   532  func WriteCertificateToPem(cert *Certificate) []byte {
   533  	block := &pem.Block{
   534  		Type:  "CERTIFICATE",
   535  		Bytes: cert.Raw,
   536  	}
   537  	certPem := pem.EncodeToMemory(block)
   538  	return certPem
   539  }
   540  
   541  // WriteCertificateToPemFile 将x509证书转为pem文件
   542  //
   543  //	@param path pem文件路径
   544  //	@param cert x509证书
   545  //	@return bool
   546  //	@return error
   547  //
   548  //goland:noinspection GoUnusedExportedFunction
   549  func WriteCertificateToPemFile(path string, cert *Certificate) (bool, error) {
   550  	block := &pem.Block{
   551  		Type:  "CERTIFICATE",
   552  		Bytes: cert.Raw,
   553  	}
   554  	file, err := os.Create(path)
   555  	if err != nil {
   556  		return false, err
   557  	}
   558  	defer func(file *os.File) {
   559  		_ = file.Close()
   560  	}(file)
   561  	err = pem.Encode(file, block)
   562  	if err != nil {
   563  		return false, err
   564  	}
   565  	return true, nil
   566  }
   567  
   568  // gmx509证书与pem相互转换
   569  // ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
   570  
   571  // ParseGmx509DerToX509 将gmx509证书DER字节数组转为x509证书
   572  //
   573  //	@param asn1data
   574  //	@return *x509.Certificate
   575  //	@return error
   576  //
   577  //goland:noinspection GoUnusedExportedFunction
   578  func ParseGmx509DerToX509(asn1data []byte) (*x509.Certificate, error) {
   579  	sm2Cert, err := ParseCertificate(asn1data)
   580  	if err != nil {
   581  		return nil, err
   582  	}
   583  	return sm2Cert.ToX509Certificate(), nil
   584  }
   585  
   586  // CreateEllipticSKI 根据椭圆曲线公钥参数生成其SKI值
   587  //
   588  //	@param curve
   589  //	@param x
   590  //	@param y
   591  //	@return []byte
   592  func CreateEllipticSKI(curve elliptic.Curve, x, y *big.Int) []byte {
   593  	if curve == nil {
   594  		return nil
   595  	}
   596  	//Marshall the public key
   597  	raw := elliptic.Marshal(curve, x, y)
   598  	// Hash it 计算ski一律使用SHA256
   599  	hash := sha256.New()
   600  	hash.Write(raw)
   601  	return hash.Sum(nil)
   602  }
   603  
   604  // ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
   605  // 对称加密密钥与pem相互转换
   606  
   607  // ReadKeyFromPem 从pem读取对称加密密钥
   608  func ReadKeyFromPem(data []byte, pwd []byte) ([]byte, error) {
   609  	block, _ := pem.Decode(data)
   610  	if block == nil {
   611  		return nil, errors.New("ReadKeyFromPem: pem decode failed")
   612  	}
   613  	blockType := strings.ToUpper(strings.TrimSpace(block.Type))
   614  	if IsEncryptedPEMBlock(block) {
   615  		if !strings.HasSuffix(blockType, "ENCRYPTED KEY") {
   616  			return nil, errors.New("ReadKeyFromPem: unknown type")
   617  		}
   618  		if len(pwd) == 0 {
   619  			return nil, errors.New("ReadKeyFromPem: need passwd")
   620  		}
   621  		data, err := DecryptPEMBlock(block, pwd)
   622  		if err != nil {
   623  			return nil, err
   624  		}
   625  		return data, nil
   626  	}
   627  	switch blockType {
   628  	case "KEY", "SM4 KEY", "AES KEY", "SYMMETRIC KEY":
   629  		return block.Bytes, nil
   630  	default:
   631  		return nil, errors.New("ReadKeyFromPem: unknown type")
   632  	}
   633  }
   634  
   635  // ReadKeyFromPemFile 从pem文件读取对称加密密钥
   636  func ReadKeyFromPemFile(FileName string, pwd []byte) ([]byte, error) {
   637  	data, err := ioutil.ReadFile(FileName)
   638  	if err != nil {
   639  		return nil, err
   640  	}
   641  	return ReadKeyFromPem(data, pwd)
   642  }
   643  
   644  // WriteKeyToPem 将对称加密密钥写入pem
   645  func WriteKeyToPem(key []byte, pwd []byte) ([]byte, error) {
   646  	var block *pem.Block
   647  	var err error
   648  	if pwd != nil {
   649  		block, err = EncryptPEMBlock(rand.Reader,
   650  			"SYMMETRIC ENCRYPTED KEY", key, pwd, PEMCipherAES256)
   651  	} else {
   652  		block = &pem.Block{
   653  			Type:  "SYMMETRIC KEY",
   654  			Bytes: key,
   655  		}
   656  	}
   657  	if err != nil {
   658  		return nil, err
   659  	}
   660  	return pem.EncodeToMemory(block), nil
   661  }
   662  
   663  // WriteKeyToPemFile 将对称加密密钥写入pem文件
   664  func WriteKeyToPemFile(FileName string, key []byte, pwd []byte) error {
   665  	pemBytes, err := WriteKeyToPem(key, pwd)
   666  	if err != nil {
   667  		return err
   668  	}
   669  	err = ioutil.WriteFile(FileName, pemBytes, 0666)
   670  	if err != nil {
   671  		return err
   672  	}
   673  	return nil
   674  }
   675  
   676  // 对称加密密钥与pem相互转换
   677  // ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑