129 lines
3.3 KiB
Go
129 lines
3.3 KiB
Go
|
|
package paddingx
|
||
|
|
|
||
|
|
import (
|
||
|
|
"bytes"
|
||
|
|
"errors"
|
||
|
|
"strings"
|
||
|
|
)
|
||
|
|
|
||
|
|
const (
|
||
|
|
PKCS5 = "PKCS5"
|
||
|
|
PKCS7 = "PKCS7"
|
||
|
|
ZERO = "ZERO"
|
||
|
|
ANSIX923 = "ANSIX923"
|
||
|
|
)
|
||
|
|
|
||
|
|
func Pad(data []byte, blockSize int, mode string) ([]byte, error) {
|
||
|
|
if blockSize <= 0 {
|
||
|
|
return nil, errors.New("block size must be greater than zero")
|
||
|
|
}
|
||
|
|
switch normalizeMode(mode) {
|
||
|
|
case "", PKCS7:
|
||
|
|
return PKCS7Padding(data, blockSize), nil
|
||
|
|
case PKCS5:
|
||
|
|
// Compatibility mode: historically PKCS5 was used generically in this project.
|
||
|
|
return PKCS7Padding(data, blockSize), nil
|
||
|
|
case ZERO:
|
||
|
|
return zeroPadding(data, blockSize), nil
|
||
|
|
case ANSIX923:
|
||
|
|
return ansiX923Padding(data, blockSize), nil
|
||
|
|
default:
|
||
|
|
return nil, errors.New("padding type not supported")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func Unpad(data []byte, blockSize int, mode string) ([]byte, error) {
|
||
|
|
if blockSize <= 0 {
|
||
|
|
return nil, errors.New("block size must be greater than zero")
|
||
|
|
}
|
||
|
|
switch normalizeMode(mode) {
|
||
|
|
case "", PKCS7:
|
||
|
|
return PKCS7Unpadding(data, blockSize)
|
||
|
|
case PKCS5:
|
||
|
|
// Compatibility mode: historically PKCS5 was used generically in this project.
|
||
|
|
return PKCS7Unpadding(data, blockSize)
|
||
|
|
case ZERO:
|
||
|
|
return zeroUnpadding(data)
|
||
|
|
case ANSIX923:
|
||
|
|
return ansiX923Unpadding(data, blockSize)
|
||
|
|
default:
|
||
|
|
return nil, errors.New("padding type not supported")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func PKCS7Padding(data []byte, blockSize int) []byte {
|
||
|
|
padding := blockSize - len(data)%blockSize
|
||
|
|
padText := bytes.Repeat([]byte{byte(padding)}, padding)
|
||
|
|
return append(data, padText...)
|
||
|
|
}
|
||
|
|
|
||
|
|
func PKCS7Unpadding(data []byte, blockSize int) ([]byte, error) {
|
||
|
|
if len(data) == 0 || len(data)%blockSize != 0 {
|
||
|
|
return nil, errors.New("invalid PKCS7 padding")
|
||
|
|
}
|
||
|
|
padding := int(data[len(data)-1])
|
||
|
|
if padding <= 0 || padding > blockSize || padding > len(data) {
|
||
|
|
return nil, errors.New("invalid PKCS7 padding")
|
||
|
|
}
|
||
|
|
for i := len(data) - padding; i < len(data); i++ {
|
||
|
|
if int(data[i]) != padding {
|
||
|
|
return nil, errors.New("invalid PKCS7 padding")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return data[:len(data)-padding], nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func PKCS5Padding(data []byte) []byte {
|
||
|
|
return PKCS7Padding(data, 8)
|
||
|
|
}
|
||
|
|
|
||
|
|
func PKCS5Unpadding(data []byte) ([]byte, error) {
|
||
|
|
return PKCS7Unpadding(data, 8)
|
||
|
|
}
|
||
|
|
|
||
|
|
func zeroPadding(data []byte, blockSize int) []byte {
|
||
|
|
padding := blockSize - len(data)%blockSize
|
||
|
|
if padding == blockSize {
|
||
|
|
return data
|
||
|
|
}
|
||
|
|
return append(data, bytes.Repeat([]byte{0x00}, padding)...)
|
||
|
|
}
|
||
|
|
|
||
|
|
func zeroUnpadding(data []byte) ([]byte, error) {
|
||
|
|
idx := len(data)
|
||
|
|
for idx > 0 && data[idx-1] == 0x00 {
|
||
|
|
idx--
|
||
|
|
}
|
||
|
|
return data[:idx], nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func ansiX923Padding(data []byte, blockSize int) []byte {
|
||
|
|
padding := blockSize - len(data)%blockSize
|
||
|
|
if padding == 0 {
|
||
|
|
padding = blockSize
|
||
|
|
}
|
||
|
|
pad := make([]byte, padding)
|
||
|
|
pad[len(pad)-1] = byte(padding)
|
||
|
|
return append(data, pad...)
|
||
|
|
}
|
||
|
|
|
||
|
|
func ansiX923Unpadding(data []byte, blockSize int) ([]byte, error) {
|
||
|
|
if len(data) == 0 || len(data)%blockSize != 0 {
|
||
|
|
return nil, errors.New("invalid ANSI X9.23 padding")
|
||
|
|
}
|
||
|
|
padding := int(data[len(data)-1])
|
||
|
|
if padding <= 0 || padding > blockSize || padding > len(data) {
|
||
|
|
return nil, errors.New("invalid ANSI X9.23 padding")
|
||
|
|
}
|
||
|
|
for i := len(data) - padding; i < len(data)-1; i++ {
|
||
|
|
if data[i] != 0x00 {
|
||
|
|
return nil, errors.New("invalid ANSI X9.23 padding")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return data[:len(data)-padding], nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func normalizeMode(mode string) string {
|
||
|
|
return strings.ToUpper(strings.TrimSpace(mode))
|
||
|
|
}
|