github.com/hxx258456/ccgo@v0.0.5-0.20230213014102-48b35f46f66f/sm4soft/utils.go (about)

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