|
2 | 2 | # Implements PKCS7 padding and unpadding |
3 | 3 |
|
4 | 4 | def _byte_padding_check(block_size): |
5 | | - """Validate block size for padding.""" |
6 | 5 | if not (0 <= block_size <= 2040): |
7 | 6 | raise ValueError("block_size must be in range(0, 2041).") |
8 | 7 | if block_size % 8 != 0: |
9 | 8 | raise ValueError("block_size must be a multiple of 8.") |
10 | 9 |
|
11 | 10 | class PKCS7PaddingContext: |
12 | | - """Handles PKCS7 padding.""" |
13 | 11 | def __init__(self, block_size): |
14 | 12 | _byte_padding_check(block_size) |
15 | | - self.block_size = block_size // 8 # Convert bits to bytes |
| 13 | + self.block_size = block_size // 8 |
16 | 14 | self._buffer = bytearray() |
17 | 15 |
|
18 | 16 | def update(self, data): |
19 | 17 | self._buffer.extend(data) |
20 | | - # Return full blocks |
21 | 18 | block_size = self.block_size |
22 | 19 | if len(self._buffer) >= block_size: |
23 | 20 | to_return = self._buffer[:len(self._buffer) - (len(self._buffer) % block_size)] |
24 | 21 | self._buffer = self._buffer[len(to_return):] |
| 22 | + print(f"PKCS7PaddingContext.update returning: {to_return.hex()}") |
25 | 23 | return to_return |
| 24 | + print(f"PKCS7PaddingContext.update buffer: {self._buffer.hex()}") |
26 | 25 | return b'' |
27 | 26 |
|
28 | 27 | def finalize(self): |
29 | | - # Pad with bytes equal to padding length |
30 | 28 | pad_length = self.block_size - (len(self._buffer) % self.block_size) |
31 | 29 | padding = bytes([pad_length] * pad_length) |
32 | 30 | self._buffer.extend(padding) |
33 | 31 | result = bytes(self._buffer) |
| 32 | + print(f"PKCS7PaddingContext.finalize pad_length: {pad_length}, padding: {padding.hex()}, result: {result.hex()}") |
34 | 33 | self._buffer = bytearray() |
35 | 34 | return result |
36 | 35 |
|
37 | 36 | class PKCS7UnpaddingContext: |
38 | | - """Handles PKCS7 unpadding.""" |
39 | 37 | def __init__(self, block_size): |
40 | 38 | _byte_padding_check(block_size) |
41 | 39 | self.block_size = block_size // 8 |
42 | 40 | self._buffer = bytearray() |
43 | 41 |
|
44 | 42 | def update(self, data): |
45 | 43 | self._buffer.extend(data) |
46 | | - # Only process complete blocks |
| 44 | + print(f"unpadder self._buffer is {self._buffer.hex()}") |
47 | 45 | block_size = self.block_size |
48 | | - if len(self._buffer) >= block_size: |
49 | | - to_return = self._buffer[:len(self._buffer) - (len(self._buffer) % block_size)] |
| 46 | + # Return all complete blocks except the last one |
| 47 | + if len(self._buffer) >= block_size * 2: # At least two blocks |
| 48 | + to_return = self._buffer[:len(self._buffer) - block_size] |
50 | 49 | self._buffer = self._buffer[len(to_return):] |
| 50 | + print(f"unpadder self._buffer is now {self._buffer.hex()} and returning {to_return.hex()}") |
51 | 51 | return to_return |
| 52 | + print(f"unpadder self._buffer retained: {self._buffer.hex()}") |
52 | 53 | return b'' |
53 | 54 |
|
54 | 55 | def finalize(self): |
| 56 | + print(f"unpadder finalize self._buffer: {self._buffer.hex()}") |
55 | 57 | if not self._buffer or len(self._buffer) % self.block_size != 0: |
56 | | - raise ValueError("Invalid padding") |
| 58 | + raise ValueError(f"Invalid padding A: buffer {self._buffer.hex()}, length {len(self._buffer)}, remainder {len(self._buffer) % self.block_size}") |
57 | 59 | pad_length = self._buffer[-1] |
| 60 | + print(f"unpadder finalize pad_length: {pad_length}, last {pad_length} bytes: {self._buffer[-pad_length:].hex()}") |
58 | 61 | if pad_length > self.block_size or pad_length == 0: |
59 | | - raise ValueError("Invalid padding") |
| 62 | + raise ValueError(f"Invalid padding B: pad_length {pad_length}") |
60 | 63 | if self._buffer[-pad_length:] != bytes([pad_length] * pad_length): |
61 | | - raise ValueError("Invalid padding") |
| 64 | + raise ValueError(f"Invalid padding C: expected {pad_length} bytes of {pad_length:02x}, got {self._buffer[-pad_length:].hex()}") |
62 | 65 | result = bytes(self._buffer[:-pad_length]) |
63 | 66 | self._buffer = bytearray() |
| 67 | + print(f"unpadder finalize result: {result.hex()}") |
64 | 68 | return result |
65 | 69 |
|
66 | 70 | class PKCS7: |
67 | | - """PKCS7 padding implementation.""" |
68 | 71 | def __init__(self, block_size): |
69 | 72 | _byte_padding_check(block_size) |
70 | 73 | self.block_size = block_size |
|
0 commit comments