gitee.com/ks-custle/core-gm@v0.0.0-20230922171213-b83bdd97b62c/sm4/sm4.go (about) 1 // Copyright (c) 2022 zhaochun 2 // core-gm 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/ks-custle/core-gm/utils" 16 "io" 17 ) 18 19 // Sm4EncryptCbc sm4加密,CBC模式 20 // 21 //goland:noinspection GoNameStartsWithPackageName 22 func Sm4EncryptCbc(plainData, key []byte) (iv, encryptData []byte, err error) { 23 block, err := NewCipher(key) 24 if err != nil { 25 return nil, nil, err 26 } 27 paddedData := utils.PKCS7Padding(plainData, BlockSize) 28 encryptData = make([]byte, len(paddedData)) 29 iv = make([]byte, BlockSize) 30 if _, err = io.ReadFull(rand.Reader, iv); err != nil { 31 return nil, nil, err 32 } 33 mode := cipher.NewCBCEncrypter(block, iv) 34 mode.CryptBlocks(encryptData, paddedData) 35 return 36 } 37 38 // Sm4DecryptCbc sm4解密,CBC模式 39 // 40 //goland:noinspection GoNameStartsWithPackageName 41 func Sm4DecryptCbc(encryptData, key, iv []byte) (plainData []byte, err error) { 42 block, err := NewCipher(key) 43 if err != nil { 44 return nil, err 45 } 46 // 长度检查 47 length := len(encryptData) 48 if length < BlockSize || length%BlockSize != 0 { 49 return nil, fmt.Errorf("sm4.Sm4DecryptCbc: 密文长度不正确,不是Block字节数的整数倍. Block字节数: [%d]", BlockSize) 50 } 51 paddedData := make([]byte, len(encryptData)) 52 mode := cipher.NewCBCDecrypter(block, iv) 53 mode.CryptBlocks(paddedData, encryptData) 54 plainData, err = utils.PKCS7UnPadding(paddedData, BlockSize) 55 if err != nil { 56 return nil, err 57 } 58 return 59 } 60 61 // Sm4EncryptCfb sm4加密,CFB模式 62 // 63 //goland:noinspection GoNameStartsWithPackageName 64 func Sm4EncryptCfb(plainData, key []byte) (iv, encryptData []byte, err error) { 65 block, err := NewCipher(key) 66 if err != nil { 67 return nil, nil, err 68 } 69 encryptData = make([]byte, len(plainData)) 70 iv = make([]byte, BlockSize) 71 if _, err = io.ReadFull(rand.Reader, iv); err != nil { 72 return nil, nil, err 73 } 74 mode := cipher.NewCFBEncrypter(block, iv) 75 mode.XORKeyStream(encryptData, plainData) 76 return 77 } 78 79 // Sm4DecryptCfb sm4解密,CFB模式 80 // 81 //goland:noinspection GoNameStartsWithPackageName 82 func Sm4DecryptCfb(encryptData, key, iv []byte) (plainData []byte, err error) { 83 block, err := NewCipher(key) 84 if err != nil { 85 return nil, err 86 } 87 plainData = make([]byte, len(encryptData)) 88 mode := cipher.NewCFBDecrypter(block, iv) 89 mode.XORKeyStream(plainData, encryptData) 90 return 91 } 92 93 // Sm4EncryptOfb sm4加密,OFB模式 94 // 95 //goland:noinspection GoNameStartsWithPackageName 96 func Sm4EncryptOfb(plainData, key []byte) (iv, encryptData []byte, err error) { 97 block, err := NewCipher(key) 98 if err != nil { 99 return nil, nil, err 100 } 101 encryptData = make([]byte, len(plainData)) 102 iv = make([]byte, BlockSize) 103 if _, err = io.ReadFull(rand.Reader, iv); err != nil { 104 return nil, nil, err 105 } 106 mode := cipher.NewOFB(block, iv) 107 mode.XORKeyStream(encryptData, plainData) 108 return 109 } 110 111 // Sm4DecryptOfb sm4解密,OFB模式 112 // 113 //goland:noinspection GoNameStartsWithPackageName 114 func Sm4DecryptOfb(encryptData, key, iv []byte) (plainData []byte, err error) { 115 block, err := NewCipher(key) 116 if err != nil { 117 return nil, err 118 } 119 plainData = make([]byte, len(encryptData)) 120 mode := cipher.NewOFB(block, iv) 121 mode.XORKeyStream(plainData, encryptData) 122 return 123 } 124 125 // Sm4EncryptGcm sm4加密,GCM模式 126 // 127 //goland:noinspection GoNameStartsWithPackageName 128 func Sm4EncryptGcm(plainData, key []byte) (nonce, encryptData []byte, err error) { 129 block, err := NewCipher(key) 130 if err != nil { 131 return nil, nil, err 132 } 133 sm4gcm, err := cipher.NewGCM(block) 134 if err != nil { 135 return nil, nil, err 136 } 137 nonce = make([]byte, sm4gcm.NonceSize()) 138 _, err = io.ReadFull(rand.Reader, nonce) 139 if err != nil { 140 return nil, nil, err 141 } 142 encryptData = sm4gcm.Seal(nil, nonce, plainData, nil) 143 return 144 } 145 146 // Sm4DecryptGcm sm4解密,GCM模式 147 // 148 //goland:noinspection GoNameStartsWithPackageName 149 func Sm4DecryptGcm(encryptData, key, nonce []byte) ([]byte, error) { 150 block, err := NewCipher(key) 151 if err != nil { 152 return nil, err 153 } 154 sm4gcm, err := cipher.NewGCM(block) 155 if err != nil { 156 return nil, err 157 } 158 // nonce, ciphertext := data[:sm4gcm.NonceSize()], data[sm4gcm.NonceSize():] 159 out, err := sm4gcm.Open(nil, nonce, encryptData, nil) 160 if err != nil { 161 return nil, err 162 } 163 return out, nil 164 } 165 166 // Sm4EncryptGcmWithNonce sm4加密,GCM模式 167 // 168 //goland:noinspection GoNameStartsWithPackageName 169 func Sm4EncryptGcmWithNonce(plainData, key, nonce, dst []byte) (encryptData []byte, err error) { 170 block, err := NewCipher(key) 171 if err != nil { 172 return nil, err 173 } 174 sm4gcm, err := cipher.NewGCM(block) 175 if err != nil { 176 return nil, err 177 } 178 out := sm4gcm.Seal(dst, nonce, plainData, dst) 179 encryptData = out[len(dst):] 180 return 181 } 182 183 // Sm4DecryptGcmWithNonce sm4解密,GCM模式 184 // 185 //goland:noinspection GoNameStartsWithPackageName 186 func Sm4DecryptGcmWithNonce(encryptData, key, nonce, dst []byte) ([]byte, error) { 187 block, err := NewCipher(key) 188 if err != nil { 189 return nil, err 190 } 191 sm4gcm, err := cipher.NewGCM(block) 192 if err != nil { 193 return nil, err 194 } 195 out, err := sm4gcm.Open(encryptData[:0], nonce, encryptData, dst) 196 if err != nil { 197 return nil, err 198 } 199 return out, nil 200 }