github.com/wangyougui/gf/v2@v2.6.5/crypto/gdes/gdes.go (about) 1 // Copyright GoFrame Author(https://goframe.org). All Rights Reserved. 2 // 3 // This Source Code Form is subject to the terms of the MIT License. 4 // If a copy of the MIT was not distributed with this file, 5 // You can obtain one at https://github.com/wangyougui/gf. 6 7 // Package gdes provides useful API for DES encryption/decryption algorithms. 8 package gdes 9 10 import ( 11 "bytes" 12 "crypto/cipher" 13 "crypto/des" 14 15 "github.com/wangyougui/gf/v2/errors/gcode" 16 "github.com/wangyougui/gf/v2/errors/gerror" 17 ) 18 19 const ( 20 NOPADDING = iota 21 PKCS5PADDING 22 ) 23 24 // EncryptECB encrypts `plainText` using ECB mode. 25 func EncryptECB(plainText []byte, key []byte, padding int) ([]byte, error) { 26 text, err := Padding(plainText, padding) 27 if err != nil { 28 return nil, err 29 } 30 31 cipherText := make([]byte, len(text)) 32 block, err := des.NewCipher(key) 33 if err != nil { 34 err = gerror.WrapCodef(gcode.CodeInvalidParameter, err, `des.NewCipher failed for key "%s"`, key) 35 return nil, err 36 } 37 38 blockSize := block.BlockSize() 39 for i, count := 0, len(text)/blockSize; i < count; i++ { 40 begin, end := i*blockSize, i*blockSize+blockSize 41 block.Encrypt(cipherText[begin:end], text[begin:end]) 42 } 43 return cipherText, nil 44 } 45 46 // DecryptECB decrypts `cipherText` using ECB mode. 47 func DecryptECB(cipherText []byte, key []byte, padding int) ([]byte, error) { 48 text := make([]byte, len(cipherText)) 49 block, err := des.NewCipher(key) 50 if err != nil { 51 err = gerror.WrapCodef(gcode.CodeInvalidParameter, err, `des.NewCipher failed for key "%s"`, key) 52 return nil, err 53 } 54 55 blockSize := block.BlockSize() 56 for i, count := 0, len(text)/blockSize; i < count; i++ { 57 begin, end := i*blockSize, i*blockSize+blockSize 58 block.Decrypt(text[begin:end], cipherText[begin:end]) 59 } 60 61 plainText, err := UnPadding(text, padding) 62 if err != nil { 63 return nil, err 64 } 65 return plainText, nil 66 } 67 68 // EncryptECBTriple encrypts `plainText` using TripleDES and ECB mode. 69 // The length of the `key` should be either 16 or 24 bytes. 70 func EncryptECBTriple(plainText []byte, key []byte, padding int) ([]byte, error) { 71 if len(key) != 16 && len(key) != 24 { 72 return nil, gerror.NewCode(gcode.CodeInvalidParameter, "key length error") 73 } 74 75 text, err := Padding(plainText, padding) 76 if err != nil { 77 return nil, err 78 } 79 80 var newKey []byte 81 if len(key) == 16 { 82 newKey = append([]byte{}, key...) 83 newKey = append(newKey, key[:8]...) 84 } else { 85 newKey = append([]byte{}, key...) 86 } 87 88 block, err := des.NewTripleDESCipher(newKey) 89 if err != nil { 90 err = gerror.WrapCodef(gcode.CodeInvalidParameter, err, `des.NewTripleDESCipher failed for key "%s"`, newKey) 91 return nil, err 92 } 93 94 blockSize := block.BlockSize() 95 cipherText := make([]byte, len(text)) 96 for i, count := 0, len(text)/blockSize; i < count; i++ { 97 begin, end := i*blockSize, i*blockSize+blockSize 98 block.Encrypt(cipherText[begin:end], text[begin:end]) 99 } 100 return cipherText, nil 101 } 102 103 // DecryptECBTriple decrypts `cipherText` using TripleDES and ECB mode. 104 // The length of the `key` should be either 16 or 24 bytes. 105 func DecryptECBTriple(cipherText []byte, key []byte, padding int) ([]byte, error) { 106 if len(key) != 16 && len(key) != 24 { 107 return nil, gerror.NewCode(gcode.CodeInvalidParameter, "key length error") 108 } 109 110 var newKey []byte 111 if len(key) == 16 { 112 newKey = append([]byte{}, key...) 113 newKey = append(newKey, key[:8]...) 114 } else { 115 newKey = append([]byte{}, key...) 116 } 117 118 block, err := des.NewTripleDESCipher(newKey) 119 if err != nil { 120 err = gerror.WrapCodef(gcode.CodeInvalidParameter, err, `des.NewTripleDESCipher failed for key "%s"`, newKey) 121 return nil, err 122 } 123 124 blockSize := block.BlockSize() 125 text := make([]byte, len(cipherText)) 126 for i, count := 0, len(text)/blockSize; i < count; i++ { 127 begin, end := i*blockSize, i*blockSize+blockSize 128 block.Decrypt(text[begin:end], cipherText[begin:end]) 129 } 130 131 plainText, err := UnPadding(text, padding) 132 if err != nil { 133 return nil, err 134 } 135 return plainText, nil 136 } 137 138 // EncryptCBC encrypts `plainText` using CBC mode. 139 func EncryptCBC(plainText []byte, key []byte, iv []byte, padding int) ([]byte, error) { 140 block, err := des.NewCipher(key) 141 if err != nil { 142 err = gerror.WrapCodef(gcode.CodeInvalidParameter, err, `des.NewCipher failed for key "%s"`, key) 143 return nil, err 144 } 145 146 if len(iv) != block.BlockSize() { 147 return nil, gerror.NewCode(gcode.CodeInvalidParameter, "invalid iv length") 148 } 149 150 text, err := Padding(plainText, padding) 151 if err != nil { 152 return nil, err 153 } 154 cipherText := make([]byte, len(text)) 155 156 encryptor := cipher.NewCBCEncrypter(block, iv) 157 encryptor.CryptBlocks(cipherText, text) 158 159 return cipherText, nil 160 } 161 162 // DecryptCBC decrypts `cipherText` using CBC mode. 163 func DecryptCBC(cipherText []byte, key []byte, iv []byte, padding int) ([]byte, error) { 164 block, err := des.NewCipher(key) 165 if err != nil { 166 err = gerror.WrapCodef(gcode.CodeInvalidParameter, err, `des.NewCipher failed for key "%s"`, key) 167 return nil, err 168 } 169 170 if len(iv) != block.BlockSize() { 171 return nil, gerror.NewCode(gcode.CodeInvalidParameter, "iv length invalid") 172 } 173 174 text := make([]byte, len(cipherText)) 175 decrypter := cipher.NewCBCDecrypter(block, iv) 176 decrypter.CryptBlocks(text, cipherText) 177 178 plainText, err := UnPadding(text, padding) 179 if err != nil { 180 return nil, err 181 } 182 183 return plainText, nil 184 } 185 186 // EncryptCBCTriple encrypts `plainText` using TripleDES and CBC mode. 187 func EncryptCBCTriple(plainText []byte, key []byte, iv []byte, padding int) ([]byte, error) { 188 if len(key) != 16 && len(key) != 24 { 189 return nil, gerror.NewCode(gcode.CodeInvalidParameter, "key length invalid") 190 } 191 192 var newKey []byte 193 if len(key) == 16 { 194 newKey = append([]byte{}, key...) 195 newKey = append(newKey, key[:8]...) 196 } else { 197 newKey = append([]byte{}, key...) 198 } 199 200 block, err := des.NewTripleDESCipher(newKey) 201 if err != nil { 202 err = gerror.WrapCodef(gcode.CodeInvalidParameter, err, `des.NewTripleDESCipher failed for key "%s"`, newKey) 203 return nil, err 204 } 205 206 if len(iv) != block.BlockSize() { 207 return nil, gerror.NewCode(gcode.CodeInvalidParameter, "invalid iv length") 208 } 209 210 text, err := Padding(plainText, padding) 211 if err != nil { 212 return nil, err 213 } 214 215 cipherText := make([]byte, len(text)) 216 encrypter := cipher.NewCBCEncrypter(block, iv) 217 encrypter.CryptBlocks(cipherText, text) 218 219 return cipherText, nil 220 } 221 222 // DecryptCBCTriple decrypts `cipherText` using TripleDES and CBC mode. 223 func DecryptCBCTriple(cipherText []byte, key []byte, iv []byte, padding int) ([]byte, error) { 224 if len(key) != 16 && len(key) != 24 { 225 return nil, gerror.NewCode(gcode.CodeInvalidParameter, "key length invalid") 226 } 227 228 var newKey []byte 229 if len(key) == 16 { 230 newKey = append([]byte{}, key...) 231 newKey = append(newKey, key[:8]...) 232 } else { 233 newKey = append([]byte{}, key...) 234 } 235 236 block, err := des.NewTripleDESCipher(newKey) 237 if err != nil { 238 err = gerror.WrapCodef(gcode.CodeInvalidParameter, err, `des.NewTripleDESCipher failed for key "%s"`, newKey) 239 return nil, err 240 } 241 242 if len(iv) != block.BlockSize() { 243 return nil, gerror.NewCode(gcode.CodeInvalidParameter, "invalid iv length") 244 } 245 246 text := make([]byte, len(cipherText)) 247 decrypter := cipher.NewCBCDecrypter(block, iv) 248 decrypter.CryptBlocks(text, cipherText) 249 250 plainText, err := UnPadding(text, padding) 251 if err != nil { 252 return nil, err 253 } 254 255 return plainText, nil 256 } 257 258 func PaddingPKCS5(text []byte, blockSize int) []byte { 259 padding := blockSize - len(text)%blockSize 260 padText := bytes.Repeat([]byte{byte(padding)}, padding) 261 return append(text, padText...) 262 } 263 264 func UnPaddingPKCS5(text []byte) []byte { 265 length := len(text) 266 padText := int(text[length-1]) 267 return text[:(length - padText)] 268 } 269 270 func Padding(text []byte, padding int) ([]byte, error) { 271 switch padding { 272 case NOPADDING: 273 if len(text)%8 != 0 { 274 return nil, gerror.NewCode(gcode.CodeInvalidParameter, "invalid text length") 275 } 276 277 case PKCS5PADDING: 278 return PaddingPKCS5(text, 8), nil 279 280 default: 281 return nil, gerror.NewCodef(gcode.CodeInvalidParameter, `unsupported padding type "%d"`, padding) 282 } 283 284 return text, nil 285 } 286 287 func UnPadding(text []byte, padding int) ([]byte, error) { 288 switch padding { 289 case NOPADDING: 290 if len(text)%8 != 0 { 291 return nil, gerror.NewCode(gcode.CodeInvalidParameter, "invalid text length") 292 } 293 294 case PKCS5PADDING: 295 return UnPaddingPKCS5(text), nil 296 297 default: 298 return nil, gerror.NewCodef(gcode.CodeInvalidParameter, `unsupported padding type "%d"`, padding) 299 } 300 return text, nil 301 }