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

     1  /*
     2  Copyright (C) THL A29 Limited, a Tencent company. All rights reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package tencentcloudkms
     8  
     9  import (
    10  	"crypto"
    11  	"encoding/base64"
    12  	"fmt"
    13  
    14  	bccrypto "chainmaker.org/chainmaker/common/v2/crypto"
    15  	"chainmaker.org/chainmaker/common/v2/crypto/hash"
    16  	"chainmaker.org/chainmaker/common/v2/json"
    17  	"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
    18  	"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/errors"
    19  	kms "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/kms/v20190118"
    20  	"github.com/tjfoc/gmsm/sm2"
    21  	"github.com/tjfoc/gmsm/sm3"
    22  )
    23  
    24  type PrivateKey struct {
    25  	kms      *kms.Client
    26  	keyType  string
    27  	keyId    string
    28  	keyAlias string
    29  	pubKey   bccrypto.PublicKey
    30  }
    31  
    32  func (sk *PrivateKey) Type() bccrypto.KeyType {
    33  	return sk.PublicKey().Type()
    34  }
    35  
    36  func (sk *PrivateKey) Bytes() ([]byte, error) {
    37  	keyConfig := KMSPrivateKeyConfig{
    38  		KeyType:  sk.keyType,
    39  		KeyId:    sk.keyId,
    40  		KeyAlias: sk.keyAlias,
    41  	}
    42  	return json.Marshal(keyConfig)
    43  }
    44  
    45  func (sk *PrivateKey) String() (string, error) {
    46  	skBytes, err := sk.Bytes()
    47  	if err != nil {
    48  		return "", err
    49  	}
    50  	return string(skBytes), nil
    51  }
    52  
    53  func (sk *PrivateKey) PublicKey() bccrypto.PublicKey {
    54  	return sk.pubKey
    55  }
    56  
    57  func (sk *PrivateKey) Sign(data []byte) ([]byte, error) {
    58  	msgBase64 := base64.StdEncoding.EncodeToString(data)
    59  
    60  	request := kms.NewSignByAsymmetricKeyRequest()
    61  
    62  	request.Algorithm = common.StringPtr(sk.keyType)
    63  	request.MessageType = common.StringPtr(MODE_DIGEST)
    64  	request.KeyId = common.StringPtr(sk.keyId)
    65  	request.Message = common.StringPtr(msgBase64)
    66  
    67  	response, err := sk.kms.SignByAsymmetricKey(request)
    68  	if _, ok := err.(*errors.TencentCloudSDKError); ok {
    69  		return nil, fmt.Errorf("KMS API error: %s", err)
    70  	}
    71  	if err != nil {
    72  		return nil, err
    73  	}
    74  
    75  	sig, err := base64.StdEncoding.DecodeString(*(response.Response.Signature))
    76  	if err != nil {
    77  		return nil, err
    78  	}
    79  
    80  	return sig, nil
    81  }
    82  
    83  func (sk *PrivateKey) SignWithOpts(msg []byte, opts *bccrypto.SignOpts) ([]byte, error) {
    84  	if opts == nil {
    85  		return sk.Sign(msg)
    86  	}
    87  	if opts.Hash == bccrypto.HASH_TYPE_SM3 && sk.Type() == bccrypto.SM2 {
    88  		pkSM2, ok := sk.PublicKey().ToStandardKey().(*sm2.PublicKey)
    89  		if !ok {
    90  			return nil, fmt.Errorf("SM2 private key does not match the type it claims")
    91  		}
    92  		uid := opts.UID
    93  		if len(uid) == 0 {
    94  			uid = bccrypto.CRYPTO_DEFAULT_UID
    95  		}
    96  
    97  		za, err := sm2.ZA(pkSM2, []byte(uid))
    98  		if err != nil {
    99  			return nil, fmt.Errorf("PKCS11 error: fail to create SM3 digest for msg [%v]", err)
   100  		}
   101  		e := sm3.New()
   102  		e.Write(za)
   103  		e.Write(msg)
   104  		dgst := e.Sum(nil)[:32]
   105  
   106  		return sk.Sign(dgst)
   107  	}
   108  	dgst, err := hash.Get(opts.Hash, msg)
   109  	if err != nil {
   110  		return nil, err
   111  	}
   112  	return sk.Sign(dgst)
   113  }
   114  
   115  func (sk *PrivateKey) ToStandardKey() crypto.PrivateKey {
   116  	return &Signer{sk}
   117  }