github.com/aaabigfish/gopkg@v1.1.0/crypto/aes.go (about) 1 package crypto 2 3 import ( 4 "crypto/aes" 5 "crypto/cipher" 6 "errors" 7 "strings" 8 "time" 9 ) 10 11 // aes 加密 12 type aesCrypto struct { 13 // 密钥必须时 16 位 14 key []byte 15 16 // 加密模式 17 mode string 18 19 // 用于生成初始向量 20 t time.Time 21 } 22 23 type aesCbcCrypto struct { 24 // 密钥必须时 16 位 25 key []byte 26 27 // iv 向量 28 iv []byte 29 } 30 31 // 创建 aes 实例 32 func NewAes(key []byte, mode string) *aesCrypto { 33 return &aesCrypto{key, strings.ToLower(mode), time.Now()} 34 } 35 36 // 创建 aes cbc实例 37 func NewAesCBC(key, vi []byte) *aesCbcCrypto { 38 return &aesCbcCrypto{key, vi} 39 } 40 41 // aes 加密 42 func (a *aesCrypto) Encrypt(data []byte) ([]byte, error) { 43 switch a.mode { 44 case ECB: 45 return a.ecbEncrypt(data) 46 case CBC: 47 return a.cbcEncrypt(data) 48 default: 49 return nil, errors.New("aes encrypt not support mode: " + a.mode) 50 } 51 } 52 53 // aes 解密 54 func (a *aesCrypto) Decrypt(ciphertext []byte) ([]byte, error) { 55 switch a.mode { 56 case ECB: 57 return a.ecbDecrypt(ciphertext) 58 case CBC: 59 return a.cbcDecrypt(ciphertext) 60 default: 61 return nil, errors.New("aes decrypt not support mode: " + a.mode) 62 } 63 } 64 65 // aes cbc 模式加密 66 func (a *aesCrypto) cbcEncrypt(data []byte) ([]byte, error) { 67 block, err := aes.NewCipher(a.key) 68 if err != nil { 69 return nil, err 70 } 71 blockSize := block.BlockSize() 72 data = pkcs5Padding(data, blockSize) 73 iv := []byte(a.t.String())[:blockSize] // 初始向量 74 blockMode := cipher.NewCBCEncrypter(block, iv) 75 dst := make([]byte, len(data)) 76 blockMode.CryptBlocks(dst, data) 77 return dst, nil 78 } 79 80 // aes cbc 模式解密 81 func (a *aesCrypto) cbcDecrypt(ciphertext []byte) ([]byte, error) { 82 block, err := aes.NewCipher(a.key) 83 if err != nil { 84 return nil, err 85 } 86 iv := []byte(a.t.String())[:block.BlockSize()] // 初始向量 87 blockMode := cipher.NewCBCDecrypter(block, iv) 88 out := make([]byte, len(ciphertext)) 89 blockMode.CryptBlocks(out, ciphertext) 90 return pkcs5UnPadding(out) 91 } 92 93 // aes ecb 模式加密 94 func (a *aesCrypto) ecbEncrypt(data []byte) ([]byte, error) { 95 block, err := aes.NewCipher(a.key) 96 if err != nil { 97 return nil, err 98 } 99 length := (len(data) + aes.BlockSize) / aes.BlockSize 100 plain := make([]byte, length*aes.BlockSize) 101 copy(plain, data) 102 pad := byte(len(plain) - len(data)) 103 for i := len(data); i < len(plain); i++ { 104 plain[i] = pad 105 } 106 dst := make([]byte, len(plain)) 107 108 // 分组分块加密 109 blockSize := block.BlockSize() 110 for bs, be := 0, blockSize; bs <= len(data); bs, be = bs+blockSize, be+blockSize { 111 block.Encrypt(dst[bs:be], plain[bs:be]) 112 } 113 return dst, nil 114 } 115 116 // aes ecb 模式解密 117 func (a *aesCrypto) ecbDecrypt(ciphertext []byte) ([]byte, error) { 118 block, err := aes.NewCipher(a.key) 119 if err != nil { 120 return nil, err 121 } 122 out := make([]byte, len(ciphertext)) 123 blockSize := block.BlockSize() 124 for bs, be := 0, blockSize; bs < len(ciphertext); bs, be = bs+blockSize, be+blockSize { 125 block.Decrypt(out[bs:be], ciphertext[bs:be]) 126 } 127 trim := 0 128 if len(out) > 0 { 129 trim = len(out) - int(out[len(out)-1]) 130 } 131 return out[:trim], nil 132 } 133 134 // aes cbc 模式加密 135 func (a *aesCbcCrypto) CbcEncrypt(plantText []byte, padding bool) ([]byte, error) { 136 block, err := aes.NewCipher(a.key) 137 if err != nil { 138 return nil, err 139 } 140 if padding { 141 plantText = pkcs5Padding(plantText, block.BlockSize()) 142 } 143 144 blockMode := cipher.NewCBCEncrypter(block, a.iv) 145 ciphertext := make([]byte, len(plantText)) 146 blockMode.CryptBlocks(ciphertext, plantText) 147 return ciphertext, nil 148 } 149 150 // aes cbc 模式解密 151 func (a *aesCbcCrypto) CbcDecrypt(ciphertext []byte, padding bool) ([]byte, error) { 152 block, err := aes.NewCipher(a.key) 153 if err != nil { 154 return nil, err 155 } 156 157 blockMode := cipher.NewCBCDecrypter(block, a.iv) 158 plantText := make([]byte, len(ciphertext)) 159 blockMode.CryptBlocks(plantText, ciphertext) 160 if padding { 161 return pkcs5UnPadding(plantText) 162 } 163 164 return plantText, nil 165 }