github.com/gogf/gf@v1.16.9/crypto/gdes/gdes.go (about)

     1  // Copyright GoFrame Author(https://goframe.org). 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/gogf/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  	"github.com/gogf/gf/errors/gcode"
    15  	"github.com/gogf/gf/errors/gerror"
    16  )
    17  
    18  const (
    19  	NOPADDING = iota
    20  	PKCS5PADDING
    21  )
    22  
    23  // EncryptECB encrypts <plainText> using ECB mode.
    24  func EncryptECB(plainText []byte, key []byte, padding int) ([]byte, error) {
    25  	text, err := Padding(plainText, padding)
    26  	if err != nil {
    27  		return nil, err
    28  	}
    29  
    30  	cipherText := make([]byte, len(text))
    31  
    32  	block, err := des.NewCipher(key)
    33  	if err != nil {
    34  		return nil, err
    35  	}
    36  
    37  	blockSize := block.BlockSize()
    38  	for i, count := 0, len(text)/blockSize; i < count; i++ {
    39  		begin, end := i*blockSize, i*blockSize+blockSize
    40  		block.Encrypt(cipherText[begin:end], text[begin:end])
    41  	}
    42  	return cipherText, nil
    43  }
    44  
    45  // DecryptECB decrypts <cipherText> using ECB mode.
    46  func DecryptECB(cipherText []byte, key []byte, padding int) ([]byte, error) {
    47  	text := make([]byte, len(cipherText))
    48  	block, err := des.NewCipher(key)
    49  	if err != nil {
    50  		return nil, err
    51  	}
    52  
    53  	blockSize := block.BlockSize()
    54  	for i, count := 0, len(text)/blockSize; i < count; i++ {
    55  		begin, end := i*blockSize, i*blockSize+blockSize
    56  		block.Decrypt(text[begin:end], cipherText[begin:end])
    57  	}
    58  
    59  	plainText, err := UnPadding(text, padding)
    60  	if err != nil {
    61  		return nil, err
    62  	}
    63  	return plainText, nil
    64  }
    65  
    66  // EncryptECBTriple encrypts <plainText> using TripleDES and ECB mode.
    67  // The length of the <key> should be either 16 or 24 bytes.
    68  func EncryptECBTriple(plainText []byte, key []byte, padding int) ([]byte, error) {
    69  	if len(key) != 16 && len(key) != 24 {
    70  		return nil, gerror.NewCode(gcode.CodeInvalidParameter, "key length error")
    71  	}
    72  
    73  	text, err := Padding(plainText, padding)
    74  	if err != nil {
    75  		return nil, err
    76  	}
    77  
    78  	var newKey []byte
    79  	if len(key) == 16 {
    80  		newKey = append([]byte{}, key...)
    81  		newKey = append(newKey, key[:8]...)
    82  	} else {
    83  		newKey = append([]byte{}, key...)
    84  	}
    85  
    86  	block, err := des.NewTripleDESCipher(newKey)
    87  	if err != nil {
    88  		return nil, err
    89  	}
    90  
    91  	blockSize := block.BlockSize()
    92  	cipherText := make([]byte, len(text))
    93  	for i, count := 0, len(text)/blockSize; i < count; i++ {
    94  		begin, end := i*blockSize, i*blockSize+blockSize
    95  		block.Encrypt(cipherText[begin:end], text[begin:end])
    96  	}
    97  	return cipherText, nil
    98  }
    99  
   100  // DecryptECBTriple decrypts <cipherText> using TripleDES and ECB mode.
   101  // The length of the <key> should be either 16 or 24 bytes.
   102  func DecryptECBTriple(cipherText []byte, key []byte, padding int) ([]byte, error) {
   103  	if len(key) != 16 && len(key) != 24 {
   104  		return nil, gerror.NewCode(gcode.CodeInvalidParameter, "key length error")
   105  	}
   106  
   107  	var newKey []byte
   108  	if len(key) == 16 {
   109  		newKey = append([]byte{}, key...)
   110  		newKey = append(newKey, key[:8]...)
   111  	} else {
   112  		newKey = append([]byte{}, key...)
   113  	}
   114  
   115  	block, err := des.NewTripleDESCipher(newKey)
   116  	if err != nil {
   117  		return nil, err
   118  	}
   119  
   120  	blockSize := block.BlockSize()
   121  	text := make([]byte, len(cipherText))
   122  	for i, count := 0, len(text)/blockSize; i < count; i++ {
   123  		begin, end := i*blockSize, i*blockSize+blockSize
   124  		block.Decrypt(text[begin:end], cipherText[begin:end])
   125  	}
   126  
   127  	plainText, err := UnPadding(text, padding)
   128  	if err != nil {
   129  		return nil, err
   130  	}
   131  	return plainText, nil
   132  }
   133  
   134  // EncryptCBC encrypts <plainText> using CBC mode.
   135  func EncryptCBC(plainText []byte, key []byte, iv []byte, padding int) ([]byte, error) {
   136  	block, err := des.NewCipher(key)
   137  	if err != nil {
   138  		return nil, err
   139  	}
   140  
   141  	if len(iv) != block.BlockSize() {
   142  		return nil, gerror.NewCode(gcode.CodeInvalidParameter, "iv length invalid")
   143  	}
   144  
   145  	text, err := Padding(plainText, padding)
   146  	if err != nil {
   147  		return nil, err
   148  	}
   149  	cipherText := make([]byte, len(text))
   150  
   151  	encrypter := cipher.NewCBCEncrypter(block, iv)
   152  	encrypter.CryptBlocks(cipherText, text)
   153  
   154  	return cipherText, nil
   155  }
   156  
   157  // DecryptCBC decrypts <cipherText> using CBC mode.
   158  func DecryptCBC(cipherText []byte, key []byte, iv []byte, padding int) ([]byte, error) {
   159  	block, err := des.NewCipher(key)
   160  	if err != nil {
   161  		return nil, err
   162  	}
   163  
   164  	if len(iv) != block.BlockSize() {
   165  		return nil, gerror.NewCode(gcode.CodeInvalidParameter, "iv length invalid")
   166  	}
   167  
   168  	text := make([]byte, len(cipherText))
   169  	decrypter := cipher.NewCBCDecrypter(block, iv)
   170  	decrypter.CryptBlocks(text, cipherText)
   171  
   172  	plainText, err := UnPadding(text, padding)
   173  	if err != nil {
   174  		return nil, err
   175  	}
   176  
   177  	return plainText, nil
   178  }
   179  
   180  // EncryptCBCTriple encrypts <plainText> using TripleDES and CBC mode.
   181  func EncryptCBCTriple(plainText []byte, key []byte, iv []byte, padding int) ([]byte, error) {
   182  	if len(key) != 16 && len(key) != 24 {
   183  		return nil, gerror.NewCode(gcode.CodeInvalidParameter, "key length invalid")
   184  	}
   185  
   186  	var newKey []byte
   187  	if len(key) == 16 {
   188  		newKey = append([]byte{}, key...)
   189  		newKey = append(newKey, key[:8]...)
   190  	} else {
   191  		newKey = append([]byte{}, key...)
   192  	}
   193  
   194  	block, err := des.NewTripleDESCipher(newKey)
   195  	if err != nil {
   196  		return nil, err
   197  	}
   198  
   199  	if len(iv) != block.BlockSize() {
   200  		return nil, gerror.NewCode(gcode.CodeInvalidParameter, "iv length invalid")
   201  	}
   202  
   203  	text, err := Padding(plainText, padding)
   204  	if err != nil {
   205  		return nil, err
   206  	}
   207  
   208  	cipherText := make([]byte, len(text))
   209  	encrypter := cipher.NewCBCEncrypter(block, iv)
   210  	encrypter.CryptBlocks(cipherText, text)
   211  
   212  	return cipherText, nil
   213  }
   214  
   215  // DecryptCBCTriple decrypts <cipherText> using TripleDES and CBC mode.
   216  func DecryptCBCTriple(cipherText []byte, key []byte, iv []byte, padding int) ([]byte, error) {
   217  	if len(key) != 16 && len(key) != 24 {
   218  		return nil, gerror.NewCode(gcode.CodeInvalidParameter, "key length invalid")
   219  	}
   220  
   221  	var newKey []byte
   222  	if len(key) == 16 {
   223  		newKey = append([]byte{}, key...)
   224  		newKey = append(newKey, key[:8]...)
   225  	} else {
   226  		newKey = append([]byte{}, key...)
   227  	}
   228  
   229  	block, err := des.NewTripleDESCipher(newKey)
   230  	if err != nil {
   231  		return nil, err
   232  	}
   233  
   234  	if len(iv) != block.BlockSize() {
   235  		return nil, gerror.NewCode(gcode.CodeInvalidParameter, "iv length invalid")
   236  	}
   237  
   238  	text := make([]byte, len(cipherText))
   239  	decrypter := cipher.NewCBCDecrypter(block, iv)
   240  	decrypter.CryptBlocks(text, cipherText)
   241  
   242  	plainText, err := UnPadding(text, padding)
   243  	if err != nil {
   244  		return nil, err
   245  	}
   246  
   247  	return plainText, nil
   248  }
   249  
   250  func PaddingPKCS5(text []byte, blockSize int) []byte {
   251  	padding := blockSize - len(text)%blockSize
   252  	padText := bytes.Repeat([]byte{byte(padding)}, padding)
   253  	return append(text, padText...)
   254  }
   255  
   256  func UnPaddingPKCS5(text []byte) []byte {
   257  	length := len(text)
   258  	padText := int(text[length-1])
   259  	return text[:(length - padText)]
   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, gerror.NewCode(gcode.CodeInvalidParameter, "text length invalid")
   267  		}
   268  	case PKCS5PADDING:
   269  		return PaddingPKCS5(text, 8), nil
   270  	default:
   271  		return nil, gerror.NewCode(gcode.CodeInvalidParameter, "padding type error")
   272  	}
   273  
   274  	return text, nil
   275  }
   276  
   277  func UnPadding(text []byte, padding int) ([]byte, error) {
   278  	switch padding {
   279  	case NOPADDING:
   280  		if len(text)%8 != 0 {
   281  			return nil, gerror.NewCode(gcode.CodeInvalidParameter, "text length invalid")
   282  		}
   283  	case PKCS5PADDING:
   284  		return UnPaddingPKCS5(text), nil
   285  	default:
   286  		return nil, gerror.NewCode(gcode.CodeInvalidParameter, "padding type error")
   287  	}
   288  	return text, nil
   289  }