gitee.com/ks-custle/core-gm@v0.0.0-20230922171213-b83bdd97b62c/sm4soft/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  /*
    10  sm4soft 是sm4的纯软实现,基于tjfoc国密算法库`tjfoc/gmsm`做了少量修改。
    11  对应版权声明: thrid_licenses/github.com/tjfoc/gmsm/版权声明
    12  */
    13  
    14  package sm4soft
    15  
    16  import (
    17  	"crypto/rand"
    18  	"encoding/pem"
    19  	"errors"
    20  	"io/ioutil"
    21  
    22  	gmx509 "gitee.com/ks-custle/core-gm/x509"
    23  )
    24  
    25  // ReadKeyFromPem will return SM4Key from PEM format data.
    26  func ReadKeyFromPem(data []byte, pwd []byte) (SM4Key, error) {
    27  	block, _ := pem.Decode(data)
    28  	if block == nil {
    29  		return nil, errors.New("SM4: pem decode failed")
    30  	}
    31  	if gmx509.IsEncryptedPEMBlock(block) {
    32  		if block.Type != "SM4 ENCRYPTED KEY" {
    33  			return nil, errors.New("SM4: unknown type")
    34  		}
    35  		if len(pwd) == 0 {
    36  			return nil, errors.New("SM4: need passwd")
    37  		}
    38  		data, err := gmx509.DecryptPEMBlock(block, pwd)
    39  		if err != nil {
    40  			return nil, err
    41  		}
    42  		return data, nil
    43  	}
    44  	if block.Type != "SM4 KEY" {
    45  		return nil, errors.New("SM4: unknown type")
    46  	}
    47  	return block.Bytes, nil
    48  }
    49  
    50  // ReadKeyFromPemFile will return SM4Key from filename that saved PEM format data.
    51  func ReadKeyFromPemFile(FileName string, pwd []byte) (SM4Key, error) {
    52  	data, err := ioutil.ReadFile(FileName)
    53  	if err != nil {
    54  		return nil, err
    55  	}
    56  	return ReadKeyFromPem(data, pwd)
    57  }
    58  
    59  // WriteKeyToPem will convert SM4Key to PEM format data and return it.
    60  //
    61  //goland:noinspection GoUnusedExportedFunction
    62  func WriteKeyToPem(key SM4Key, pwd []byte) ([]byte, error) {
    63  	if pwd != nil {
    64  		block, err := gmx509.EncryptPEMBlock(rand.Reader,
    65  			"SM4 ENCRYPTED KEY", key, pwd, gmx509.PEMCipherAES256) //Use AES256  algorithms to encrypt SM4KEY
    66  		if err != nil {
    67  			return nil, err
    68  		}
    69  		return pem.EncodeToMemory(block), nil
    70  	} else {
    71  		block := &pem.Block{
    72  			Type:  "SM4 KEY",
    73  			Bytes: key,
    74  		}
    75  		return pem.EncodeToMemory(block), nil
    76  	}
    77  }
    78  
    79  // WriteKeyToPemFile will convert SM4Key to PEM format data, then write it
    80  // into the input filename.
    81  func WriteKeyToPemFile(FileName string, key SM4Key, pwd []byte) error {
    82  	var block *pem.Block
    83  	var err error
    84  	if pwd != nil {
    85  		block, err = gmx509.EncryptPEMBlock(rand.Reader,
    86  			"SM4 ENCRYPTED KEY", key, pwd, gmx509.PEMCipherAES256)
    87  		if err != nil {
    88  			return err
    89  		}
    90  	} else {
    91  		block = &pem.Block{
    92  			Type:  "SM4 KEY",
    93  			Bytes: key,
    94  		}
    95  	}
    96  	pemBytes := pem.EncodeToMemory(block)
    97  	err = ioutil.WriteFile(FileName, pemBytes, 0666)
    98  	if err != nil {
    99  		return err
   100  	}
   101  	return nil
   102  }
   103  
   104  // WriteKeytoMem sm4密钥转为pem字节数组
   105  //
   106  //goland:noinspection GoUnusedExportedFunction
   107  func WriteKeytoMem(key SM4Key, pwd []byte) ([]byte, error) {
   108  	if pwd != nil {
   109  		block, err := gmx509.EncryptPEMBlock(rand.Reader,
   110  			"SM4 ENCRYPTED KEY", key, pwd, gmx509.PEMCipherAES256)
   111  		if err != nil {
   112  			return nil, err
   113  		}
   114  		return pem.EncodeToMemory(block), nil
   115  	} else {
   116  		block := &pem.Block{
   117  			Type:  "SM4 KEY",
   118  			Bytes: key,
   119  		}
   120  		return pem.EncodeToMemory(block), nil
   121  	}
   122  }
   123  
   124  // ReadKeyFromMem 将pem字节数组转为sm4密钥
   125  //
   126  //goland:noinspection GoUnusedExportedFunction
   127  func ReadKeyFromMem(data []byte, pwd []byte) (SM4Key, error) {
   128  	block, _ := pem.Decode(data)
   129  	if gmx509.IsEncryptedPEMBlock(block) {
   130  		if block.Type != "SM4 ENCRYPTED KEY" {
   131  			return nil, errors.New("SM4: unknown type")
   132  		}
   133  		if len(pwd) == 0 {
   134  			return nil, errors.New("SM4: need passwd")
   135  		}
   136  		data, err := gmx509.DecryptPEMBlock(block, pwd)
   137  		if err != nil {
   138  			return nil, err
   139  		}
   140  		return data, nil
   141  	}
   142  	if block.Type != "SM4 KEY" {
   143  		return nil, errors.New("SM4: unknown type")
   144  	}
   145  	return block.Bytes, nil
   146  }