Skip to content

Commit a2b2199

Browse files
committed
refacto: Added rust PKCS7Unpadding
refacto: removed check_pkcs7_padding function refacto: removed python _PKCS7Unpadding
1 parent e343723 commit a2b2199

File tree

5 files changed

+70
-26
lines changed

5 files changed

+70
-26
lines changed

src/cryptography/hazmat/bindings/_rust/__init__.pyi

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,18 @@ import typing
66

77
from cryptography.hazmat.primitives import padding
88

9-
def check_pkcs7_padding(data: bytes) -> bool: ...
109
def check_ansix923_padding(data: bytes) -> bool: ...
1110

1211
class PKCS7PaddingContext(padding.PaddingContext):
1312
def __init__(self, block_size: int) -> None: ...
1413
def update(self, data: bytes) -> bytes: ...
1514
def finalize(self) -> bytes: ...
1615

16+
class PKCS7UnpaddingContext(padding.PaddingContext):
17+
def __init__(self, block_size: int) -> None: ...
18+
def update(self, data: bytes) -> bytes: ...
19+
def finalize(self) -> bytes: ...
20+
1721
class ObjectIdentifier:
1822
def __init__(self, val: str) -> None: ...
1923
@property

src/cryptography/hazmat/primitives/padding.py

Lines changed: 3 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
from cryptography.exceptions import AlreadyFinalized
1212
from cryptography.hazmat.bindings._rust import (
1313
PKCS7PaddingContext,
14+
PKCS7UnpaddingContext,
1415
check_ansix923_padding,
15-
check_pkcs7_padding,
1616
)
1717

1818

@@ -115,32 +115,11 @@ def padder(self) -> PaddingContext:
115115
return PKCS7PaddingContext(self.block_size)
116116

117117
def unpadder(self) -> PaddingContext:
118-
return _PKCS7UnpaddingContext(self.block_size)
119-
120-
121-
class _PKCS7UnpaddingContext(PaddingContext):
122-
_buffer: bytes | None
123-
124-
def __init__(self, block_size: int):
125-
self.block_size = block_size
126-
# TODO: more copies than necessary, we should use zero-buffer (#193)
127-
self._buffer = b""
128-
129-
def update(self, data: bytes) -> bytes:
130-
self._buffer, result = _byte_unpadding_update(
131-
self._buffer, data, self.block_size
132-
)
133-
return result
134-
135-
def finalize(self) -> bytes:
136-
result = _byte_unpadding_check(
137-
self._buffer, self.block_size, check_pkcs7_padding
138-
)
139-
self._buffer = None
140-
return result
118+
return PKCS7UnpaddingContext(self.block_size)
141119

142120

143121
PaddingContext.register(PKCS7PaddingContext)
122+
PaddingContext.register(PKCS7UnpaddingContext)
144123

145124

146125
class ANSIX923:

src/rust/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ mod _rust {
102102
#[pymodule_export]
103103
use crate::oid::ObjectIdentifier;
104104
#[pymodule_export]
105-
use crate::padding::{check_ansix923_padding, check_pkcs7_padding, PKCS7PaddingContext};
105+
use crate::padding::{check_ansix923_padding, PKCS7PaddingContext, PKCS7UnpaddingContext};
106106
#[pymodule_export]
107107
use crate::pkcs12::pkcs12;
108108
#[pymodule_export]

src/rust/src/padding.rs

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,65 @@ impl PKCS7PaddingContext {
111111
}
112112
}
113113

114+
#[pyo3::pyclass]
115+
pub(crate) struct PKCS7UnpaddingContext {
116+
block_size: usize,
117+
buffer: Option<Vec<u8>>,
118+
}
119+
120+
#[pyo3::pymethods]
121+
impl PKCS7UnpaddingContext {
122+
#[new]
123+
pub(crate) fn new(block_size: usize) -> PKCS7UnpaddingContext {
124+
PKCS7UnpaddingContext {
125+
block_size: block_size / 8,
126+
buffer: Some(Vec::new()),
127+
}
128+
}
129+
130+
pub(crate) fn update<'a>(
131+
&mut self,
132+
py: pyo3::Python<'a>,
133+
buf: CffiBuf<'a>,
134+
) -> CryptographyResult<pyo3::Bound<'a, pyo3::types::PyBytes>> {
135+
match self.buffer.as_mut() {
136+
Some(v) => {
137+
v.extend_from_slice(buf.as_bytes());
138+
let finished_blocks = (v.len() / self.block_size).saturating_sub(1);
139+
let result_size = finished_blocks * self.block_size;
140+
let result: Vec<u8> = v.drain(..result_size).collect();
141+
Ok(pyo3::types::PyBytes::new_bound(py, &result))
142+
}
143+
None => Err(exceptions::already_finalized_error()),
144+
}
145+
}
146+
147+
pub(crate) fn finalize<'p>(
148+
&mut self,
149+
py: pyo3::Python<'p>,
150+
) -> CryptographyResult<pyo3::Bound<'p, pyo3::types::PyBytes>> {
151+
match self.buffer.take() {
152+
Some(v) => {
153+
if v.len() != self.block_size {
154+
return Err(
155+
pyo3::exceptions::PyValueError::new_err("Invalid padding bytes.").into(),
156+
);
157+
}
158+
if !check_pkcs7_padding(&v) {
159+
return Err(
160+
pyo3::exceptions::PyValueError::new_err("Invalid padding bytes.").into(),
161+
);
162+
}
163+
164+
let pad_size = *v.last().unwrap();
165+
let result = v[..v.len() - pad_size as usize].to_vec();
166+
Ok(pyo3::types::PyBytes::new_bound(py, &result))
167+
}
168+
None => Err(exceptions::already_finalized_error()),
169+
}
170+
}
171+
}
172+
114173
#[cfg(test)]
115174
mod tests {
116175
use super::constant_time_lt;

tests/hazmat/primitives/test_padding.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ def test_pad(self, size, unpadded, padded):
8080
b"111111111111111122222222222222",
8181
b"111111111111111122222222222222\x02\x02",
8282
),
83+
(128, b"1" * 16, b"1" * 16 + b"\x10" * 16),
84+
(128, b"1" * 17, b"1" * 17 + b"\x0f" * 15),
8385
],
8486
)
8587
def test_unpad(self, size, unpadded, padded):

0 commit comments

Comments
 (0)