Created
September 26, 2019 00:56
-
-
Save HacKanCuBa/bd6d5d0d049d7fc4900c6ebad44c2c91 to your computer and use it in GitHub Desktop.
Python3 OTPCypher (toy module)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from typing import Tuple | |
from typing import Union | |
TParam = Union[bytes, str, bytearray] | |
class OTPCypher: | |
"""One-time pad cypher (use with extreme care!). | |
There are several restrictions for this to work: both parameters must have | |
the same byte length (meaning: be careful with non-ascii characters), and | |
the OTP parameter must truly be unique (if it is repeated, the encryption | |
can be broken). Additionally, no parameter must be controlled by the user | |
because this algorithm is malleable. | |
If that holds, then this encryption is information-theoretically secure. | |
""" | |
@staticmethod | |
def _check_param_before_conversion(param: TParam) -> bool: | |
if not isinstance(param, (bytes, str, bytearray)): | |
raise TypeError('Both parameters must be an instance of bytes, str or ' | |
'bytearray') | |
return True | |
@classmethod | |
def _check_params_before_conversion(cls, p1: TParam, p2: TParam) -> bool: | |
return all((cls._check_param_before_conversion(p1), | |
cls._check_param_before_conversion(p2))) | |
@staticmethod | |
def _convert_param_to_process(param: TParam) -> bytearray: | |
if isinstance(param, str): | |
return bytearray(param, 'utf-8') | |
return bytearray(param) | |
@staticmethod | |
def _check_params_before_process(p1: bytearray, p2: bytearray) -> bool: | |
if not isinstance(p1, bytearray) or not isinstance(p2, bytearray): | |
raise TypeError('Both parameters must be an instance of bytearray') | |
if len(p1) != len(p2): | |
raise ValueError('Both parameters must be of the same length') | |
return True | |
@classmethod | |
def _convert_params_to_process(cls, | |
p1: TParam, | |
p2: TParam) -> Tuple[bytearray, bytearray]: | |
cls._check_params_before_conversion(p1, p2) | |
p1_c, p2_c = (cls._convert_param_to_process(p1), | |
cls._convert_param_to_process(p2)) | |
cls._check_params_before_process(p1_c, p2_c) | |
return p1_c, p2_c | |
@staticmethod | |
def _convert_to_output(value: bytearray) -> str: | |
return value.decode('utf-8') | |
@classmethod | |
def encrypt_decrypt(cls, key: TParam, pt_ct: TParam) -> str: | |
"""Encrypt or decrypt given parameters. | |
:param key: Key parameter that will be used to encrypt or decrypt. | |
:param pt_ct: Either plain text to encrypt or cypher text to decrypt. | |
:return: The result of XORing each byte of both parameters, as UTF-8 | |
string. | |
""" | |
# ToDo: maybe use a short header to know whether it's encrypted or not | |
key_p, pt_ct_p = cls._convert_params_to_process(key, pt_ct) | |
processed = bytearray(p1 ^ p2 for p1, p2 in zip(key_p, pt_ct_p)) | |
return cls._convert_to_output(processed) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment