github.com/bigzoro/my_simplechain@v0.0.0-20240315012955-8ad0a2a29bb9/core/access_contoller/crypto/pkcs11/sm4key.go (about)

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