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