github.com/bingoohuang/gg@v0.0.0-20240325092523-45da7dee9335/pkg/cry/triple_des.go (about)

     1  package cry
     2  
     3  import (
     4  	"bytes"
     5  	"crypto/cipher"
     6  	"crypto/des"
     7  	"encoding/base64"
     8  
     9  	"github.com/pkg/errors"
    10  )
    11  
    12  // DESOpt contains all DES session option
    13  type DESOpt struct {
    14  	block     cipher.Block
    15  	blockSize []byte
    16  }
    17  
    18  // NewDESOpt is function to create new configuration of des algorithm option
    19  // the secret must be 24 character
    20  func NewDESOpt(secret string) (*DESOpt, error) {
    21  	if len(secret) != 24 {
    22  		return nil, errors.New("secret must be 24 char")
    23  	}
    24  
    25  	/* #nosec */
    26  	block, err := des.NewTripleDESCipher([]byte(secret))
    27  	if err != nil {
    28  		return nil, errors.Wrap(err, "NewDESOpt.des.NewTripleDESCipher")
    29  	}
    30  
    31  	blockSize := secret[:des.BlockSize]
    32  
    33  	return &DESOpt{
    34  		block:     block,
    35  		blockSize: []byte(blockSize),
    36  	}, nil
    37  }
    38  
    39  // Encrypt is function to encrypt data using DES algorithm
    40  func (desOpt *DESOpt) Encrypt(plainText []byte) (string, error) {
    41  	block := desOpt.block
    42  	iv := desOpt.blockSize
    43  	origData := pkcs5Padding(plainText, block.BlockSize())
    44  	mode := cipher.NewCBCEncrypter(block, iv)
    45  	encrypted := make([]byte, len(origData))
    46  	mode.CryptBlocks(encrypted, origData)
    47  	return base64.URLEncoding.EncodeToString(encrypted), nil
    48  }
    49  
    50  // Decrypt is function to decypt data using DES algorithm
    51  func (desOpt *DESOpt) Decrypt(chiperText []byte) (string, error) {
    52  	block := desOpt.block
    53  	rbyte, err := base64.URLEncoding.DecodeString(string(chiperText))
    54  	if err != nil {
    55  		return "", err
    56  	}
    57  	iv := desOpt.blockSize
    58  	decrypter := cipher.NewCBCDecrypter(block, iv)
    59  	decrypted := make([]byte, len(rbyte))
    60  	decrypter.CryptBlocks(decrypted, rbyte)
    61  	decrypted = pkcs5Unpadding(decrypted)
    62  	return string(decrypted), nil
    63  }
    64  
    65  func pkcs5Padding(ciphertext []byte, blockSize int) []byte {
    66  	padding := blockSize - len(ciphertext)%blockSize
    67  	padtext := bytes.Repeat([]byte{byte(padding)}, padding)
    68  	return append(ciphertext, padtext...)
    69  }
    70  
    71  func pkcs5Unpadding(origData []byte) []byte {
    72  	length := len(origData)
    73  	unpadding := int(origData[length-1])
    74  	return origData[:(length - unpadding)]
    75  }