gitee.com/lh-her-team/common@v1.5.1/crypto/sym/sm4/sm4.go (about)

     1  package sm4
     2  
     3  import (
     4  	"crypto/cipher"
     5  	"crypto/rand"
     6  	"encoding/hex"
     7  
     8  	"gitee.com/lh-her-team/common/crypto"
     9  	"gitee.com/lh-her-team/common/crypto/sym/modes"
    10  	"gitee.com/lh-her-team/common/crypto/sym/util"
    11  	"github.com/tjfoc/gmsm/sm4"
    12  )
    13  
    14  var defaultSM4Opts = &crypto.EncOpts{
    15  	EncodingType: modes.PADDING_NONE,
    16  	BlockMode:    modes.BLOCK_MODE_GCM,
    17  	EnableMAC:    true,
    18  	Hash:         0,
    19  	Label:        nil,
    20  	EnableASN1:   false,
    21  }
    22  
    23  type SM4Key struct {
    24  	Key []byte
    25  }
    26  
    27  func (sm4Key *SM4Key) Bytes() ([]byte, error) {
    28  	return sm4Key.Key, nil
    29  }
    30  
    31  func (sm4Key *SM4Key) String() (string, error) {
    32  	return hex.EncodeToString(sm4Key.Key), nil
    33  }
    34  
    35  func (sm4Key *SM4Key) Encrypt(plain []byte) ([]byte, error) {
    36  	return sm4Key.EncryptWithOpts(plain, defaultSM4Opts)
    37  }
    38  
    39  func (sm4Key *SM4Key) EncryptWithOpts(plain []byte, opts *crypto.EncOpts) ([]byte, error) {
    40  	// TODO implement different mode
    41  	block, err := sm4.NewCipher(sm4Key.Key)
    42  	if err != nil {
    43  		return nil, err
    44  	}
    45  	msg := util.PKCS5Padding(plain, block.BlockSize())
    46  	iv := make([]byte, block.BlockSize())
    47  	if _, err := rand.Read(iv); err != nil {
    48  		return nil, err
    49  	}
    50  	blockMode := cipher.NewCBCEncrypter(block, iv)
    51  	crypted := make([]byte, len(msg)+len(iv))
    52  	blockMode.CryptBlocks(crypted[block.BlockSize():], msg)
    53  	copy(crypted[0:block.BlockSize()], iv)
    54  	return crypted, nil
    55  }
    56  
    57  func (sm4Key *SM4Key) Decrypt(crypted []byte) ([]byte, error) {
    58  	return sm4Key.DecryptWithOpts(crypted, defaultSM4Opts)
    59  }
    60  
    61  func (sm4Key *SM4Key) DecryptWithOpts(crypted []byte, opts *crypto.EncOpts) ([]byte, error) {
    62  	// TODO implement different mode
    63  	block, err := sm4.NewCipher(sm4Key.Key)
    64  	if err != nil {
    65  		return nil, err
    66  	}
    67  	blockMode := cipher.NewCBCDecrypter(block, crypted[:block.BlockSize()])
    68  	orig := make([]byte, len(crypted)-block.BlockSize())
    69  	blockMode.CryptBlocks(orig, crypted[block.BlockSize():])
    70  	orig, err = util.PKCS5UnPadding(orig)
    71  	if err != nil {
    72  		return nil, err
    73  	}
    74  	return orig, nil
    75  }
    76  
    77  func (sm4Key *SM4Key) Type() crypto.KeyType {
    78  	return crypto.SM4
    79  }