github.com/artpar/rclone@v1.67.3/backend/crypt/pkcs7/pkcs7.go (about)

     1  // Package pkcs7 implements PKCS#7 padding
     2  //
     3  // This is a standard way of encoding variable length buffers into
     4  // buffers which are a multiple of an underlying crypto block size.
     5  package pkcs7
     6  
     7  import "errors"
     8  
     9  // Errors Unpad can return
    10  var (
    11  	ErrorPaddingNotFound      = errors.New("bad PKCS#7 padding - not padded")
    12  	ErrorPaddingNotAMultiple  = errors.New("bad PKCS#7 padding - not a multiple of blocksize")
    13  	ErrorPaddingTooLong       = errors.New("bad PKCS#7 padding - too long")
    14  	ErrorPaddingTooShort      = errors.New("bad PKCS#7 padding - too short")
    15  	ErrorPaddingNotAllTheSame = errors.New("bad PKCS#7 padding - not all the same")
    16  )
    17  
    18  // Pad buf using PKCS#7 to a multiple of n.
    19  //
    20  // Appends the padding to buf - make a copy of it first if you don't
    21  // want it modified.
    22  func Pad(n int, buf []byte) []byte {
    23  	if n <= 1 || n >= 256 {
    24  		panic("bad multiple")
    25  	}
    26  	length := len(buf)
    27  	padding := n - (length % n)
    28  	for i := 0; i < padding; i++ {
    29  		buf = append(buf, byte(padding))
    30  	}
    31  	if (len(buf) % n) != 0 {
    32  		panic("padding failed")
    33  	}
    34  	return buf
    35  }
    36  
    37  // Unpad buf using PKCS#7 from a multiple of n returning a slice of
    38  // buf or an error if malformed.
    39  func Unpad(n int, buf []byte) ([]byte, error) {
    40  	if n <= 1 || n >= 256 {
    41  		panic("bad multiple")
    42  	}
    43  	length := len(buf)
    44  	if length == 0 {
    45  		return nil, ErrorPaddingNotFound
    46  	}
    47  	if (length % n) != 0 {
    48  		return nil, ErrorPaddingNotAMultiple
    49  	}
    50  	padding := int(buf[length-1])
    51  	if padding > n {
    52  		return nil, ErrorPaddingTooLong
    53  	}
    54  	if padding == 0 {
    55  		return nil, ErrorPaddingTooShort
    56  	}
    57  	for i := 0; i < padding; i++ {
    58  		if buf[length-1-i] != byte(padding) {
    59  			return nil, ErrorPaddingNotAllTheSame
    60  		}
    61  	}
    62  	return buf[:length-padding], nil
    63  }