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