github.com/gogf/gf@v1.16.9/crypto/gaes/gaes.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 gaes provides useful API for AES encryption/decryption algorithms. 8 package gaes 9 10 import ( 11 "bytes" 12 "crypto/aes" 13 "crypto/cipher" 14 "github.com/gogf/gf/errors/gcode" 15 "github.com/gogf/gf/errors/gerror" 16 ) 17 18 var ( 19 // IVDefaultValue is the default value for IV. 20 // This can be changed globally. 21 IVDefaultValue = "I Love Go Frame!" 22 ) 23 24 // Encrypt is alias of EncryptCBC. 25 func Encrypt(plainText []byte, key []byte, iv ...[]byte) ([]byte, error) { 26 return EncryptCBC(plainText, key, iv...) 27 } 28 29 // Decrypt is alias of DecryptCBC. 30 func Decrypt(cipherText []byte, key []byte, iv ...[]byte) ([]byte, error) { 31 return DecryptCBC(cipherText, key, iv...) 32 } 33 34 // EncryptCBC encrypts <plainText> using CBC mode. 35 // Note that the key must be 16/24/32 bit length. 36 // The parameter <iv> initialization vector is unnecessary. 37 func EncryptCBC(plainText []byte, key []byte, iv ...[]byte) ([]byte, error) { 38 block, err := aes.NewCipher(key) 39 if err != nil { 40 return nil, err 41 } 42 blockSize := block.BlockSize() 43 plainText = PKCS5Padding(plainText, blockSize) 44 ivValue := ([]byte)(nil) 45 if len(iv) > 0 { 46 ivValue = iv[0] 47 } else { 48 ivValue = []byte(IVDefaultValue) 49 } 50 blockMode := cipher.NewCBCEncrypter(block, ivValue) 51 cipherText := make([]byte, len(plainText)) 52 blockMode.CryptBlocks(cipherText, plainText) 53 54 return cipherText, nil 55 } 56 57 // DecryptCBC decrypts <cipherText> using CBC mode. 58 // Note that the key must be 16/24/32 bit length. 59 // The parameter <iv> initialization vector is unnecessary. 60 func DecryptCBC(cipherText []byte, key []byte, iv ...[]byte) ([]byte, error) { 61 block, err := aes.NewCipher(key) 62 if err != nil { 63 return nil, err 64 } 65 blockSize := block.BlockSize() 66 if len(cipherText) < blockSize { 67 return nil, gerror.NewCode(gcode.CodeInvalidParameter, "cipherText too short") 68 } 69 ivValue := ([]byte)(nil) 70 if len(iv) > 0 { 71 ivValue = iv[0] 72 } else { 73 ivValue = []byte(IVDefaultValue) 74 } 75 if len(cipherText)%blockSize != 0 { 76 return nil, gerror.NewCode(gcode.CodeInvalidParameter, "cipherText is not a multiple of the block size") 77 } 78 blockModel := cipher.NewCBCDecrypter(block, ivValue) 79 plainText := make([]byte, len(cipherText)) 80 blockModel.CryptBlocks(plainText, cipherText) 81 plainText, e := PKCS5UnPadding(plainText, blockSize) 82 if e != nil { 83 return nil, e 84 } 85 return plainText, nil 86 } 87 88 func PKCS5Padding(src []byte, blockSize int) []byte { 89 padding := blockSize - len(src)%blockSize 90 padtext := bytes.Repeat([]byte{byte(padding)}, padding) 91 return append(src, padtext...) 92 } 93 94 func PKCS5UnPadding(src []byte, blockSize int) ([]byte, error) { 95 length := len(src) 96 if blockSize <= 0 { 97 return nil, gerror.NewCode(gcode.CodeInvalidParameter, "invalid blocklen") 98 } 99 100 if length%blockSize != 0 || length == 0 { 101 return nil, gerror.NewCode(gcode.CodeInvalidParameter, "invalid data len") 102 } 103 104 unpadding := int(src[length-1]) 105 if unpadding > blockSize || unpadding == 0 { 106 return nil, gerror.NewCode(gcode.CodeInvalidParameter, "invalid padding") 107 } 108 109 padding := src[length-unpadding:] 110 for i := 0; i < unpadding; i++ { 111 if padding[i] != byte(unpadding) { 112 return nil, gerror.NewCode(gcode.CodeInvalidParameter, "invalid padding") 113 } 114 } 115 116 return src[:(length - unpadding)], nil 117 } 118 119 // EncryptCFB encrypts <plainText> using CFB mode. 120 // Note that the key must be 16/24/32 bit length. 121 // The parameter <iv> initialization vector is unnecessary. 122 func EncryptCFB(plainText []byte, key []byte, padding *int, iv ...[]byte) ([]byte, error) { 123 block, err := aes.NewCipher(key) 124 if err != nil { 125 return nil, err 126 } 127 blockSize := block.BlockSize() 128 plainText, *padding = ZeroPadding(plainText, blockSize) 129 ivValue := ([]byte)(nil) 130 if len(iv) > 0 { 131 ivValue = iv[0] 132 } else { 133 ivValue = []byte(IVDefaultValue) 134 } 135 stream := cipher.NewCFBEncrypter(block, ivValue) 136 cipherText := make([]byte, len(plainText)) 137 stream.XORKeyStream(cipherText, plainText) 138 return cipherText, nil 139 } 140 141 // DecryptCFB decrypts <plainText> using CFB mode. 142 // Note that the key must be 16/24/32 bit length. 143 // The parameter <iv> initialization vector is unnecessary. 144 func DecryptCFB(cipherText []byte, key []byte, unPadding int, iv ...[]byte) ([]byte, error) { 145 block, err := aes.NewCipher(key) 146 if err != nil { 147 return nil, err 148 } 149 if len(cipherText) < aes.BlockSize { 150 return nil, gerror.NewCode(gcode.CodeInvalidParameter, "cipherText too short") 151 } 152 ivValue := ([]byte)(nil) 153 if len(iv) > 0 { 154 ivValue = iv[0] 155 } else { 156 ivValue = []byte(IVDefaultValue) 157 } 158 stream := cipher.NewCFBDecrypter(block, ivValue) 159 plainText := make([]byte, len(cipherText)) 160 stream.XORKeyStream(plainText, cipherText) 161 plainText = ZeroUnPadding(plainText, unPadding) 162 return plainText, nil 163 } 164 165 func ZeroPadding(cipherText []byte, blockSize int) ([]byte, int) { 166 padding := blockSize - len(cipherText)%blockSize 167 padText := bytes.Repeat([]byte{byte(0)}, padding) 168 return append(cipherText, padText...), padding 169 } 170 171 func ZeroUnPadding(plaintext []byte, unPadding int) []byte { 172 length := len(plaintext) 173 return plaintext[:(length - unPadding)] 174 }