diff options
Diffstat (limited to 'internal/nametransform/pad16.go')
-rw-r--r-- | internal/nametransform/pad16.go | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/internal/nametransform/pad16.go b/internal/nametransform/pad16.go new file mode 100644 index 0000000..c15160e --- /dev/null +++ b/internal/nametransform/pad16.go @@ -0,0 +1,60 @@ +package nametransform + +import ( + "fmt" + "crypto/aes" + "errors" +) + +// pad16 - pad data to AES block size (=16 byte) using standard PKCS#7 padding +// https://tools.ietf.org/html/rfc5652#section-6.3 +func pad16(orig []byte) (padded []byte) { + oldLen := len(orig) + if oldLen == 0 { + panic("Padding zero-length string makes no sense") + } + padLen := aes.BlockSize - oldLen%aes.BlockSize + if padLen == 0 { + padLen = aes.BlockSize + } + newLen := oldLen + padLen + padded = make([]byte, newLen) + copy(padded, orig) + padByte := byte(padLen) + for i := oldLen; i < newLen; i++ { + padded[i] = padByte + } + return padded +} + +// unPad16 - remove padding +func unPad16(padded []byte) ([]byte, error) { + oldLen := len(padded) + if oldLen%aes.BlockSize != 0 { + return nil, errors.New("Unaligned size") + } + // The last byte is always a padding byte + padByte := padded[oldLen-1] + // The padding byte's value is the padding length + padLen := int(padByte) + // Padding must be at least 1 byte + if padLen <= 0 { + return nil, errors.New("Padding cannot be zero-length") + } + // Larger paddings make no sense + if padLen > aes.BlockSize { + return nil, fmt.Errorf("Padding too long, padLen = %d > 16", padLen) + } + // All padding bytes must be identical + for i := oldLen - padLen; i < oldLen; i++ { + if padded[i] != padByte { + return nil, fmt.Errorf("Padding byte at i=%d is invalid", i) + } + } + newLen := oldLen - padLen + // Padding an empty string makes no sense + if newLen == 0 { + return nil, errors.New("Unpadded length is zero") + } + return padded[0:newLen], nil +} |