github.com/zhongdalu/gf@v1.0.0/g/crypto/gdes/gdes.go (about)

     1  // Copyright 2018 gf Author(https://github.com/zhongdalu/gf). All Rights Reserved.
     2  //
     3  // This Source Code Form is subject to the terms of the MIT License.
     4  // If a copy of the MIT was not distributed with this file,
     5  // You can obtain one at https://github.com/zhongdalu/gf.
     6  
     7  // Package gdes provides useful API for DES encryption/decryption algorithms.
     8  package gdes
     9  
    10  import (
    11  	"bytes"
    12  	"crypto/cipher"
    13  	"crypto/des"
    14  	"errors"
    15  )
    16  
    17  const (
    18  	NOPADDING = iota
    19  	PKCS5PADDING
    20  )
    21  
    22  // ECB模式DES加密
    23  func DesECBEncrypt(key []byte, clearText []byte, padding int) ([]byte, error) {
    24  	text, err := Padding(clearText, padding)
    25  	if err != nil {
    26  		return nil, err
    27  	}
    28  
    29  	cipherText := make([]byte, len(text))
    30  
    31  	block, err := des.NewCipher(key)
    32  	if err != nil {
    33  		return nil, err
    34  	}
    35  
    36  	blockSize := block.BlockSize()
    37  	for i, count := 0, len(text)/blockSize; i < count; i++ {
    38  		begin, end := i*blockSize, i*blockSize+blockSize
    39  		block.Encrypt(cipherText[begin:end], text[begin:end])
    40  	}
    41  	return cipherText, nil
    42  }
    43  
    44  // ECB模式DES解密
    45  func DesECBDecrypt(key []byte, cipherText []byte, padding int) ([]byte, error) {
    46  	text := make([]byte, len(cipherText))
    47  	block, err := des.NewCipher(key)
    48  	if err != nil {
    49  		return nil, err
    50  	}
    51  
    52  	blockSize := block.BlockSize()
    53  	for i, count := 0, len(text)/blockSize; i < count; i++ {
    54  		begin, end := i*blockSize, i*blockSize+blockSize
    55  		block.Decrypt(text[begin:end], cipherText[begin:end])
    56  	}
    57  
    58  	clearText, err := UnPadding(text, padding)
    59  	if err != nil {
    60  		return nil, err
    61  	}
    62  	return clearText, nil
    63  }
    64  
    65  // ECB模式3DES加密,密钥长度可以是16或24位长
    66  func TripleDesECBEncrypt(key []byte, clearText []byte, padding int) ([]byte, error) {
    67  	if len(key) != 16 && len(key) != 24 {
    68  		return nil, errors.New("key length error")
    69  	}
    70  
    71  	text, err := Padding(clearText, padding)
    72  	if err != nil {
    73  		return nil, err
    74  	}
    75  
    76  	var newKey []byte
    77  	if len(key) == 16 {
    78  		newKey = append([]byte{}, key...)
    79  		newKey = append(newKey, key[:8]...)
    80  	} else {
    81  		newKey = append([]byte{}, key...)
    82  	}
    83  
    84  	block, err := des.NewTripleDESCipher(newKey)
    85  	if err != nil {
    86  		return nil, err
    87  	}
    88  
    89  	blockSize := block.BlockSize()
    90  	cipherText := make([]byte, len(text))
    91  	for i, count := 0, len(text)/blockSize; i < count; i++ {
    92  		begin, end := i*blockSize, i*blockSize+blockSize
    93  		block.Encrypt(cipherText[begin:end], text[begin:end])
    94  	}
    95  	return cipherText, nil
    96  }
    97  
    98  // ECB模式3DES解密,密钥长度可以是16或24位长
    99  func TripleDesECBDecrypt(key []byte, cipherText []byte, padding int) ([]byte, error) {
   100  	if len(key) != 16 && len(key) != 24 {
   101  		return nil, errors.New("key length error")
   102  	}
   103  
   104  	var newKey []byte
   105  	if len(key) == 16 {
   106  		newKey = append([]byte{}, key...)
   107  		newKey = append(newKey, key[:8]...)
   108  	} else {
   109  		newKey = append([]byte{}, key...)
   110  	}
   111  
   112  	block, err := des.NewTripleDESCipher(newKey)
   113  	if err != nil {
   114  		return nil, err
   115  	}
   116  
   117  	blockSize := block.BlockSize()
   118  	text := make([]byte, len(cipherText))
   119  	for i, count := 0, len(text)/blockSize; i < count; i++ {
   120  		begin, end := i*blockSize, i*blockSize+blockSize
   121  		block.Decrypt(text[begin:end], cipherText[begin:end])
   122  	}
   123  
   124  	clearText, err := UnPadding(text, padding)
   125  	if err != nil {
   126  		return nil, err
   127  	}
   128  	return clearText, nil
   129  }
   130  
   131  // CBC模式DES加密
   132  func DesCBCEncrypt(key []byte, clearText []byte, iv []byte, padding int) ([]byte, error) {
   133  	block, err := des.NewCipher(key)
   134  	if err != nil {
   135  		return nil, err
   136  	}
   137  
   138  	if len(iv) != block.BlockSize() {
   139  		return nil, errors.New("iv length invalid")
   140  	}
   141  
   142  	text, err := Padding(clearText, padding)
   143  	if err != nil {
   144  		return nil, err
   145  	}
   146  	cipherText := make([]byte, len(text))
   147  
   148  	encrypter := cipher.NewCBCEncrypter(block, iv)
   149  	encrypter.CryptBlocks(cipherText, text)
   150  
   151  	return cipherText, nil
   152  }
   153  
   154  // CBC模式DES解密
   155  func DesCBCDecrypt(key []byte, cipherText []byte, iv []byte, padding int) ([]byte, error) {
   156  	block, err := des.NewCipher(key)
   157  	if err != nil {
   158  		return nil, err
   159  	}
   160  
   161  	if len(iv) != block.BlockSize() {
   162  		return nil, errors.New("iv length invalid")
   163  	}
   164  
   165  	text := make([]byte, len(cipherText))
   166  	decrypter := cipher.NewCBCDecrypter(block, iv)
   167  	decrypter.CryptBlocks(text, cipherText)
   168  
   169  	clearText, err := UnPadding(text, padding)
   170  	if err != nil {
   171  		return nil, err
   172  	}
   173  
   174  	return clearText, nil
   175  }
   176  
   177  // CBC模式3DES加密
   178  func TripleDesCBCEncrypt(key []byte, clearText []byte, iv []byte, padding int) ([]byte, error) {
   179  	if len(key) != 16 && len(key) != 24 {
   180  		return nil, errors.New("key length invalid")
   181  	}
   182  
   183  	var newKey []byte
   184  	if len(key) == 16 {
   185  		newKey = append([]byte{}, key...)
   186  		newKey = append(newKey, key[:8]...)
   187  	} else {
   188  		newKey = append([]byte{}, key...)
   189  	}
   190  
   191  	block, err := des.NewTripleDESCipher(newKey)
   192  	if err != nil {
   193  		return nil, err
   194  	}
   195  
   196  	if len(iv) != block.BlockSize() {
   197  		return nil, errors.New("iv length invalid")
   198  	}
   199  
   200  	text, err := Padding(clearText, padding)
   201  	if err != nil {
   202  		return nil, err
   203  	}
   204  
   205  	cipherText := make([]byte, len(text))
   206  	encrypter := cipher.NewCBCEncrypter(block, iv)
   207  	encrypter.CryptBlocks(cipherText, text)
   208  
   209  	return cipherText, nil
   210  }
   211  
   212  // CBC模式3DES解密
   213  func TripleDesCBCDecrypt(key []byte, cipherText []byte, iv []byte, padding int) ([]byte, error) {
   214  	if len(key) != 16 && len(key) != 24 {
   215  		return nil, errors.New("key length invalid")
   216  	}
   217  
   218  	var newKey []byte
   219  	if len(key) == 16 {
   220  		newKey = append([]byte{}, key...)
   221  		newKey = append(newKey, key[:8]...)
   222  	} else {
   223  		newKey = append([]byte{}, key...)
   224  	}
   225  
   226  	block, err := des.NewTripleDESCipher(newKey)
   227  	if err != nil {
   228  		return nil, err
   229  	}
   230  
   231  	if len(iv) != block.BlockSize() {
   232  		return nil, errors.New("iv length invalid")
   233  	}
   234  
   235  	text := make([]byte, len(cipherText))
   236  	decrypter := cipher.NewCBCDecrypter(block, iv)
   237  	decrypter.CryptBlocks(text, cipherText)
   238  
   239  	clearText, err := UnPadding(text, padding)
   240  	if err != nil {
   241  		return nil, err
   242  	}
   243  
   244  	return clearText, nil
   245  }
   246  
   247  // PKCS5补位
   248  func PKCS5Padding(text []byte, blockSize int) []byte {
   249  	padding := blockSize - len(text)%blockSize
   250  	padtext := bytes.Repeat([]byte{byte(padding)}, padding)
   251  	return append(text, padtext...)
   252  }
   253  
   254  // 去除PKCS5补位
   255  func PKCS5Unpadding(text []byte) []byte {
   256  	length := len(text)
   257  	padtext := int(text[length-1])
   258  	return text[:(length - padtext)]
   259  }
   260  
   261  // 补位方法
   262  func Padding(text []byte, padding int) ([]byte, error) {
   263  	switch padding {
   264  	case NOPADDING:
   265  		if len(text)%8 != 0 {
   266  			return nil, errors.New("text length invalid")
   267  		}
   268  	case PKCS5PADDING:
   269  		return PKCS5Padding(text, 8), nil
   270  	default:
   271  		return nil, errors.New("padding type error")
   272  	}
   273  
   274  	return text, nil
   275  }
   276  
   277  // 去除补位方法
   278  func UnPadding(text []byte, padding int) ([]byte, error) {
   279  	switch padding {
   280  	case NOPADDING:
   281  		if len(text)%8 != 0 {
   282  			return nil, errors.New("text length invalid")
   283  		}
   284  	case PKCS5PADDING:
   285  		return PKCS5Unpadding(text), nil
   286  	default:
   287  		return nil, errors.New("padding type error.")
   288  	}
   289  	return text, nil
   290  }