1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
//! External padding for batch unlinkability.
//!
//! This module provides functions to create and detect external padding blocks used by the
//! `pad_to()` method on long data types for batch unlinkability.
//!
//! # Purpose
//!
//! External padding normalizes different-sized values to identical structure for unlinkable batch transcryption.
//!
//! # When Used
//!
//! - Explicitly via the `pad_to(n)` method on long types
//! - Only for multi-block data (see [`long`](crate::data::long) module)
//! - Required when batch processing needs unlinkability guarantees
//!
//! # How It Works
//!
//! - Adds full 16-byte all-zero blocks after the data
//! - Format: `[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]`
//! - During decoding, scans backwards from the end removing all-zero blocks until a data block is found
//! - Automatically detected and removed during decoding
//!
//! # Order of Operations
//!
//! **Encoding:**
//! 1. PKCS#7 padding is applied first to the last data block
//! 2. All-zero external padding blocks are added after
//!
//! **Decoding:**
//! 1. Scan backwards from the end, removing all-zero blocks
//! 2. Stop when a non-zero block is found (the last data block with PKCS#7 padding)
//! 3. Remove PKCS#7 padding from the last data block
//!
//! This ordering ensures that even if data is all zeros, PKCS#7 padding will change the last
//! byte to `0x01`-`0x10`, guaranteeing it won't be detected as an external padding block.
//!
//! # Example
//!
//! ```text
//! After pad_to(3):
//! Block 1: [h e l l o | 0x0B 0x0B 0x0B 0x0B 0x0B 0x0B 0x0B 0x0B 0x0B 0x0B 0x0B] ← data with PKCS#7
//! Block 2: [0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00] ← padding
//! Block 3: [0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00] ← padding
//! ```
//!
//! # Disambiguation Guarantee
//!
//! External padding blocks are **all zeros**, while PKCS#7 padded blocks **never** have `0x00`
//! in the last byte (valid PKCS#7 padding: `0x01`-`0x10`).
//!
//! Because PKCS#7 padding is applied first during encoding, it **always** changes the last
//! byte of any data block to `0x01`-`0x10`. This deterministically prevents any data from being
//! mistaken for an external padding block.
//!
//! This means **ALL possible byte sequences can be encoded without ambiguity**, including values
//! that are all zeros (PKCS#7 changes the last byte)
/// Creates an external padding block.
///
/// Format: [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
///
/// All-zero blocks are impossible for PKCS#7 padded data blocks (valid padding bytes are 0x01-0x10),
/// making this unambiguous.
pub
/// Checks if a block is an external padding block.
///
/// Returns `true` if this block is all zeros (external padding),
/// or `false` if this is a regular data block.
///
/// # Disambiguation Guarantee
///
/// - External padding blocks are **all zeros**
/// - PKCS#7 padded data blocks **never** have `0x00` in the last byte (valid padding: `0x01`-`0x10`)
///
/// This means **ALL possible byte sequences can be encoded without ambiguity**, including:
/// - Data blocks that are all zeros except the last byte (PKCS#7 will set last byte to 0x01-0x10)
/// - Any combination of bytes whatsoever
pub