l_crypt/encrypt_way/aes/aes.go

91 lines
2.3 KiB
Go

package aes
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"encoding/base64"
"encoding/json"
"fmt"
"io"
)
// PKCS7Padding pads an input slice to be a multiple of the block size.
func PKCS7Padding(ciphertext []byte, blockSize int) []byte {
padding := blockSize - len(ciphertext)%blockSize
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
return append(ciphertext, padtext...)
}
// PKCS7UnPadding removes the padding from a padded ciphertext.
func PKCS7UnPadding(origData []byte) ([]byte, error) {
length := len(origData)
unpadding := int(origData[length-1])
if unpadding > length {
return nil, fmt.Errorf("unpadding size is invalid")
}
return origData[:(length - unpadding)], nil
}
// Encrypt encrypts a string to an encrypted string.
func Encrypt(key, text string) (string, error) {
block, err := aes.NewCipher([]byte(key))
if err != nil {
return "", err
}
b := base64.StdEncoding.EncodeToString([]byte(text))
ciphertext := make([]byte, aes.BlockSize+len(b))
iv := ciphertext[:aes.BlockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
return "", err
}
stream := cipher.NewCFBEncrypter(block, iv)
stream.XORKeyStream(ciphertext[aes.BlockSize:], []byte(b))
ciphertext = PKCS7Padding(ciphertext, aes.BlockSize)
return base64.StdEncoding.EncodeToString(ciphertext), nil
}
// Decrypt decrypts an encrypted string to an original string.
func Decrypt(key, cryptoText string) (string, error) {
ciphertext, _ := base64.StdEncoding.DecodeString(cryptoText)
ciphertext, err := PKCS7UnPadding(ciphertext)
if err != nil {
return "", err
}
block, err := aes.NewCipher([]byte(key))
if err != nil {
return "", err
}
if len(ciphertext) < aes.BlockSize {
return "", fmt.Errorf("ciphertext too short")
}
iv := ciphertext[:aes.BlockSize]
ciphertext = ciphertext[aes.BlockSize:]
stream := cipher.NewCFBDecrypter(block, iv)
stream.XORKeyStream(ciphertext, ciphertext)
result, err := base64.StdEncoding.DecodeString(string(ciphertext))
if err != nil {
return "", err
}
return string(result), nil
}
// EncryptType encrypts a type to an encrypted string.
// Note: This assumes the type can be marshaled to JSON.
func EncryptType(key string, data interface{}) (string, error) {
jsonData, err := json.Marshal(data)
if err != nil {
return "", err
}
return Encrypt(key, string(jsonData))
}