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 }