Last active
October 3, 2023 06:55
-
-
Save nanmu42/b838acc10d393bc51cb861128ce7f89c to your computer and use it in GitHub Desktop.
Golang PKCS7 Padding/Unpadding
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// pkcs7strip remove pkcs7 padding | |
func pkcs7strip(data []byte, blockSize int) ([]byte, error) { | |
length := len(data) | |
if length == 0 { | |
return nil, errors.New("pkcs7: Data is empty") | |
} | |
if length%blockSize != 0 { | |
return nil, errors.New("pkcs7: Data is not block-aligned") | |
} | |
padLen := int(data[length-1]) | |
ref := bytes.Repeat([]byte{byte(padLen)}, padLen) | |
if padLen > blockSize || padLen == 0 || !bytes.HasSuffix(data, ref) { | |
return nil, errors.New("pkcs7: Invalid padding") | |
} | |
return data[:length-padLen], nil | |
} | |
// pkcs7pad add pkcs7 padding | |
func pkcs7pad(data []byte, blockSize int) ([]byte, error) { | |
if blockSize <= 1 || blockSize >= 256 { | |
return nil, fmt.Errorf("pkcs7: Invalid block size %d", blockSize) | |
} else { | |
padLen := blockSize - len(data) % blockSize | |
padding := bytes.Repeat([]byte{byte(padLen)}, padLen) | |
return append(data, padding...), nil | |
} | |
} |
So current implementation is correct, yes?
padLen := blockSize - len(data) % blockSize
It is effectively the same as:
padLen := blockSize - (len(data) % blockSize)
if we use
padLen := (blockSize - len(data)) % blockSize
len(data)
could be greater than blockSize and produces minus result.
https://www.rfc-editor.org/rfc/rfc2315
There is an error in line 20 of the code, as described on page 21 of this link.
Kaliski Informational [Page 21]
[RFC 2315](https://www.rfc-editor.org/rfc/rfc2315) PKCS #7: Crytographic Message Syntax March 1998
2. Some content-encryption algorithms assume the
input length is a multiple of k octets, where k > 1, and
let the application define a method for handling inputs
whose lengths are not a multiple of k octets. For such
algorithms, the method shall be to pad the input at the
trailing end with k - (l mod k) octets all having value k -
(l mod k), where l is the length of the input. In other
words, the input is padded at the trailing end with one of
the following strings:
01 -- if l mod k = k-1
02 02 -- if l mod k = k-2
.
.
.
k k ... k k -- if l mod k = 0
The padding can be removed unambiguously since all input is
padded and no padding string is a suffix of another. This
padding method is well-defined if and only if k < 256;
methods for larger k are an open issue for further study.
https://www.rfc-editor.org/rfc/rfc2315
There is an error in line 20 of the code, as described on page 21 of this link.
Hi @aimuz , thanks for your feedback. What change should be made? Is it this?
if blockSize <= 1 || blockSize >= 256 {
Yes, I think that should be the case
Yes, I think that should be the case
Thanks, I have updated the gist per your suggestion.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The original code is correct. If the data is an integral number of blocks there should be a full block of padding. It’s necessary in order for the last byte to make sense.