github.com/aaabigfish/gopkg@v1.1.0/crypto/aes.go (about)

     1  package crypto
     2  
     3  import (
     4  	"crypto/aes"
     5  	"crypto/cipher"
     6  	"errors"
     7  	"strings"
     8  	"time"
     9  )
    10  
    11  // aes 加密
    12  type aesCrypto struct {
    13  	// 密钥必须时 16 位
    14  	key []byte
    15  
    16  	// 加密模式
    17  	mode string
    18  
    19  	// 用于生成初始向量
    20  	t time.Time
    21  }
    22  
    23  type aesCbcCrypto struct {
    24  	// 密钥必须时 16 位
    25  	key []byte
    26  
    27  	// iv 向量
    28  	iv []byte
    29  }
    30  
    31  // 创建 aes 实例
    32  func NewAes(key []byte, mode string) *aesCrypto {
    33  	return &aesCrypto{key, strings.ToLower(mode), time.Now()}
    34  }
    35  
    36  // 创建 aes cbc实例
    37  func NewAesCBC(key, vi []byte) *aesCbcCrypto {
    38  	return &aesCbcCrypto{key, vi}
    39  }
    40  
    41  // aes 加密
    42  func (a *aesCrypto) Encrypt(data []byte) ([]byte, error) {
    43  	switch a.mode {
    44  	case ECB:
    45  		return a.ecbEncrypt(data)
    46  	case CBC:
    47  		return a.cbcEncrypt(data)
    48  	default:
    49  		return nil, errors.New("aes encrypt not support mode: " + a.mode)
    50  	}
    51  }
    52  
    53  // aes 解密
    54  func (a *aesCrypto) Decrypt(ciphertext []byte) ([]byte, error) {
    55  	switch a.mode {
    56  	case ECB:
    57  		return a.ecbDecrypt(ciphertext)
    58  	case CBC:
    59  		return a.cbcDecrypt(ciphertext)
    60  	default:
    61  		return nil, errors.New("aes decrypt not support mode: " + a.mode)
    62  	}
    63  }
    64  
    65  // aes cbc 模式加密
    66  func (a *aesCrypto) cbcEncrypt(data []byte) ([]byte, error) {
    67  	block, err := aes.NewCipher(a.key)
    68  	if err != nil {
    69  		return nil, err
    70  	}
    71  	blockSize := block.BlockSize()
    72  	data = pkcs5Padding(data, blockSize)
    73  	iv := []byte(a.t.String())[:blockSize] // 初始向量
    74  	blockMode := cipher.NewCBCEncrypter(block, iv)
    75  	dst := make([]byte, len(data))
    76  	blockMode.CryptBlocks(dst, data)
    77  	return dst, nil
    78  }
    79  
    80  // aes cbc 模式解密
    81  func (a *aesCrypto) cbcDecrypt(ciphertext []byte) ([]byte, error) {
    82  	block, err := aes.NewCipher(a.key)
    83  	if err != nil {
    84  		return nil, err
    85  	}
    86  	iv := []byte(a.t.String())[:block.BlockSize()] // 初始向量
    87  	blockMode := cipher.NewCBCDecrypter(block, iv)
    88  	out := make([]byte, len(ciphertext))
    89  	blockMode.CryptBlocks(out, ciphertext)
    90  	return pkcs5UnPadding(out)
    91  }
    92  
    93  // aes ecb 模式加密
    94  func (a *aesCrypto) ecbEncrypt(data []byte) ([]byte, error) {
    95  	block, err := aes.NewCipher(a.key)
    96  	if err != nil {
    97  		return nil, err
    98  	}
    99  	length := (len(data) + aes.BlockSize) / aes.BlockSize
   100  	plain := make([]byte, length*aes.BlockSize)
   101  	copy(plain, data)
   102  	pad := byte(len(plain) - len(data))
   103  	for i := len(data); i < len(plain); i++ {
   104  		plain[i] = pad
   105  	}
   106  	dst := make([]byte, len(plain))
   107  
   108  	// 分组分块加密
   109  	blockSize := block.BlockSize()
   110  	for bs, be := 0, blockSize; bs <= len(data); bs, be = bs+blockSize, be+blockSize {
   111  		block.Encrypt(dst[bs:be], plain[bs:be])
   112  	}
   113  	return dst, nil
   114  }
   115  
   116  // aes ecb 模式解密
   117  func (a *aesCrypto) ecbDecrypt(ciphertext []byte) ([]byte, error) {
   118  	block, err := aes.NewCipher(a.key)
   119  	if err != nil {
   120  		return nil, err
   121  	}
   122  	out := make([]byte, len(ciphertext))
   123  	blockSize := block.BlockSize()
   124  	for bs, be := 0, blockSize; bs < len(ciphertext); bs, be = bs+blockSize, be+blockSize {
   125  		block.Decrypt(out[bs:be], ciphertext[bs:be])
   126  	}
   127  	trim := 0
   128  	if len(out) > 0 {
   129  		trim = len(out) - int(out[len(out)-1])
   130  	}
   131  	return out[:trim], nil
   132  }
   133  
   134  // aes cbc 模式加密
   135  func (a *aesCbcCrypto) CbcEncrypt(plantText []byte, padding bool) ([]byte, error) {
   136  	block, err := aes.NewCipher(a.key)
   137  	if err != nil {
   138  		return nil, err
   139  	}
   140  	if padding {
   141  		plantText = pkcs5Padding(plantText, block.BlockSize())
   142  	}
   143  
   144  	blockMode := cipher.NewCBCEncrypter(block, a.iv)
   145  	ciphertext := make([]byte, len(plantText))
   146  	blockMode.CryptBlocks(ciphertext, plantText)
   147  	return ciphertext, nil
   148  }
   149  
   150  // aes cbc 模式解密
   151  func (a *aesCbcCrypto) CbcDecrypt(ciphertext []byte, padding bool) ([]byte, error) {
   152  	block, err := aes.NewCipher(a.key)
   153  	if err != nil {
   154  		return nil, err
   155  	}
   156  
   157  	blockMode := cipher.NewCBCDecrypter(block, a.iv)
   158  	plantText := make([]byte, len(ciphertext))
   159  	blockMode.CryptBlocks(plantText, ciphertext)
   160  	if padding {
   161  		return pkcs5UnPadding(plantText)
   162  	}
   163  
   164  	return plantText, nil
   165  }