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

     1  package sm4
     2  
     3  import (
     4  	"crypto/rand"
     5  	"encoding/hex"
     6  	"fmt"
     7  
     8  	"gitee.com/lh-her-team/common/opencrypto/gmssl/gmssl"
     9  
    10  	"gitee.com/lh-her-team/common/opencrypto/utils"
    11  
    12  	"gitee.com/lh-her-team/common/crypto"
    13  	"gitee.com/lh-her-team/common/crypto/sym/modes"
    14  )
    15  
    16  var defaultSM4Opts = &crypto.EncOpts{
    17  	EncodingType: modes.PADDING_PKCS5,
    18  	BlockMode:    modes.BLOCK_MODE_CBC,
    19  	EnableMAC:    true,
    20  	Hash:         0,
    21  	Label:        nil,
    22  	EnableASN1:   false,
    23  }
    24  
    25  var _ crypto.SymmetricKey = (*SM4Key)(nil)
    26  
    27  type SM4Key struct {
    28  	Key []byte
    29  }
    30  
    31  func (s SM4Key) Bytes() ([]byte, error) {
    32  	return s.Key, nil
    33  }
    34  
    35  func (s SM4Key) Type() crypto.KeyType {
    36  	return crypto.SM4
    37  }
    38  
    39  func (s SM4Key) String() (string, error) {
    40  	return hex.EncodeToString(s.Key), nil
    41  }
    42  
    43  func (s SM4Key) Encrypt(plain []byte) ([]byte, error) {
    44  	return s.EncryptWithOpts(plain, defaultSM4Opts)
    45  }
    46  
    47  func (s SM4Key) EncryptWithOpts(plain []byte, opts *crypto.EncOpts) ([]byte, error) {
    48  	switch opts.BlockMode {
    49  	case modes.BLOCK_MODE_CBC:
    50  		var iv [16]byte
    51  		if _, err := rand.Read(iv[:]); err != nil {
    52  			return nil, err
    53  		}
    54  		switch opts.EncodingType {
    55  		case modes.PADDING_PKCS5:
    56  			encrypter, err := gmssl.NewCipherContext("SMS4", s.Key, iv[:], true)
    57  			if err != nil {
    58  				return nil, err
    59  			}
    60  			cipher1, err := encrypter.Update(plain)
    61  			if err != nil {
    62  				return nil, err
    63  			}
    64  			cipher2, err := encrypter.Final()
    65  			if err != nil {
    66  				return nil, err
    67  			}
    68  			ciphertext := make([]byte, 0, len(cipher1)+len(cipher2))
    69  			ciphertext = append(append(ciphertext, cipher1...), cipher2...)
    70  			return append(iv[:], ciphertext...), nil
    71  		default:
    72  			return nil, fmt.Errorf("SM4 encryption fails, unknown encoding type [%s]", opts.EncodingType)
    73  		}
    74  	default:
    75  		return nil, fmt.Errorf("SM4 encryption fails: unknown cipher block mode [%s]", opts.BlockMode)
    76  	}
    77  }
    78  
    79  func (s SM4Key) Decrypt(ciphertext []byte) ([]byte, error) {
    80  	return s.DecryptWithOpts(ciphertext, defaultSM4Opts)
    81  }
    82  
    83  func (s SM4Key) DecryptWithOpts(ciphertext []byte, opts *crypto.EncOpts) ([]byte, error) {
    84  	switch opts.BlockMode {
    85  	case modes.BLOCK_MODE_CBC:
    86  		if len(ciphertext) < utils.SM4_BlockSize {
    87  			return nil, fmt.Errorf("invalid ciphertext length, want > 16, got %d", len(ciphertext))
    88  		}
    89  		switch opts.EncodingType {
    90  		case modes.PADDING_PKCS5:
    91  			decrypter, err := gmssl.NewCipherContext("SMS4", s.Key, ciphertext[:utils.SM4_BlockSize], false)
    92  			if err != nil {
    93  				return nil, err
    94  			}
    95  			plain1, err := decrypter.Update(ciphertext[utils.SM4_BlockSize:])
    96  			if err != nil {
    97  				return nil, err
    98  			}
    99  			plain2, err := decrypter.Final()
   100  			if err != nil {
   101  				return nil, err
   102  			}
   103  			plain := make([]byte, 0, len(plain1)+len(plain2))
   104  			plain = append(append(plain, plain1...), plain2...)
   105  			return plain, nil
   106  		default:
   107  			return nil, fmt.Errorf("SM4 encryption fails, unknown encoding type [%s]", opts.EncodingType)
   108  		}
   109  	default:
   110  		return nil, fmt.Errorf("SM4 encryption fails: unknown cipher block mode [%s]", opts.BlockMode)
   111  	}
   112  }