gitee.com/zhaochuninhefei/gmgo@v0.0.31-0.20240209061119-069254a02979/x509/utils.go (about)

     1  // Copyright (c) 2022 zhaochun
     2  // gmgo 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/zhaochuninhefei/gmgo/ecdsa_ext"
    54  	"gitee.com/zhaochuninhefei/zcgolog/zclog"
    55  	"io/ioutil"
    56  	"math/big"
    57  	"os"
    58  	"strings"
    59  
    60  	"gitee.com/zhaochuninhefei/gmgo/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  			zclog.Errorln(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  //  - 公钥类型: *sm2.PublicKey, *rsa.PublicKey, *ecdsa.PublicKey, ed25519.PublicKey
   275  //
   276  //  @param key
   277  //  @return []byte
   278  //  @return error
   279  func WritePublicKeyToPem(key interface{}) ([]byte, error) {
   280  	der, err := MarshalPKIXPublicKey(key)
   281  	if err != nil {
   282  		return nil, err
   283  	}
   284  	var pemType string
   285  	switch key.(type) {
   286  	case *sm2.PublicKey:
   287  		pemType = "SM2 PUBLIC KEY"
   288  	case *ecdsa.PublicKey:
   289  		pemType = "ECDSA PUBLIC KEY"
   290  	case *ecdsa_ext.PublicKey:
   291  		pemType = "ECDSA_EXT PUBLIC KEY"
   292  	case ed25519.PublicKey:
   293  		pemType = "ED25519 PUBLIC KEY"
   294  	case *rsa.PublicKey:
   295  		pemType = "RSA PUBLIC KEY"
   296  	default:
   297  		return nil, fmt.Errorf("gmx509.WritePublicKeyToPem : unsupported key: [%T]", key)
   298  	}
   299  	block := &pem.Block{
   300  		Type:  pemType,
   301  		Bytes: der,
   302  	}
   303  	certPem := pem.EncodeToMemory(block)
   304  	return certPem, nil
   305  }
   306  
   307  // WritePublicKeytoPemFile 将公钥转为pem文件
   308  //  - 公钥类型: *sm2.PublicKey, *rsa.PublicKey, *ecdsa.PublicKey, ed25519.PublicKey
   309  //
   310  //  @param FileName
   311  //  @param key
   312  //  @return bool
   313  //  @return error
   314  func WritePublicKeytoPemFile(FileName string, key interface{}) (bool, error) {
   315  	der, err := MarshalPKIXPublicKey(key)
   316  	if err != nil {
   317  		return false, err
   318  	}
   319  	var pemType string
   320  	switch key.(type) {
   321  	case *sm2.PublicKey:
   322  		pemType = "SM2 PUBLIC KEY"
   323  	case *ecdsa.PublicKey:
   324  		pemType = "ECDSA PUBLIC KEY"
   325  	case *ecdsa_ext.PublicKey:
   326  		pemType = "ECDSA_EXT PUBLIC KEY"
   327  	case ed25519.PublicKey:
   328  		pemType = "ED25519 PUBLIC KEY"
   329  	case *rsa.PublicKey:
   330  		pemType = "RSA PUBLIC KEY"
   331  	default:
   332  		return false, fmt.Errorf("gmx509.WritePublicKeytoPemFile : unsupported key: [%T]", key)
   333  	}
   334  	block := &pem.Block{
   335  		Type:  pemType,
   336  		Bytes: der,
   337  	}
   338  	file, err := os.Create(FileName)
   339  	if err != nil {
   340  		return false, err
   341  	}
   342  	defer func(file *os.File) {
   343  		err := file.Close()
   344  		if err != nil {
   345  			zclog.Errorln(err)
   346  		}
   347  	}(file)
   348  	err = pem.Encode(file, block)
   349  	if err != nil {
   350  		return false, err
   351  	}
   352  	return true, nil
   353  }
   354  
   355  // 公钥与pem相互转换
   356  // ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
   357  
   358  // ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
   359  // 证书申请与pem相互转换
   360  
   361  // ReadCertificateRequestFromPem 将pem字节数组转为证书申请
   362  //
   363  //  @param certPem
   364  //  @return *CertificateRequest
   365  //  @return error
   366  func ReadCertificateRequestFromPem(certPem []byte) (*CertificateRequest, error) {
   367  	block, _ := pem.Decode(certPem)
   368  	if block == nil {
   369  		return nil, errors.New("failed to decode certificate request")
   370  	}
   371  	return ParseCertificateRequest(block.Bytes)
   372  }
   373  
   374  // ReadCertificateRequestFromPemFile 将pem文件转为证书申请
   375  //
   376  //  @param FileName
   377  //  @return *CertificateRequest
   378  //  @return error
   379  func ReadCertificateRequestFromPemFile(FileName string) (*CertificateRequest, error) {
   380  	data, err := ioutil.ReadFile(FileName)
   381  	if err != nil {
   382  		return nil, err
   383  	}
   384  	return ReadCertificateRequestFromPem(data)
   385  }
   386  
   387  // CreateCertificateRequestToPem 创建证书申请并转为pem字节数组
   388  //
   389  //  @param template
   390  //  @param signer
   391  //  @return []byte
   392  //  @return error
   393  func CreateCertificateRequestToPem(template *CertificateRequest, signer interface{}) ([]byte, error) {
   394  	der, err := CreateCertificateRequest(rand.Reader, template, signer)
   395  	if err != nil {
   396  		return nil, err
   397  	}
   398  	block := &pem.Block{
   399  		Type:  "CERTIFICATE REQUEST",
   400  		Bytes: der,
   401  	}
   402  	certPem := pem.EncodeToMemory(block)
   403  	return certPem, nil
   404  }
   405  
   406  // CreateCertificateRequestToPemFile 创建证书申请并转为pem文件
   407  //
   408  //  @param FileName
   409  //  @param template
   410  //  @param signer
   411  //  @return bool
   412  //  @return error
   413  func CreateCertificateRequestToPemFile(FileName string, template *CertificateRequest, signer interface{}) (bool, error) {
   414  	der, err := CreateCertificateRequest(rand.Reader, template, signer)
   415  	if err != nil {
   416  		return false, err
   417  	}
   418  	block := &pem.Block{
   419  		Type:  "CERTIFICATE REQUEST",
   420  		Bytes: der,
   421  	}
   422  	file, err := os.Create(FileName)
   423  	if err != nil {
   424  		return false, err
   425  	}
   426  	defer func(file *os.File) {
   427  		err := file.Close()
   428  		if err != nil {
   429  			zclog.Errorln(err)
   430  		}
   431  	}(file)
   432  	err = pem.Encode(file, block)
   433  	if err != nil {
   434  		return false, err
   435  	}
   436  	return true, nil
   437  }
   438  
   439  // 证书申请与pem相互转换
   440  // ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
   441  
   442  // ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
   443  // gmx509证书与pem相互转换
   444  
   445  // ReadCertificateFromPem 将pem字节数组转为gmx509证书
   446  //
   447  //  @param certPem
   448  //  @return *Certificate
   449  //  @return error
   450  func ReadCertificateFromPem(certPem []byte) (*Certificate, error) {
   451  	block, _ := pem.Decode(certPem)
   452  	if block == nil {
   453  		return nil, errors.New("failed to decode certificate request")
   454  	}
   455  	return ParseCertificate(block.Bytes)
   456  }
   457  
   458  // ReadCertificateFromPemFile 将pem文件转为gmx509证书
   459  //
   460  //  @param FileName
   461  //  @return *Certificate
   462  //  @return error
   463  func ReadCertificateFromPemFile(FileName string) (*Certificate, error) {
   464  	data, err := ioutil.ReadFile(FileName)
   465  	if err != nil {
   466  		return nil, err
   467  	}
   468  	return ReadCertificateFromPem(data)
   469  }
   470  
   471  // CreateCertificateToPem 创建gmx509证书并转为pem字节数组
   472  //
   473  //  @param template
   474  //  @param parent
   475  //  @param pubKey
   476  //  @param signer
   477  //  @return []byte
   478  //  @return error
   479  func CreateCertificateToPem(template, parent *Certificate, pubKey, signer interface{}) ([]byte, error) {
   480  	der, err := CreateCertificate(rand.Reader, template, parent, pubKey, signer)
   481  	if err != nil {
   482  		return nil, err
   483  	}
   484  	block := &pem.Block{
   485  		Type:  "CERTIFICATE",
   486  		Bytes: der,
   487  	}
   488  	certPem := pem.EncodeToMemory(block)
   489  	return certPem, nil
   490  }
   491  
   492  // CreateCertificateToPemFile 创建gmx509证书并转为pem文件
   493  //
   494  //  @param FileName
   495  //  @param template
   496  //  @param parent
   497  //  @param pubKey
   498  //  @param privKey
   499  //  @return bool
   500  //  @return error
   501  func CreateCertificateToPemFile(FileName string, template, parent *Certificate, pubKey, privKey interface{}) (bool, error) {
   502  	der, err := CreateCertificate(rand.Reader, template, parent, pubKey, privKey)
   503  	if err != nil {
   504  		return false, err
   505  	}
   506  	block := &pem.Block{
   507  		Type:  "CERTIFICATE",
   508  		Bytes: der,
   509  	}
   510  	file, err := os.Create(FileName)
   511  	if err != nil {
   512  		return false, err
   513  	}
   514  	defer func(file *os.File) {
   515  		_ = file.Close()
   516  	}(file)
   517  	err = pem.Encode(file, block)
   518  	if err != nil {
   519  		return false, err
   520  	}
   521  	return true, nil
   522  }
   523  
   524  // WriteCertificateToPem 将x509证书转为pem字节数组
   525  //  @param cert x509证书
   526  //  @return []byte pem字节数组
   527  //goland:noinspection GoUnusedExportedFunction
   528  func WriteCertificateToPem(cert *Certificate) []byte {
   529  	block := &pem.Block{
   530  		Type:  "CERTIFICATE",
   531  		Bytes: cert.Raw,
   532  	}
   533  	certPem := pem.EncodeToMemory(block)
   534  	return certPem
   535  }
   536  
   537  // WriteCertificateToPemFile 将x509证书转为pem文件
   538  //  @param path pem文件路径
   539  //  @param cert x509证书
   540  //  @return bool
   541  //  @return error
   542  //goland:noinspection GoUnusedExportedFunction
   543  func WriteCertificateToPemFile(path string, cert *Certificate) (bool, error) {
   544  	block := &pem.Block{
   545  		Type:  "CERTIFICATE",
   546  		Bytes: cert.Raw,
   547  	}
   548  	file, err := os.Create(path)
   549  	if err != nil {
   550  		return false, err
   551  	}
   552  	defer func(file *os.File) {
   553  		_ = file.Close()
   554  	}(file)
   555  	err = pem.Encode(file, block)
   556  	if err != nil {
   557  		return false, err
   558  	}
   559  	return true, nil
   560  }
   561  
   562  // gmx509证书与pem相互转换
   563  // ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
   564  
   565  // ParseGmx509DerToX509 将gmx509证书DER字节数组转为x509证书
   566  //
   567  //  @param asn1data
   568  //  @return *x509.Certificate
   569  //  @return error
   570  //goland:noinspection GoUnusedExportedFunction
   571  func ParseGmx509DerToX509(asn1data []byte) (*x509.Certificate, error) {
   572  	sm2Cert, err := ParseCertificate(asn1data)
   573  	if err != nil {
   574  		return nil, err
   575  	}
   576  	return sm2Cert.ToX509Certificate(), nil
   577  }
   578  
   579  // CreateEllipticSKI 根据椭圆曲线公钥参数生成其SKI值
   580  //
   581  //  @param curve
   582  //  @param x
   583  //  @param y
   584  //  @return []byte
   585  func CreateEllipticSKI(curve elliptic.Curve, x, y *big.Int) []byte {
   586  	if curve == nil {
   587  		return nil
   588  	}
   589  	//Marshall the public key
   590  	raw := elliptic.Marshal(curve, x, y)
   591  	// Hash it 计算ski一律使用SHA256
   592  	hash := sha256.New()
   593  	hash.Write(raw)
   594  	return hash.Sum(nil)
   595  }
   596  
   597  // ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
   598  // 对称加密密钥与pem相互转换
   599  
   600  // ReadKeyFromPem 从pem读取对称加密密钥
   601  func ReadKeyFromPem(data []byte, pwd []byte) ([]byte, error) {
   602  	block, _ := pem.Decode(data)
   603  	if block == nil {
   604  		return nil, errors.New("ReadKeyFromPem: pem decode failed")
   605  	}
   606  	blockType := strings.ToUpper(strings.TrimSpace(block.Type))
   607  	if IsEncryptedPEMBlock(block) {
   608  		if !strings.HasSuffix(blockType, "ENCRYPTED KEY") {
   609  			return nil, errors.New("ReadKeyFromPem: unknown type")
   610  		}
   611  		if len(pwd) == 0 {
   612  			return nil, errors.New("ReadKeyFromPem: need passwd")
   613  		}
   614  		data, err := DecryptPEMBlock(block, pwd)
   615  		if err != nil {
   616  			return nil, err
   617  		}
   618  		return data, nil
   619  	}
   620  	switch blockType {
   621  	case "KEY", "SM4 KEY", "AES KEY", "SYMMETRIC KEY":
   622  		return block.Bytes, nil
   623  	default:
   624  		return nil, errors.New("ReadKeyFromPem: unknown type")
   625  	}
   626  }
   627  
   628  // ReadKeyFromPemFile 从pem文件读取对称加密密钥
   629  func ReadKeyFromPemFile(FileName string, pwd []byte) ([]byte, error) {
   630  	data, err := ioutil.ReadFile(FileName)
   631  	if err != nil {
   632  		return nil, err
   633  	}
   634  	return ReadKeyFromPem(data, pwd)
   635  }
   636  
   637  // WriteKeyToPem 将对称加密密钥写入pem
   638  func WriteKeyToPem(key []byte, pwd []byte) ([]byte, error) {
   639  	var block *pem.Block
   640  	var err error
   641  	if pwd != nil {
   642  		block, err = EncryptPEMBlock(rand.Reader,
   643  			"SYMMETRIC ENCRYPTED KEY", key, pwd, PEMCipherAES256)
   644  	} else {
   645  		block = &pem.Block{
   646  			Type:  "SYMMETRIC KEY",
   647  			Bytes: key,
   648  		}
   649  	}
   650  	if err != nil {
   651  		return nil, err
   652  	}
   653  	return pem.EncodeToMemory(block), nil
   654  }
   655  
   656  // WriteKeyToPemFile 将对称加密密钥写入pem文件
   657  func WriteKeyToPemFile(FileName string, key []byte, pwd []byte) error {
   658  	pemBytes, err := WriteKeyToPem(key, pwd)
   659  	if err != nil {
   660  		return err
   661  	}
   662  	err = ioutil.WriteFile(FileName, pemBytes, 0666)
   663  	if err != nil {
   664  		return err
   665  	}
   666  	return nil
   667  }
   668  
   669  // 对称加密密钥与pem相互转换
   670  // ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑