欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

golang数据加解密

程序员文章站 2024-03-14 10:44:28
...
package ystEncrypt

import (
	"bytes"
	"crypto/aes"
	"crypto/cipher"
	"encoding/base64"
	"errors"
	"strings"
)

type aesEncrypt struct {
	Key        string //
	IvDefValue string //ivDefValue
}

/**
aesEncrypt初始化
*/
func NewAesEncrypt(Key string, IvDefValue string) *aesEncrypt {
	var a aesEncrypt
	a.Key = Key
	a.IvDefValue = IvDefValue
	return &a
}

/**
数据加密
*/
func (a *aesEncrypt) EncodeData(data string, isBase64 bool, isUrlSafe bool) (string, error) {
	if data == "" {
		return "", errors.New("data  is null")
	}

	key := a.Key
	ivDefValue := a.IvDefValue

	decodeBytesKey, err := base64.StdEncoding.DecodeString(key)
	if err != nil {
		return "", err
	}

	decodeBytesivDefValue, err2 := base64.StdEncoding.DecodeString(ivDefValue)
	if err2 != nil {
		return "", err2
	}

	origData, err3 := a.AesEncrypt([]byte(data), decodeBytesKey, decodeBytesivDefValue)
	if err3 != nil {
		return "", err3
	}
	if isBase64 {
		uEnc := ""
		if isUrlSafe {
			uEnc = base64.URLEncoding.EncodeToString(origData)
			uEnc = strings.Replace(uEnc, "=", "", -1)
		} else {
			uEnc = base64.StdEncoding.EncodeToString(origData)
		}
		return uEnc, nil
	}

	return string(origData), nil
}

/**
数据解密
*/
func (a *aesEncrypt) DecodeData(data string, isBase64 bool, isUrlSafe bool) (string, error) {

	if data == "" {
		return "", errors.New("data  is null")
	}
	decodeBytesivData := []byte{}
	err := *new(error)
	if isBase64 {
		if isUrlSafe {
			decodeBytesivData, err = base64.RawURLEncoding.DecodeString(data)
		} else {
			decodeBytesivData, err = base64.StdEncoding.DecodeString(data)
		}
	} else {
		decodeBytesivData = []byte(data)
	}

	if err != nil {
		return "", err
	}

	key := a.Key
	ivDefValue := a.IvDefValue

	decodeBytesKey, err2 := base64.StdEncoding.DecodeString(key)
	if err2 != nil {
		return "", err2
	}

	decodeBytesivDefValue, err4 := base64.StdEncoding.DecodeString(ivDefValue)
	if err4 != nil {
		return "", err4
	}

	origData, err3 := a.AesDecrypt(decodeBytesivData, decodeBytesKey, decodeBytesivDefValue)
	if err3 != nil {
		return "", err3
	}

	return string(origData), nil
}

/**
字符串替换
*/
func (a *aesEncrypt) UrlDecodeForBase64(str string) string {
	str = strings.Replace(str, "-", "+", -1)
	str = strings.Replace(str, "_", "/", -1)
	return str
}

/**
url安全
*/
func (a *aesEncrypt) UrlEncodeForBase64(str string) string {
	str = strings.Replace(str, "+", "-", -1)
	str = strings.Replace(str, "/", "_", -1)
	str = strings.Replace(str, "=", "", -1)
	return str
}

func (a *aesEncrypt) AesEncrypt(plaintext []byte, key []byte, iv []byte) ([]byte, error) {
	block, err := aes.NewCipher(key)
	if err != nil {
		return nil, errors.New("invalid decrypt key")
	}
	blockSize := block.BlockSize()
	plaintext = a.PKCS5Padding(plaintext, blockSize)
	blockMode := cipher.NewCBCEncrypter(block, iv)

	ciphertext := make([]byte, len(plaintext))
	blockMode.CryptBlocks(ciphertext, plaintext)

	return ciphertext, nil
}

func (a *aesEncrypt) AesDecrypt(ciphertext []byte, key []byte, iv []byte) ([]byte, error) {

	block, err := aes.NewCipher(key)
	if err != nil {
		return nil, errors.New("invalid decrypt key")
	}

	blockSize := block.BlockSize()

	if len(ciphertext) < blockSize {
		return nil, errors.New("ciphertext too short")
	}

	if len(ciphertext)%blockSize != 0 {
		return nil, errors.New("ciphertext is not a multiple of the block size")
	}

	blockModel := cipher.NewCBCDecrypter(block, iv)

	plaintext := make([]byte, len(ciphertext))
	blockModel.CryptBlocks(plaintext, ciphertext)
	plaintext = a.PKCS5UnPadding(plaintext)

	return plaintext, nil
}

func (a *aesEncrypt) PKCS5Padding(src []byte, blockSize int) []byte {
	padding := blockSize - len(src)%blockSize
	padtext := bytes.Repeat([]byte{byte(padding)}, padding)
	return append(src, padtext...)
}

func (a *aesEncrypt) PKCS5UnPadding(src []byte) []byte {
	length := len(src)
	unpadding := int(src[length-1])
	if length-unpadding <= 0 {
		return src
	}
	return src[:(length - unpadding)]
}