github.com/AntonOrnatskyi/goproxy@v0.0.0-20190205095733-4526a9fa18b4/utils/aes/aes.go (about)

     1  // Playbook - http://play.golang.org/p/3wFl4lacjX
     2  
     3  package goaes
     4  
     5  import (
     6  	"bytes"
     7  	"crypto/aes"
     8  	"crypto/cipher"
     9  	"crypto/rand"
    10  	"errors"
    11  	"io"
    12  	"strings"
    13  )
    14  
    15  func addBase64Padding(value string) string {
    16  	m := len(value) % 4
    17  	if m != 0 {
    18  		value += strings.Repeat("=", 4-m)
    19  	}
    20  
    21  	return value
    22  }
    23  
    24  func removeBase64Padding(value string) string {
    25  	return strings.Replace(value, "=", "", -1)
    26  }
    27  
    28  func Pad(src []byte) []byte {
    29  	padding := aes.BlockSize - len(src)%aes.BlockSize
    30  	padtext := bytes.Repeat([]byte{byte(padding)}, padding)
    31  	return append(src, padtext...)
    32  }
    33  
    34  func Unpad(src []byte) ([]byte, error) {
    35  	length := len(src)
    36  	unpadding := int(src[length-1])
    37  
    38  	if unpadding > length {
    39  		return nil, errors.New("unpad error. This could happen when incorrect encryption key is used")
    40  	}
    41  
    42  	return src[:(length - unpadding)], nil
    43  }
    44  
    45  func Encrypt(key []byte, text []byte) ([]byte, error) {
    46  	block, err := aes.NewCipher(key)
    47  	if err != nil {
    48  		return nil, err
    49  	}
    50  
    51  	msg := Pad(text)
    52  	ciphertext := make([]byte, aes.BlockSize+len(msg))
    53  	iv := ciphertext[:aes.BlockSize]
    54  	if _, err := io.ReadFull(rand.Reader, iv); err != nil {
    55  		return nil, err
    56  	}
    57  
    58  	cfb := cipher.NewCFBEncrypter(block, iv)
    59  	cfb.XORKeyStream(ciphertext[aes.BlockSize:], []byte(msg))
    60  
    61  	return ciphertext, nil
    62  }
    63  
    64  func Decrypt(key []byte, text []byte) ([]byte, error) {
    65  	block, err := aes.NewCipher(key)
    66  	if err != nil {
    67  		return nil, err
    68  	}
    69  	if (len(text) % aes.BlockSize) != 0 {
    70  		return nil, errors.New("blocksize must be multipe of decoded message length")
    71  	}
    72  	iv := text[:aes.BlockSize]
    73  	msg := text[aes.BlockSize:]
    74  
    75  	cfb := cipher.NewCFBDecrypter(block, iv)
    76  	cfb.XORKeyStream(msg, msg)
    77  
    78  	unpadMsg, err := Unpad(msg)
    79  	if err != nil {
    80  		return nil, err
    81  	}
    82  
    83  	return unpadMsg, nil
    84  }