This commit is contained in:
Iliyan Angelov
2025-11-19 12:27:01 +02:00
parent 2043ac897c
commit 34b4c969d4
469 changed files with 26870 additions and 8329 deletions

View File

@@ -5,19 +5,19 @@
from __future__ import annotations
import abc
import typing
from cryptography import utils
from cryptography.exceptions import AlreadyFinalized
from cryptography.hazmat.bindings._rust import (
check_ansix923_padding,
check_pkcs7_padding,
ANSIX923PaddingContext,
ANSIX923UnpaddingContext,
PKCS7PaddingContext,
PKCS7UnpaddingContext,
)
class PaddingContext(metaclass=abc.ABCMeta):
@abc.abstractmethod
def update(self, data: bytes) -> bytes:
def update(self, data: utils.Buffer) -> bytes:
"""
Pads the provided bytes and returns any available data as bytes.
"""
@@ -37,131 +37,20 @@ def _byte_padding_check(block_size: int) -> None:
raise ValueError("block_size must be a multiple of 8.")
def _byte_padding_update(
buffer_: typing.Optional[bytes], data: bytes, block_size: int
) -> typing.Tuple[bytes, bytes]:
if buffer_ is None:
raise AlreadyFinalized("Context was already finalized.")
utils._check_byteslike("data", data)
buffer_ += bytes(data)
finished_blocks = len(buffer_) // (block_size // 8)
result = buffer_[: finished_blocks * (block_size // 8)]
buffer_ = buffer_[finished_blocks * (block_size // 8) :]
return buffer_, result
def _byte_padding_pad(
buffer_: typing.Optional[bytes],
block_size: int,
paddingfn: typing.Callable[[int], bytes],
) -> bytes:
if buffer_ is None:
raise AlreadyFinalized("Context was already finalized.")
pad_size = block_size // 8 - len(buffer_)
return buffer_ + paddingfn(pad_size)
def _byte_unpadding_update(
buffer_: typing.Optional[bytes], data: bytes, block_size: int
) -> typing.Tuple[bytes, bytes]:
if buffer_ is None:
raise AlreadyFinalized("Context was already finalized.")
utils._check_byteslike("data", data)
buffer_ += bytes(data)
finished_blocks = max(len(buffer_) // (block_size // 8) - 1, 0)
result = buffer_[: finished_blocks * (block_size // 8)]
buffer_ = buffer_[finished_blocks * (block_size // 8) :]
return buffer_, result
def _byte_unpadding_check(
buffer_: typing.Optional[bytes],
block_size: int,
checkfn: typing.Callable[[bytes], int],
) -> bytes:
if buffer_ is None:
raise AlreadyFinalized("Context was already finalized.")
if len(buffer_) != block_size // 8:
raise ValueError("Invalid padding bytes.")
valid = checkfn(buffer_)
if not valid:
raise ValueError("Invalid padding bytes.")
pad_size = buffer_[-1]
return buffer_[:-pad_size]
class PKCS7:
def __init__(self, block_size: int):
_byte_padding_check(block_size)
self.block_size = block_size
def padder(self) -> PaddingContext:
return _PKCS7PaddingContext(self.block_size)
return PKCS7PaddingContext(self.block_size)
def unpadder(self) -> PaddingContext:
return _PKCS7UnpaddingContext(self.block_size)
return PKCS7UnpaddingContext(self.block_size)
class _PKCS7PaddingContext(PaddingContext):
_buffer: typing.Optional[bytes]
def __init__(self, block_size: int):
self.block_size = block_size
# TODO: more copies than necessary, we should use zero-buffer (#193)
self._buffer = b""
def update(self, data: bytes) -> bytes:
self._buffer, result = _byte_padding_update(
self._buffer, data, self.block_size
)
return result
def _padding(self, size: int) -> bytes:
return bytes([size]) * size
def finalize(self) -> bytes:
result = _byte_padding_pad(
self._buffer, self.block_size, self._padding
)
self._buffer = None
return result
class _PKCS7UnpaddingContext(PaddingContext):
_buffer: typing.Optional[bytes]
def __init__(self, block_size: int):
self.block_size = block_size
# TODO: more copies than necessary, we should use zero-buffer (#193)
self._buffer = b""
def update(self, data: bytes) -> bytes:
self._buffer, result = _byte_unpadding_update(
self._buffer, data, self.block_size
)
return result
def finalize(self) -> bytes:
result = _byte_unpadding_check(
self._buffer, self.block_size, check_pkcs7_padding
)
self._buffer = None
return result
PaddingContext.register(PKCS7PaddingContext)
PaddingContext.register(PKCS7UnpaddingContext)
class ANSIX923:
@@ -170,56 +59,11 @@ class ANSIX923:
self.block_size = block_size
def padder(self) -> PaddingContext:
return _ANSIX923PaddingContext(self.block_size)
return ANSIX923PaddingContext(self.block_size)
def unpadder(self) -> PaddingContext:
return _ANSIX923UnpaddingContext(self.block_size)
return ANSIX923UnpaddingContext(self.block_size)
class _ANSIX923PaddingContext(PaddingContext):
_buffer: typing.Optional[bytes]
def __init__(self, block_size: int):
self.block_size = block_size
# TODO: more copies than necessary, we should use zero-buffer (#193)
self._buffer = b""
def update(self, data: bytes) -> bytes:
self._buffer, result = _byte_padding_update(
self._buffer, data, self.block_size
)
return result
def _padding(self, size: int) -> bytes:
return bytes([0]) * (size - 1) + bytes([size])
def finalize(self) -> bytes:
result = _byte_padding_pad(
self._buffer, self.block_size, self._padding
)
self._buffer = None
return result
class _ANSIX923UnpaddingContext(PaddingContext):
_buffer: typing.Optional[bytes]
def __init__(self, block_size: int):
self.block_size = block_size
# TODO: more copies than necessary, we should use zero-buffer (#193)
self._buffer = b""
def update(self, data: bytes) -> bytes:
self._buffer, result = _byte_unpadding_update(
self._buffer, data, self.block_size
)
return result
def finalize(self) -> bytes:
result = _byte_unpadding_check(
self._buffer,
self.block_size,
check_ansix923_padding,
)
self._buffer = None
return result
PaddingContext.register(ANSIX923PaddingContext)
PaddingContext.register(ANSIX923UnpaddingContext)