github.com/zhongdalu/gf@v1.0.0/g/crypto/gaes/gaes.go (about) 1 // Copyright 2017 gf Author(https://github.com/zhongdalu/gf). 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/zhongdalu/gf. 6 7 // Package gaes provides useful API for AES encryption/decryption algorithms. 8 package gaes 9 10 import ( 11 "bytes" 12 "crypto/aes" 13 "crypto/cipher" 14 "errors" 15 ) 16 17 const ( 18 ivDefValue = "I Love Go Frame!" 19 ) 20 21 // Encrypt is alias of EncryptCBC. 22 func Encrypt(plainText []byte, key []byte, iv ...[]byte) ([]byte, error) { 23 return EncryptCBC(plainText, key, iv...) 24 } 25 26 // Decrypt is alias of DecryptCBC. 27 func Decrypt(cipherText []byte, key []byte, iv ...[]byte) ([]byte, error) { 28 return DecryptCBC(cipherText, key, iv...) 29 } 30 31 // AES加密, 使用CBC模式,注意key必须为16/24/32位长度,iv初始化向量为非必需参数。 32 func EncryptCBC(plainText []byte, key []byte, iv ...[]byte) ([]byte, error) { 33 block, err := aes.NewCipher(key) 34 if err != nil { 35 return nil, err 36 } 37 blockSize := block.BlockSize() 38 plainText = PKCS5Padding(plainText, blockSize) 39 ivValue := ([]byte)(nil) 40 if len(iv) > 0 { 41 ivValue = iv[0] 42 } else { 43 ivValue = []byte(ivDefValue) 44 } 45 blockMode := cipher.NewCBCEncrypter(block, ivValue) 46 cipherText := make([]byte, len(plainText)) 47 blockMode.CryptBlocks(cipherText, plainText) 48 49 return cipherText, nil 50 } 51 52 // AES解密, 使用CBC模式,注意key必须为16/24/32位长度,iv初始化向量为非必需参数 53 func DecryptCBC(cipherText []byte, key []byte, iv ...[]byte) ([]byte, error) { 54 block, err := aes.NewCipher(key) 55 if err != nil { 56 return nil, err 57 } 58 blockSize := block.BlockSize() 59 if len(cipherText) < blockSize { 60 return nil, errors.New("cipherText too short") 61 } 62 ivValue := ([]byte)(nil) 63 if len(iv) > 0 { 64 ivValue = iv[0] 65 } else { 66 ivValue = []byte(ivDefValue) 67 } 68 if len(cipherText)%blockSize != 0 { 69 return nil, errors.New("cipherText is not a multiple of the block size") 70 } 71 blockModel := cipher.NewCBCDecrypter(block, ivValue) 72 plainText := make([]byte, len(cipherText)) 73 blockModel.CryptBlocks(plainText, cipherText) 74 plainText, e := PKCS5UnPadding(plainText, blockSize) 75 if e != nil { 76 return nil, e 77 } 78 return plainText, nil 79 } 80 81 func PKCS5Padding(src []byte, blockSize int) []byte { 82 padding := blockSize - len(src)%blockSize 83 padtext := bytes.Repeat([]byte{byte(padding)}, padding) 84 return append(src, padtext...) 85 } 86 87 func PKCS5UnPadding(src []byte, blockSize int) ([]byte, error) { 88 length := len(src) 89 if blockSize <= 0 { 90 return nil, errors.New("invalid blocklen") 91 } 92 93 if length%blockSize != 0 || length == 0 { 94 return nil, errors.New("invalid data len") 95 } 96 97 unpadding := int(src[length-1]) 98 if unpadding > blockSize || unpadding == 0 { 99 return nil, errors.New("invalid padding") 100 } 101 102 padding := src[length-unpadding:] 103 for i := 0; i < unpadding; i++ { 104 if padding[i] != byte(unpadding) { 105 return nil, errors.New("invalid padding") 106 } 107 } 108 109 return src[:(length - unpadding)], nil 110 } 111 112 // AES加密, 使用CFB模式。 113 // 注意key必须为16/24/32位长度,padding返回补位长度,iv初始化向量为非必需参数。 114 func EncryptCFB(plainText []byte, key []byte, padding *int, iv ...[]byte) ([]byte, error) { 115 block, err := aes.NewCipher(key) 116 if err != nil { 117 return nil, err 118 } 119 blockSize := block.BlockSize() 120 plainText, *padding = ZeroPadding(plainText, blockSize) //补位0 121 ivValue := ([]byte)(nil) 122 if len(iv) > 0 { 123 ivValue = iv[0] 124 } else { 125 ivValue = []byte(ivDefValue) 126 } 127 stream := cipher.NewCFBEncrypter(block, ivValue) 128 cipherText := make([]byte, len(plainText)) 129 stream.XORKeyStream(cipherText, plainText) 130 return cipherText, nil 131 } 132 133 // AES解密, 使用CFB模式。 134 // 注意key必须为16/24/32位长度,unpadding为去补位长度,iv初始化向量为非必需参数。 135 func DecryptCFB(cipherText []byte, key []byte, unpadding int, iv ...[]byte) ([]byte, error) { 136 block, err := aes.NewCipher(key) 137 if err != nil { 138 return nil, err 139 } 140 if len(cipherText) < aes.BlockSize { 141 return nil, errors.New("cipherText too short") 142 } 143 ivValue := ([]byte)(nil) 144 if len(iv) > 0 { 145 ivValue = iv[0] 146 } else { 147 ivValue = []byte(ivDefValue) 148 } 149 stream := cipher.NewCFBDecrypter(block, ivValue) 150 plainText := make([]byte, len(cipherText)) 151 stream.XORKeyStream(plainText, cipherText) 152 plainText = ZeroUnPadding(plainText, unpadding) //去补位0 153 return plainText, nil 154 } 155 156 func ZeroPadding(ciphertext []byte, blockSize int) ([]byte, int) { 157 padding := blockSize - len(ciphertext)%blockSize 158 padtext := bytes.Repeat([]byte{byte(0)}, padding) 159 return append(ciphertext, padtext...), padding 160 } 161 162 func ZeroUnPadding(plaintext []byte, unpadding int) []byte { 163 length := len(plaintext) 164 return plaintext[:(length - unpadding)] 165 }