123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174 |
- // Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
- //
- // This Source Code Form is subject to the terms of the MIT License.
- // If a copy of the MIT was not distributed with this file,
- // You can obtain one at https://github.com/gogf/gf.
- // Package gaes provides useful API for AES encryption/decryption algorithms.
- package gaes
- import (
- "bytes"
- "crypto/aes"
- "crypto/cipher"
- "github.com/gogf/gf/errors/gcode"
- "github.com/gogf/gf/errors/gerror"
- )
- var (
- // IVDefaultValue is the default value for IV.
- // This can be changed globally.
- IVDefaultValue = "I Love Go Frame!"
- )
- // Encrypt is alias of EncryptCBC.
- func Encrypt(plainText []byte, key []byte, iv ...[]byte) ([]byte, error) {
- return EncryptCBC(plainText, key, iv...)
- }
- // Decrypt is alias of DecryptCBC.
- func Decrypt(cipherText []byte, key []byte, iv ...[]byte) ([]byte, error) {
- return DecryptCBC(cipherText, key, iv...)
- }
- // EncryptCBC encrypts <plainText> using CBC mode.
- // Note that the key must be 16/24/32 bit length.
- // The parameter <iv> initialization vector is unnecessary.
- func EncryptCBC(plainText []byte, key []byte, iv ...[]byte) ([]byte, error) {
- block, err := aes.NewCipher(key)
- if err != nil {
- return nil, err
- }
- blockSize := block.BlockSize()
- plainText = PKCS5Padding(plainText, blockSize)
- ivValue := ([]byte)(nil)
- if len(iv) > 0 {
- ivValue = iv[0]
- } else {
- ivValue = []byte(IVDefaultValue)
- }
- blockMode := cipher.NewCBCEncrypter(block, ivValue)
- cipherText := make([]byte, len(plainText))
- blockMode.CryptBlocks(cipherText, plainText)
- return cipherText, nil
- }
- // DecryptCBC decrypts <cipherText> using CBC mode.
- // Note that the key must be 16/24/32 bit length.
- // The parameter <iv> initialization vector is unnecessary.
- func DecryptCBC(cipherText []byte, key []byte, iv ...[]byte) ([]byte, error) {
- block, err := aes.NewCipher(key)
- if err != nil {
- return nil, err
- }
- blockSize := block.BlockSize()
- if len(cipherText) < blockSize {
- return nil, gerror.NewCode(gcode.CodeInvalidParameter, "cipherText too short")
- }
- ivValue := ([]byte)(nil)
- if len(iv) > 0 {
- ivValue = iv[0]
- } else {
- ivValue = []byte(IVDefaultValue)
- }
- if len(cipherText)%blockSize != 0 {
- return nil, gerror.NewCode(gcode.CodeInvalidParameter, "cipherText is not a multiple of the block size")
- }
- blockModel := cipher.NewCBCDecrypter(block, ivValue)
- plainText := make([]byte, len(cipherText))
- blockModel.CryptBlocks(plainText, cipherText)
- plainText, e := PKCS5UnPadding(plainText, blockSize)
- if e != nil {
- return nil, e
- }
- return plainText, nil
- }
- func PKCS5Padding(src []byte, blockSize int) []byte {
- padding := blockSize - len(src)%blockSize
- padtext := bytes.Repeat([]byte{byte(padding)}, padding)
- return append(src, padtext...)
- }
- func PKCS5UnPadding(src []byte, blockSize int) ([]byte, error) {
- length := len(src)
- if blockSize <= 0 {
- return nil, gerror.NewCode(gcode.CodeInvalidParameter, "invalid blocklen")
- }
- if length%blockSize != 0 || length == 0 {
- return nil, gerror.NewCode(gcode.CodeInvalidParameter, "invalid data len")
- }
- unpadding := int(src[length-1])
- if unpadding > blockSize || unpadding == 0 {
- return nil, gerror.NewCode(gcode.CodeInvalidParameter, "invalid padding")
- }
- padding := src[length-unpadding:]
- for i := 0; i < unpadding; i++ {
- if padding[i] != byte(unpadding) {
- return nil, gerror.NewCode(gcode.CodeInvalidParameter, "invalid padding")
- }
- }
- return src[:(length - unpadding)], nil
- }
- // EncryptCFB encrypts <plainText> using CFB mode.
- // Note that the key must be 16/24/32 bit length.
- // The parameter <iv> initialization vector is unnecessary.
- func EncryptCFB(plainText []byte, key []byte, padding *int, iv ...[]byte) ([]byte, error) {
- block, err := aes.NewCipher(key)
- if err != nil {
- return nil, err
- }
- blockSize := block.BlockSize()
- plainText, *padding = ZeroPadding(plainText, blockSize)
- ivValue := ([]byte)(nil)
- if len(iv) > 0 {
- ivValue = iv[0]
- } else {
- ivValue = []byte(IVDefaultValue)
- }
- stream := cipher.NewCFBEncrypter(block, ivValue)
- cipherText := make([]byte, len(plainText))
- stream.XORKeyStream(cipherText, plainText)
- return cipherText, nil
- }
- // DecryptCFB decrypts <plainText> using CFB mode.
- // Note that the key must be 16/24/32 bit length.
- // The parameter <iv> initialization vector is unnecessary.
- func DecryptCFB(cipherText []byte, key []byte, unPadding int, iv ...[]byte) ([]byte, error) {
- block, err := aes.NewCipher(key)
- if err != nil {
- return nil, err
- }
- if len(cipherText) < aes.BlockSize {
- return nil, gerror.NewCode(gcode.CodeInvalidParameter, "cipherText too short")
- }
- ivValue := ([]byte)(nil)
- if len(iv) > 0 {
- ivValue = iv[0]
- } else {
- ivValue = []byte(IVDefaultValue)
- }
- stream := cipher.NewCFBDecrypter(block, ivValue)
- plainText := make([]byte, len(cipherText))
- stream.XORKeyStream(plainText, cipherText)
- plainText = ZeroUnPadding(plainText, unPadding)
- return plainText, nil
- }
- func ZeroPadding(cipherText []byte, blockSize int) ([]byte, int) {
- padding := blockSize - len(cipherText)%blockSize
- padText := bytes.Repeat([]byte{byte(0)}, padding)
- return append(cipherText, padText...), padding
- }
- func ZeroUnPadding(plaintext []byte, unPadding int) []byte {
- length := len(plaintext)
- return plaintext[:(length - unPadding)]
- }
|