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