gitee.com/zhaochuninhefei/gmgo@v0.0.31-0.20240209061119-069254a02979/sm4/sm4.go (about) 1 // Copyright (c) 2022 zhaochun 2 // gmgo is licensed under Mulan PSL v2. 3 // You can use this software according to the terms and conditions of the Mulan PSL v2. 4 // You may obtain a copy of Mulan PSL v2 at: 5 // http://license.coscl.org.cn/MulanPSL2 6 // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 7 // See the Mulan PSL v2 for more details. 8 9 package sm4 10 11 import ( 12 "crypto/cipher" 13 "crypto/rand" 14 "fmt" 15 "gitee.com/zhaochuninhefei/gmgo/utils" 16 "io" 17 ) 18 19 // Sm4EncryptCbc sm4加密,CBC模式 20 //goland:noinspection GoNameStartsWithPackageName 21 func Sm4EncryptCbc(plainData, key []byte) (iv, encryptData []byte, err error) { 22 block, err := NewCipher(key) 23 if err != nil { 24 return nil, nil, err 25 } 26 paddedData := utils.PKCS7Padding(plainData, BlockSize) 27 encryptData = make([]byte, len(paddedData)) 28 iv = make([]byte, BlockSize) 29 if _, err = io.ReadFull(rand.Reader, iv); err != nil { 30 return nil, nil, err 31 } 32 mode := cipher.NewCBCEncrypter(block, iv) 33 mode.CryptBlocks(encryptData, paddedData) 34 return 35 } 36 37 // Sm4EncryptCbcWithIV sm4加密,CBC模式,指定IV 38 //goland:noinspection GoNameStartsWithPackageName 39 func Sm4EncryptCbcWithIV(plainData, key, iv []byte) (encryptData []byte, err error) { 40 if len(iv) != BlockSize { 41 return nil, fmt.Errorf("sm4.Sm4EncryptCbcWithIV: iv长度不正确,不是Block字节数的长度. Block字节数: [%d]", BlockSize) 42 } 43 block, err := NewCipher(key) 44 if err != nil { 45 return nil, err 46 } 47 paddedData := utils.PKCS7Padding(plainData, BlockSize) 48 encryptData = make([]byte, len(paddedData)) 49 mode := cipher.NewCBCEncrypter(block, iv) 50 mode.CryptBlocks(encryptData, paddedData) 51 return 52 } 53 54 // Sm4DecryptCbc sm4解密,CBC模式 55 //goland:noinspection GoNameStartsWithPackageName 56 func Sm4DecryptCbc(encryptData, key, iv []byte) (plainData []byte, err error) { 57 block, err := NewCipher(key) 58 if err != nil { 59 return nil, err 60 } 61 // 长度检查 62 length := len(encryptData) 63 if length < BlockSize || length%BlockSize != 0 { 64 return nil, fmt.Errorf("sm4.Sm4DecryptCbc: 密文长度不正确,不是Block字节数的整数倍. Block字节数: [%d]", BlockSize) 65 } 66 paddedData := make([]byte, len(encryptData)) 67 mode := cipher.NewCBCDecrypter(block, iv) 68 mode.CryptBlocks(paddedData, encryptData) 69 plainData, err = utils.PKCS7UnPadding(paddedData, BlockSize) 70 if err != nil { 71 return nil, err 72 } 73 return 74 } 75 76 // Sm4EncryptCfb sm4加密,CFB模式 77 //goland:noinspection GoNameStartsWithPackageName 78 func Sm4EncryptCfb(plainData, key []byte) (iv, encryptData []byte, err error) { 79 block, err := NewCipher(key) 80 if err != nil { 81 return nil, nil, err 82 } 83 encryptData = make([]byte, len(plainData)) 84 iv = make([]byte, BlockSize) 85 if _, err = io.ReadFull(rand.Reader, iv); err != nil { 86 return nil, nil, err 87 } 88 mode := cipher.NewCFBEncrypter(block, iv) 89 mode.XORKeyStream(encryptData, plainData) 90 return 91 } 92 93 // Sm4DecryptCfb sm4解密,CFB模式 94 //goland:noinspection GoNameStartsWithPackageName 95 func Sm4DecryptCfb(encryptData, key, iv []byte) (plainData []byte, err error) { 96 block, err := NewCipher(key) 97 if err != nil { 98 return nil, err 99 } 100 plainData = make([]byte, len(encryptData)) 101 mode := cipher.NewCFBDecrypter(block, iv) 102 mode.XORKeyStream(plainData, encryptData) 103 return 104 } 105 106 // Sm4EncryptOfb sm4加密,OFB模式 107 //goland:noinspection GoNameStartsWithPackageName 108 func Sm4EncryptOfb(plainData, key []byte) (iv, encryptData []byte, err error) { 109 block, err := NewCipher(key) 110 if err != nil { 111 return nil, nil, err 112 } 113 encryptData = make([]byte, len(plainData)) 114 iv = make([]byte, BlockSize) 115 if _, err = io.ReadFull(rand.Reader, iv); err != nil { 116 return nil, nil, err 117 } 118 mode := cipher.NewOFB(block, iv) 119 mode.XORKeyStream(encryptData, plainData) 120 return 121 } 122 123 // Sm4DecryptOfb sm4解密,OFB模式 124 //goland:noinspection GoNameStartsWithPackageName 125 func Sm4DecryptOfb(encryptData, key, iv []byte) (plainData []byte, err error) { 126 block, err := NewCipher(key) 127 if err != nil { 128 return nil, err 129 } 130 plainData = make([]byte, len(encryptData)) 131 mode := cipher.NewOFB(block, iv) 132 mode.XORKeyStream(plainData, encryptData) 133 return 134 } 135 136 // Sm4EncryptGcm sm4加密,GCM模式 137 //goland:noinspection GoNameStartsWithPackageName 138 func Sm4EncryptGcm(plainData, key []byte) (nonce, encryptData []byte, err error) { 139 block, err := NewCipher(key) 140 if err != nil { 141 return nil, nil, err 142 } 143 sm4gcm, err := cipher.NewGCM(block) 144 if err != nil { 145 return nil, nil, err 146 } 147 nonce = make([]byte, sm4gcm.NonceSize()) 148 _, err = io.ReadFull(rand.Reader, nonce) 149 if err != nil { 150 return nil, nil, err 151 } 152 encryptData = sm4gcm.Seal(nil, nonce, plainData, nil) 153 return 154 } 155 156 // Sm4DecryptGcm sm4解密,GCM模式 157 //goland:noinspection GoNameStartsWithPackageName 158 func Sm4DecryptGcm(encryptData, key, nonce []byte) ([]byte, error) { 159 block, err := NewCipher(key) 160 if err != nil { 161 return nil, err 162 } 163 sm4gcm, err := cipher.NewGCM(block) 164 if err != nil { 165 return nil, err 166 } 167 // nonce, ciphertext := data[:sm4gcm.NonceSize()], data[sm4gcm.NonceSize():] 168 out, err := sm4gcm.Open(nil, nonce, encryptData, nil) 169 if err != nil { 170 return nil, err 171 } 172 return out, nil 173 } 174 175 // Sm4EncryptGcmWithNonce sm4加密,GCM模式 176 //goland:noinspection GoNameStartsWithPackageName 177 func Sm4EncryptGcmWithNonce(plainData, key, nonce, dst []byte) (encryptData []byte, err error) { 178 block, err := NewCipher(key) 179 if err != nil { 180 return nil, err 181 } 182 sm4gcm, err := cipher.NewGCM(block) 183 if err != nil { 184 return nil, err 185 } 186 out := sm4gcm.Seal(dst, nonce, plainData, dst) 187 encryptData = out[len(dst):] 188 return 189 } 190 191 // Sm4DecryptGcmWithNonce sm4解密,GCM模式 192 //goland:noinspection GoNameStartsWithPackageName 193 func Sm4DecryptGcmWithNonce(encryptData, key, nonce, dst []byte) ([]byte, error) { 194 block, err := NewCipher(key) 195 if err != nil { 196 return nil, err 197 } 198 sm4gcm, err := cipher.NewGCM(block) 199 if err != nil { 200 return nil, err 201 } 202 out, err := sm4gcm.Open(encryptData[:0], nonce, encryptData, dst) 203 if err != nil { 204 return nil, err 205 } 206 return out, nil 207 }