github.com/aacfactory/fns@v1.2.86-0.20240310083819-80d667fc0a17/commons/cryptos/ciphers/padding.go (about)

     1  /*
     2   * Copyright 2023 Wang Min Xiang
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   * 	http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   *
    16   */
    17  
    18  package ciphers
    19  
    20  import (
    21  	"bytes"
    22  	"github.com/aacfactory/errors"
    23  )
    24  
    25  var (
    26  	ErrUnPadding = errors.Warning("cbc: unPadding error")
    27  )
    28  
    29  const (
    30  	ZEROS = iota
    31  	PKCS5
    32  	PKCS7
    33  )
    34  
    35  func Padding(padding int, src []byte, blockSize int) []byte {
    36  	switch padding {
    37  	case PKCS5:
    38  		src = pkcs5Padding(src, blockSize)
    39  	case PKCS7:
    40  		src = pkcs7Padding(src, blockSize)
    41  	case ZEROS:
    42  		src = zerosPadding(src, blockSize)
    43  	}
    44  	return src
    45  }
    46  
    47  func UnPadding(padding int, src []byte) ([]byte, error) {
    48  	switch padding {
    49  	case PKCS5:
    50  		return pkcs5UnPadding(src)
    51  	case PKCS7:
    52  		return pkcs7UnPadding(src)
    53  	case ZEROS:
    54  		return zerosUnPadding(src)
    55  	}
    56  	return src, nil
    57  }
    58  
    59  func pkcs5Padding(src []byte, blockSize int) []byte {
    60  	return pkcs7Padding(src, blockSize)
    61  }
    62  
    63  func pkcs5UnPadding(src []byte) ([]byte, error) {
    64  	return pkcs7UnPadding(src)
    65  }
    66  
    67  func pkcs7Padding(src []byte, blockSize int) []byte {
    68  	padding := blockSize - len(src)%blockSize
    69  	paddings := bytes.Repeat([]byte{byte(padding)}, padding)
    70  	return append(src, paddings...)
    71  }
    72  
    73  func pkcs7UnPadding(src []byte) ([]byte, error) {
    74  	length := len(src)
    75  	if length == 0 {
    76  		return src, ErrUnPadding
    77  	}
    78  	unPadding := int(src[length-1])
    79  	if length < unPadding {
    80  		return src, ErrUnPadding
    81  	}
    82  	return src[:(length - unPadding)], nil
    83  }
    84  
    85  func zerosPadding(src []byte, blockSize int) []byte {
    86  	paddingCount := blockSize - len(src)%blockSize
    87  	if paddingCount == 0 {
    88  		return src
    89  	} else {
    90  		return append(src, bytes.Repeat([]byte{byte(0)}, paddingCount)...)
    91  	}
    92  }
    93  
    94  func zerosUnPadding(src []byte) ([]byte, error) {
    95  	for i := len(src) - 1; ; i-- {
    96  		if src[i] != 0 {
    97  			return src[:i+1], nil
    98  		}
    99  	}
   100  }