
| Current Path : /var/www/wsgi/www/api/venv/lib64/python3.12/site-packages/pyhanko/pdf_utils/crypt/ |
Linux ift1.ift-informatik.de 5.4.0-216-generic #236-Ubuntu SMP Fri Apr 11 19:53:21 UTC 2025 x86_64 |
| Current File : /var/www/wsgi/www/api/venv/lib64/python3.12/site-packages/pyhanko/pdf_utils/crypt/cred_ser.py |
import abc
from dataclasses import dataclass
from typing import Dict, Type
from pyhanko.pdf_utils import misc
# TODO Consider maybe allowing a credential exporter that just dumps
# the file encryption key, and would be compatible with any of the "built-in"
# security handlers.
@dataclass(frozen=True)
class SerialisedCredential:
"""
A credential in serialised form.
"""
credential_type: str
"""
The registered type name of the credential
(see :meth:`.SerialisableCredential.register`).
"""
data: bytes
"""
The credential data, as a byte string.
"""
class SerialisableCredential(abc.ABC):
"""
Class representing a credential that can be serialised.
"""
__registered_subclasses: Dict[str, Type['SerialisableCredential']] = dict()
@classmethod
def get_name(cls) -> str:
"""
Get the type name of the credential, which will be embedded into
serialised values and used on deserialisation.
"""
raise NotImplementedError
@staticmethod
def register(cls: Type['SerialisableCredential']):
"""
Register a subclass into the credential serialisation registry, using
the name returned by :meth:`get_name`. Can be used as a class decorator.
:param cls:
The subclass.
:return:
The subclass.
"""
SerialisableCredential.__registered_subclasses[cls.get_name()] = cls
return cls
def _ser_value(self) -> bytes:
"""
Serialise a value to raw binary data. To be overridden by subclasses.
:return:
A byte string
:raises misc.PdfWriteError:
If a serialisation error occurs.
"""
raise NotImplementedError
@classmethod
def _deser_value(cls, data: bytes):
"""
Deserialise a value from raw binary data.
:param data:
The data to deserialise.
:return:
The deserialised value (an instance of a subclass of
:class:`.SerialisableCredential`)
:raises misc.PdfReadError:
If a deserialisation error occurs.
"""
raise NotImplementedError
@staticmethod
def deserialise(
ser_value: SerialisedCredential,
) -> 'SerialisableCredential':
"""
Deserialise a :class:`.SerialisedCredential` value by looking up
the proper subclass of :class:`.SerialisableCredential` and invoking
its deserialisation method.
:param ser_value:
The value to deserialise.
:return:
The deserialised credential.
:raises misc.PdfReadError:
If a deserialisation error occurs.
"""
cred_type = ser_value.credential_type
try:
cls = SerialisableCredential.__registered_subclasses[cred_type]
except KeyError:
raise misc.PdfReadError(
f"Failed to deserialise credential: "
f"credential type '{cred_type}' not known."
)
return cls._deser_value(ser_value.data)
def serialise(self) -> SerialisedCredential:
"""
Serialise a value to an annotated :class:`.SerialisedCredential` value.
:return:
A :class:`.SerialisedCredential` value.
:raises misc.PdfWriteError:
If a serialisation error occurs.
"""
return SerialisedCredential(
credential_type=self.__class__.get_name(), data=self._ser_value()
)