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

     1  package pkcs11
     2  
     3  import (
     4  	"crypto/rand"
     5  	"fmt"
     6  	"strconv"
     7  
     8  	"gitee.com/lh-her-team/common/crypto/hsm"
     9  
    10  	"gitee.com/lh-her-team/common/crypto/sym/util"
    11  
    12  	bccrypto "gitee.com/lh-her-team/common/crypto"
    13  	"gitee.com/lh-her-team/common/crypto/sym/modes"
    14  	"github.com/miekg/pkcs11"
    15  	"github.com/pkg/errors"
    16  )
    17  
    18  var defaultSM4Opts = &bccrypto.EncOpts{
    19  	EncodingType: modes.PADDING_PKCS5,
    20  	BlockMode:    modes.BLOCK_MODE_CBC,
    21  	EnableMAC:    true,
    22  	Hash:         0,
    23  	Label:        nil,
    24  	EnableASN1:   false,
    25  }
    26  
    27  var _ bccrypto.SymmetricKey = (*sm4Key)(nil)
    28  
    29  type sm4Key struct {
    30  	p11Ctx    *P11Handle
    31  	keyId     []byte
    32  	keyType   P11KeyType
    33  	keyObject pkcs11.ObjectHandle
    34  	blockSize int
    35  }
    36  
    37  func NewSM4Key(ctx *P11Handle, keyId []byte) (bccrypto.SymmetricKey, error) {
    38  	//find private key
    39  	id, err := strconv.Atoi(string(keyId))
    40  	if err != nil {
    41  		return nil, err
    42  	}
    43  	keyIdStr, err := hsm.GetHSMAdapter("").PKCS11_GetSM4KeyId(id)
    44  	if err != nil {
    45  		return nil, err
    46  	}
    47  	obj, err := ctx.findSecretKey([]byte(keyIdStr))
    48  	if err != nil {
    49  		return nil, fmt.Errorf("PKCS11 error: fail to find sm4 key [%s]", err)
    50  	}
    51  	return &sm4Key{
    52  		p11Ctx:    ctx,
    53  		keyId:     keyId,
    54  		keyObject: *obj,
    55  		keyType:   SM4,
    56  		blockSize: 16,
    57  	}, nil
    58  }
    59  
    60  func (s *sm4Key) Bytes() ([]byte, error) {
    61  	return s.keyId, nil
    62  }
    63  
    64  func (s *sm4Key) Type() bccrypto.KeyType {
    65  	return bccrypto.SM4
    66  }
    67  
    68  func (s *sm4Key) String() (string, error) {
    69  	return string(s.keyId), nil
    70  }
    71  
    72  func (s *sm4Key) Encrypt(plain []byte) ([]byte, error) {
    73  	return s.EncryptWithOpts(plain, defaultSM4Opts)
    74  }
    75  
    76  func (s *sm4Key) EncryptWithOpts(plain []byte, opts *bccrypto.EncOpts) ([]byte, error) {
    77  	iv := make([]byte, s.blockSize)
    78  	if _, err := rand.Read(iv); err != nil {
    79  		return nil, err
    80  	}
    81  	var cipherWithPad []byte
    82  	switch opts.BlockMode {
    83  	case modes.BLOCK_MODE_CBC:
    84  		switch opts.EncodingType {
    85  		case modes.PADDING_PKCS5:
    86  			plainWithPad := util.PKCS5Padding(plain, s.blockSize)
    87  			ciphertex, err := s.p11Ctx.Encrypt(s.keyObject, pkcs11.NewMechanism(CKM_SM4_CBC, iv), plainWithPad)
    88  			if err != nil {
    89  				return nil, err
    90  			}
    91  			cipherWithPad = append(iv, ciphertex...)
    92  		default:
    93  			return nil, fmt.Errorf("sm4 CBC encryption fails: invalid padding scheme [%s]", opts.EncodingType)
    94  		}
    95  	default:
    96  		return nil, fmt.Errorf("sm4 encryption fails: unknown cipher block mode [%s]", opts.BlockMode)
    97  	}
    98  	return cipherWithPad, nil
    99  }
   100  
   101  func (s *sm4Key) Decrypt(ciphertext []byte) ([]byte, error) {
   102  	return s.DecryptWithOpts(ciphertext, defaultSM4Opts)
   103  }
   104  
   105  func (s *sm4Key) DecryptWithOpts(ciphertext []byte, opts *bccrypto.EncOpts) ([]byte, error) {
   106  	if len(ciphertext) < s.blockSize {
   107  		return nil, errors.New("invalid ciphertext length")
   108  	}
   109  	var plain []byte
   110  	switch opts.BlockMode {
   111  	case modes.BLOCK_MODE_CBC:
   112  		switch opts.EncodingType {
   113  		case modes.PADDING_PKCS5:
   114  			iv := ciphertext[:s.blockSize]
   115  			out, err := s.p11Ctx.Decrypt(s.keyObject, pkcs11.NewMechanism(CKM_SM4_CBC, iv), ciphertext[s.blockSize:])
   116  			if err != nil {
   117  				return nil, fmt.Errorf("PKCS11 error: fail to encrypt [%s]", err)
   118  			}
   119  			plain, err = util.PKCS5UnPadding(out)
   120  			if err != nil {
   121  				return nil, err
   122  			}
   123  		default:
   124  			return nil, fmt.Errorf("sm4 CBC encryption fails: invalid padding scheme [%s]", opts.EncodingType)
   125  		}
   126  	default:
   127  		return nil, fmt.Errorf("sm4 encryption fails: unknown cipher block mode [%s]", opts.BlockMode)
   128  	}
   129  	return plain, nil
   130  }