github.com/aaabigfish/gopkg@v1.1.0/crypto/des.go (about) 1 package crypto 2 3 import ( 4 "bytes" 5 "crypto/cipher" 6 "crypto/des" 7 "errors" 8 "strings" 9 "time" 10 ) 11 12 const ( 13 // des 加密模式 14 CBC string = "cbc" 15 ECB string = "ecb" 16 ) 17 18 // des 加解密 19 type desCrypto struct { 20 // 密钥必须是 8 个字节 21 key []byte 22 23 // 加密模式 24 mode string 25 26 // 用于生成初始向量 27 t time.Time 28 } 29 30 // 创建 des 实例 31 func NewDes(key []byte, mode string) *desCrypto { 32 return &desCrypto{key, strings.ToLower(mode), time.Now()} 33 } 34 35 // des 加密 36 func (d *desCrypto) Encrypt(data []byte) ([]byte, error) { 37 switch d.mode { 38 case ECB: 39 return d.ecbEncrypt(data) 40 case CBC: 41 return d.cbcEncrypt(data) 42 default: 43 return nil, errors.New("des encrypt not support mode: " + d.mode) 44 } 45 } 46 47 // des 解密 48 func (d *desCrypto) Decrypt(ciphertext []byte) ([]byte, error) { 49 switch d.mode { 50 case ECB: 51 return d.ecbDecrypt(ciphertext) 52 case CBC: 53 return d.cbcDecrypt(ciphertext) 54 default: 55 return nil, errors.New("des decrypt not support mode: " + d.mode) 56 } 57 } 58 59 // ecb 模式加密 60 func (d *desCrypto) ecbEncrypt(data []byte) ([]byte, error) { 61 block, err := des.NewCipher(d.key) 62 if err != nil { 63 return nil, err 64 } 65 66 // 加密数据 67 bs := block.BlockSize() 68 data = pkcs5Padding(data, bs) 69 if len(data)%bs != 0 { 70 return nil, errors.New("need a multiple of the blocksize") 71 } 72 out := make([]byte, len(data)) 73 dst := out 74 for len(data) > 0 { 75 // 对明文按照 blocksize 进行分块加密 76 block.Encrypt(dst, data[:bs]) 77 data = data[bs:] 78 dst = dst[bs:] 79 } 80 return out, nil 81 } 82 83 // ecb 模式解密 84 func (d *desCrypto) ecbDecrypt(ciphertext []byte) ([]byte, error) { 85 block, err := des.NewCipher(d.key) 86 if err != nil { 87 return nil, err 88 } 89 bs := block.BlockSize() 90 if len(ciphertext)%bs != 0 { 91 return nil, errors.New("crypto/cipher: input not full blocks") 92 } 93 out := make([]byte, len(ciphertext)) 94 dst := out 95 for len(ciphertext) > 0 { 96 block.Decrypt(dst, ciphertext[:bs]) 97 ciphertext = ciphertext[bs:] 98 dst = dst[bs:] 99 } 100 101 return pkcs5UnPadding(out) 102 } 103 104 // cbc 模式加密,安全性高于 ecb 105 func (d *desCrypto) cbcEncrypt(data []byte) ([]byte, error) { 106 block, err := des.NewCipher(d.key) 107 if err != nil { 108 return nil, err 109 } 110 data = pkcs5Padding(data, block.BlockSize()) 111 iv := []byte(d.t.String())[:block.BlockSize()] // 初始向量 112 mode := cipher.NewCBCEncrypter(block, iv) 113 out := make([]byte, len(data)) 114 mode.CryptBlocks(out, data) 115 return out, nil 116 } 117 118 func (d *desCrypto) cbcDecrypt(ciphertext []byte) ([]byte, error) { 119 block, err := des.NewCipher(d.key) 120 if err != nil { 121 return nil, err 122 } 123 iv := []byte(d.t.String())[:block.BlockSize()] // 初始向量 124 mode := cipher.NewCBCDecrypter(block, iv) 125 out := make([]byte, len(ciphertext)) 126 mode.CryptBlocks(out, ciphertext) 127 128 return pkcs5UnPadding(out) 129 } 130 131 // 3DES 加解密,相当于 des 加解密重复 3 次 132 // 增加复杂度,以提高破解难度 133 type tripleDesCrypto struct { 134 // 密钥必须是 24 个字节 135 key []byte 136 137 // 加密模式 138 mode string 139 140 // 用于生成初始向量 141 t time.Time 142 } 143 144 // 创建 3des 实例 145 func New3Des(key []byte, mode string) *tripleDesCrypto { 146 return &tripleDesCrypto{key, mode, time.Now()} 147 } 148 149 // 3des 加密 150 func (d *tripleDesCrypto) TripleEncrypt(data []byte) ([]byte, error) { 151 switch strings.ToLower(d.mode) { 152 case ECB: 153 return d.tripleEcbEncrypt(data) 154 case CBC: 155 return d.tripleCbcEncrypt(data) 156 default: 157 return nil, errors.New("3des encrypt not support mode: " + d.mode) 158 } 159 } 160 161 // 3des 解密 162 func (d *tripleDesCrypto) TripleDecrypt(ciphertext []byte) ([]byte, error) { 163 switch strings.ToLower(d.mode) { 164 case ECB: 165 return d.tripleEcbDecrypt(ciphertext) 166 case CBC: 167 return d.tripleCbcDecrypt(ciphertext) 168 default: 169 return nil, errors.New("3des decrypt not support mode: " + d.mode) 170 } 171 } 172 173 // 3des ecb 加密 174 func (d *tripleDesCrypto) tripleEcbEncrypt(data []byte) ([]byte, error) { 175 block, err := des.NewTripleDESCipher(d.key) 176 if err != nil { 177 return nil, err 178 } 179 180 // 加密数据 181 bs := block.BlockSize() 182 data = pkcs5Padding(data, bs) 183 if len(data)%bs != 0 { 184 return nil, errors.New("need a multiple of the blocksize") 185 } 186 out := make([]byte, len(data)) 187 dst := out 188 for len(data) > 0 { 189 // 对明文按照 blocksize 进行分块加密 190 block.Encrypt(dst, data[:bs]) 191 data = data[bs:] 192 dst = dst[bs:] 193 } 194 return out, nil 195 } 196 197 // 3des ecb 解密 198 func (d *tripleDesCrypto) tripleEcbDecrypt(ciphertext []byte) ([]byte, error) { 199 block, err := des.NewTripleDESCipher(d.key) 200 if err != nil { 201 return nil, err 202 } 203 bs := block.BlockSize() 204 if len(ciphertext)%bs != 0 { 205 return nil, errors.New("crypto/cipher: input not full blocks") 206 } 207 out := make([]byte, len(ciphertext)) 208 dst := out 209 for len(ciphertext) > 0 { 210 block.Decrypt(dst, ciphertext[:bs]) 211 ciphertext = ciphertext[bs:] 212 dst = dst[bs:] 213 } 214 return pkcs5UnPadding(out) 215 } 216 217 // 3des cbc 加密 218 func (d *tripleDesCrypto) tripleCbcEncrypt(data []byte) ([]byte, error) { 219 block, err := des.NewTripleDESCipher(d.key) 220 if err != nil { 221 return nil, err 222 } 223 data = pkcs5Padding(data, block.BlockSize()) 224 iv := []byte(d.t.String())[:block.BlockSize()] // 初始向量 225 mode := cipher.NewCBCEncrypter(block, iv) 226 out := make([]byte, len(data)) 227 mode.CryptBlocks(out, data) 228 return out, nil 229 } 230 231 // 3des cbc 解密 232 func (d *tripleDesCrypto) tripleCbcDecrypt(ciphertext []byte) ([]byte, error) { 233 block, err := des.NewTripleDESCipher(d.key) 234 if err != nil { 235 return nil, err 236 } 237 iv := []byte(d.t.String())[:block.BlockSize()] // 初始向量 238 mode := cipher.NewCBCDecrypter(block, iv) 239 out := make([]byte, len(ciphertext)) 240 mode.CryptBlocks(out, ciphertext) 241 242 return pkcs5UnPadding(out) 243 } 244 245 func pkcs5Padding(ciphertext []byte, blockSize int) []byte { 246 padding := blockSize - len(ciphertext)%blockSize 247 padText := bytes.Repeat([]byte{byte(padding)}, padding) 248 return append(ciphertext, padText...) 249 } 250 251 func pkcs5UnPadding(plantText []byte) ([]byte, error) { 252 length := len(plantText) 253 unpadding := int(plantText[length-1]) 254 255 len := length - unpadding 256 if len < 0 || len > length { 257 return nil, errors.New("aes unpadding error") 258 } 259 260 return plantText[:(len)], nil 261 }