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

     1  package crypto
     2  
     3  import (
     4  	"bytes"
     5  	"crypto/cipher"
     6  	"crypto/des"
     7  	"errors"
     8  	"strings"
     9  	"time"
    10  )
    11  
    12  const (
    13  	// des 加密模式
    14  	CBC string = "cbc"
    15  	ECB string = "ecb"
    16  )
    17  
    18  // des 加解密
    19  type desCrypto struct {
    20  	// 密钥必须是 8 个字节
    21  	key []byte
    22  
    23  	// 加密模式
    24  	mode string
    25  
    26  	// 用于生成初始向量
    27  	t time.Time
    28  }
    29  
    30  // 创建 des 实例
    31  func NewDes(key []byte, mode string) *desCrypto {
    32  	return &desCrypto{key, strings.ToLower(mode), time.Now()}
    33  }
    34  
    35  // des 加密
    36  func (d *desCrypto) Encrypt(data []byte) ([]byte, error) {
    37  	switch d.mode {
    38  	case ECB:
    39  		return d.ecbEncrypt(data)
    40  	case CBC:
    41  		return d.cbcEncrypt(data)
    42  	default:
    43  		return nil, errors.New("des encrypt not support mode: " + d.mode)
    44  	}
    45  }
    46  
    47  // des 解密
    48  func (d *desCrypto) Decrypt(ciphertext []byte) ([]byte, error) {
    49  	switch d.mode {
    50  	case ECB:
    51  		return d.ecbDecrypt(ciphertext)
    52  	case CBC:
    53  		return d.cbcDecrypt(ciphertext)
    54  	default:
    55  		return nil, errors.New("des decrypt not support mode: " + d.mode)
    56  	}
    57  }
    58  
    59  // ecb 模式加密
    60  func (d *desCrypto) ecbEncrypt(data []byte) ([]byte, error) {
    61  	block, err := des.NewCipher(d.key)
    62  	if err != nil {
    63  		return nil, err
    64  	}
    65  
    66  	// 加密数据
    67  	bs := block.BlockSize()
    68  	data = pkcs5Padding(data, bs)
    69  	if len(data)%bs != 0 {
    70  		return nil, errors.New("need a multiple of the blocksize")
    71  	}
    72  	out := make([]byte, len(data))
    73  	dst := out
    74  	for len(data) > 0 {
    75  		// 对明文按照 blocksize 进行分块加密
    76  		block.Encrypt(dst, data[:bs])
    77  		data = data[bs:]
    78  		dst = dst[bs:]
    79  	}
    80  	return out, nil
    81  }
    82  
    83  // ecb 模式解密
    84  func (d *desCrypto) ecbDecrypt(ciphertext []byte) ([]byte, error) {
    85  	block, err := des.NewCipher(d.key)
    86  	if err != nil {
    87  		return nil, err
    88  	}
    89  	bs := block.BlockSize()
    90  	if len(ciphertext)%bs != 0 {
    91  		return nil, errors.New("crypto/cipher: input not full blocks")
    92  	}
    93  	out := make([]byte, len(ciphertext))
    94  	dst := out
    95  	for len(ciphertext) > 0 {
    96  		block.Decrypt(dst, ciphertext[:bs])
    97  		ciphertext = ciphertext[bs:]
    98  		dst = dst[bs:]
    99  	}
   100  
   101  	return pkcs5UnPadding(out)
   102  }
   103  
   104  // cbc 模式加密,安全性高于 ecb
   105  func (d *desCrypto) cbcEncrypt(data []byte) ([]byte, error) {
   106  	block, err := des.NewCipher(d.key)
   107  	if err != nil {
   108  		return nil, err
   109  	}
   110  	data = pkcs5Padding(data, block.BlockSize())
   111  	iv := []byte(d.t.String())[:block.BlockSize()] // 初始向量
   112  	mode := cipher.NewCBCEncrypter(block, iv)
   113  	out := make([]byte, len(data))
   114  	mode.CryptBlocks(out, data)
   115  	return out, nil
   116  }
   117  
   118  func (d *desCrypto) cbcDecrypt(ciphertext []byte) ([]byte, error) {
   119  	block, err := des.NewCipher(d.key)
   120  	if err != nil {
   121  		return nil, err
   122  	}
   123  	iv := []byte(d.t.String())[:block.BlockSize()] // 初始向量
   124  	mode := cipher.NewCBCDecrypter(block, iv)
   125  	out := make([]byte, len(ciphertext))
   126  	mode.CryptBlocks(out, ciphertext)
   127  
   128  	return pkcs5UnPadding(out)
   129  }
   130  
   131  // 3DES 加解密,相当于 des 加解密重复 3 次
   132  // 增加复杂度,以提高破解难度
   133  type tripleDesCrypto struct {
   134  	// 密钥必须是 24 个字节
   135  	key []byte
   136  
   137  	// 加密模式
   138  	mode string
   139  
   140  	// 用于生成初始向量
   141  	t time.Time
   142  }
   143  
   144  // 创建 3des 实例
   145  func New3Des(key []byte, mode string) *tripleDesCrypto {
   146  	return &tripleDesCrypto{key, mode, time.Now()}
   147  }
   148  
   149  // 3des 加密
   150  func (d *tripleDesCrypto) TripleEncrypt(data []byte) ([]byte, error) {
   151  	switch strings.ToLower(d.mode) {
   152  	case ECB:
   153  		return d.tripleEcbEncrypt(data)
   154  	case CBC:
   155  		return d.tripleCbcEncrypt(data)
   156  	default:
   157  		return nil, errors.New("3des encrypt not support mode: " + d.mode)
   158  	}
   159  }
   160  
   161  // 3des 解密
   162  func (d *tripleDesCrypto) TripleDecrypt(ciphertext []byte) ([]byte, error) {
   163  	switch strings.ToLower(d.mode) {
   164  	case ECB:
   165  		return d.tripleEcbDecrypt(ciphertext)
   166  	case CBC:
   167  		return d.tripleCbcDecrypt(ciphertext)
   168  	default:
   169  		return nil, errors.New("3des decrypt not support mode: " + d.mode)
   170  	}
   171  }
   172  
   173  // 3des ecb 加密
   174  func (d *tripleDesCrypto) tripleEcbEncrypt(data []byte) ([]byte, error) {
   175  	block, err := des.NewTripleDESCipher(d.key)
   176  	if err != nil {
   177  		return nil, err
   178  	}
   179  
   180  	// 加密数据
   181  	bs := block.BlockSize()
   182  	data = pkcs5Padding(data, bs)
   183  	if len(data)%bs != 0 {
   184  		return nil, errors.New("need a multiple of the blocksize")
   185  	}
   186  	out := make([]byte, len(data))
   187  	dst := out
   188  	for len(data) > 0 {
   189  		// 对明文按照 blocksize 进行分块加密
   190  		block.Encrypt(dst, data[:bs])
   191  		data = data[bs:]
   192  		dst = dst[bs:]
   193  	}
   194  	return out, nil
   195  }
   196  
   197  // 3des ecb 解密
   198  func (d *tripleDesCrypto) tripleEcbDecrypt(ciphertext []byte) ([]byte, error) {
   199  	block, err := des.NewTripleDESCipher(d.key)
   200  	if err != nil {
   201  		return nil, err
   202  	}
   203  	bs := block.BlockSize()
   204  	if len(ciphertext)%bs != 0 {
   205  		return nil, errors.New("crypto/cipher: input not full blocks")
   206  	}
   207  	out := make([]byte, len(ciphertext))
   208  	dst := out
   209  	for len(ciphertext) > 0 {
   210  		block.Decrypt(dst, ciphertext[:bs])
   211  		ciphertext = ciphertext[bs:]
   212  		dst = dst[bs:]
   213  	}
   214  	return pkcs5UnPadding(out)
   215  }
   216  
   217  // 3des cbc 加密
   218  func (d *tripleDesCrypto) tripleCbcEncrypt(data []byte) ([]byte, error) {
   219  	block, err := des.NewTripleDESCipher(d.key)
   220  	if err != nil {
   221  		return nil, err
   222  	}
   223  	data = pkcs5Padding(data, block.BlockSize())
   224  	iv := []byte(d.t.String())[:block.BlockSize()] // 初始向量
   225  	mode := cipher.NewCBCEncrypter(block, iv)
   226  	out := make([]byte, len(data))
   227  	mode.CryptBlocks(out, data)
   228  	return out, nil
   229  }
   230  
   231  // 3des cbc 解密
   232  func (d *tripleDesCrypto) tripleCbcDecrypt(ciphertext []byte) ([]byte, error) {
   233  	block, err := des.NewTripleDESCipher(d.key)
   234  	if err != nil {
   235  		return nil, err
   236  	}
   237  	iv := []byte(d.t.String())[:block.BlockSize()] // 初始向量
   238  	mode := cipher.NewCBCDecrypter(block, iv)
   239  	out := make([]byte, len(ciphertext))
   240  	mode.CryptBlocks(out, ciphertext)
   241  
   242  	return pkcs5UnPadding(out)
   243  }
   244  
   245  func pkcs5Padding(ciphertext []byte, blockSize int) []byte {
   246  	padding := blockSize - len(ciphertext)%blockSize
   247  	padText := bytes.Repeat([]byte{byte(padding)}, padding)
   248  	return append(ciphertext, padText...)
   249  }
   250  
   251  func pkcs5UnPadding(plantText []byte) ([]byte, error) {
   252  	length := len(plantText)
   253  	unpadding := int(plantText[length-1])
   254  
   255  	len := length - unpadding
   256  	if len < 0 || len > length {
   257  		return nil, errors.New("aes unpadding error")
   258  	}
   259  
   260  	return plantText[:(len)], nil
   261  }