github.com/bigzoro/my_simplechain@v0.0.0-20240315012955-8ad0a2a29bb9/core/access_contoller/crypto/sdf/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 sdf 9 10 import ( 11 "crypto/rand" 12 "fmt" 13 "strconv" 14 15 "chainmaker.org/chainmaker/common/v2/crypto/sdf/base" 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/pkg/errors" 22 ) 23 24 const ( 25 BLOCK_MODE_ECB = "ECB" 26 BLOCK_MODE_CTR = "CTR" 27 ) 28 29 var defaultSM4Opts = &bccrypto.EncOpts{ 30 EncodingType: modes.PADDING_PKCS5, 31 BlockMode: BLOCK_MODE_ECB, 32 EnableMAC: true, 33 Hash: 0, 34 Label: nil, 35 EnableASN1: false, 36 } 37 38 var _ bccrypto.SymmetricKey = (*sm4Key)(nil) 39 40 type sm4Key struct { 41 sdfCtx *SDFHandle 42 keyId uint 43 keyPwd []byte 44 keyType SDFKeyType 45 blockSize int 46 47 keyHandle base.SessionHandle 48 } 49 50 func NewSecretKey(sdf *SDFHandle, keyId string, keyPwd []byte, tp bccrypto.KeyType) (bccrypto.SymmetricKey, error) { 51 if sdf == nil || len(keyId) == 0 { 52 return nil, errors.New("Invalid parameter, sdfHandle or keyId is nil") 53 } 54 55 //SM4 or AES 56 keyType := convertToSDFKeyType(tp) 57 58 //check keyId 59 keyIndex, err := strconv.Atoi(keyId) 60 if err != nil { 61 return nil, err 62 } 63 64 session, err := sdf.getSession() 65 if err != nil { 66 return nil, err 67 } 68 defer sdf.returnSession(err, session) 69 70 keyHandle, err := sdf.ctx.SDFGetSymmKeyHandle(session, uint(keyIndex)) 71 if err != nil { 72 return nil, errors.WithMessagef(err, "failed to get sym keyHandle, keyIndex = %d", keyIndex) 73 } 74 75 return &sm4Key{ 76 sdfCtx: sdf, 77 keyId: uint(keyIndex), 78 keyPwd: keyPwd, 79 keyType: keyType, 80 blockSize: 16, 81 82 keyHandle: keyHandle, 83 }, nil 84 } 85 86 func (s *sm4Key) Bytes() ([]byte, error) { 87 return []byte(fmt.Sprintf("%d", s.keyId)), nil 88 } 89 90 func (s *sm4Key) Type() bccrypto.KeyType { 91 return bccrypto.SM4 92 } 93 94 func (s *sm4Key) String() (string, error) { 95 return fmt.Sprintf("%d", s.keyId), nil 96 } 97 98 func (s *sm4Key) Encrypt(plain []byte) ([]byte, error) { 99 return s.EncryptWithOpts(plain, defaultSM4Opts) 100 } 101 102 func (s *sm4Key) EncryptWithOpts(plain []byte, opts *bccrypto.EncOpts) ([]byte, error) { 103 if opts == nil { 104 opts = defaultSM4Opts 105 } 106 iv := make([]byte, s.blockSize) 107 if _, err := rand.Read(iv); err != nil { 108 return nil, err 109 } 110 111 var cipherWithPad []byte 112 switch opts.BlockMode { 113 case modes.BLOCK_MODE_CBC: 114 switch opts.EncodingType { 115 case modes.PADDING_PKCS5: 116 plainWithPad := util.PKCS5Padding(plain, s.blockSize) 117 ciphertext, err := s.sdfCtx.SymEncrypt(s.keyHandle, base.SGD_SMS4_CBC, iv, plainWithPad) 118 if err != nil { 119 return nil, err 120 } 121 cipherWithPad = append(iv, ciphertext...) 122 default: 123 return nil, fmt.Errorf("sm4 CBC encryption fails: invalid padding scheme [%s]", opts.EncodingType) 124 } 125 case BLOCK_MODE_ECB: 126 plainWithPad := util.PKCS5Padding(plain, s.blockSize) 127 ciphertext, err := s.sdfCtx.SymEncrypt(s.keyHandle, base.SGD_SMS4_ECB, nil, plainWithPad) 128 if err != nil { 129 return nil, err 130 } 131 cipherWithPad = ciphertext 132 default: 133 return nil, fmt.Errorf("sm4 encryption fails: unknown cipher block mode [%s]", opts.BlockMode) 134 } 135 136 return cipherWithPad, nil 137 } 138 139 func (s *sm4Key) Decrypt(ciphertext []byte) ([]byte, error) { 140 return s.DecryptWithOpts(ciphertext, defaultSM4Opts) 141 } 142 143 func (s *sm4Key) DecryptWithOpts(ciphertext []byte, opts *bccrypto.EncOpts) ([]byte, error) { 144 if len(ciphertext) < s.blockSize { 145 return nil, errors.New("invalid ciphertext length") 146 } 147 if opts == nil { 148 opts = defaultSM4Opts 149 } 150 switch opts.BlockMode { 151 case modes.BLOCK_MODE_CBC: 152 switch opts.EncodingType { 153 case modes.PADDING_PKCS5: 154 iv := ciphertext[:s.blockSize] 155 out, err := s.sdfCtx.SymDecrypt(s.keyHandle, base.SGD_SMS4_CBC, iv, ciphertext[s.blockSize:]) 156 if err != nil { 157 return nil, err 158 } 159 return util.PKCS5UnPadding(out) 160 default: 161 return nil, fmt.Errorf("sm4 CBC encryption fails: invalid padding scheme [%s]", opts.EncodingType) 162 } 163 case BLOCK_MODE_ECB: 164 out, err := s.sdfCtx.SymDecrypt(s.keyHandle, base.SGD_SMS4_ECB, nil, ciphertext) 165 if err != nil { 166 return nil, err 167 } 168 return util.PKCS5UnPadding(out) 169 default: 170 return nil, fmt.Errorf("sm4 encryption fails: unknown cipher block mode [%s]", opts.BlockMode) 171 } 172 }