Advertisement
Guest User

Untitled

a guest
Oct 14th, 2019
83
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.81 KB | None | 0 0
  1. from typing import Tuple
  2. from typing import Union
  3.  
  4. TParam = Union[bytes, str, bytearray]
  5.  
  6.  
  7. class OTPCypher:
  8. """One-time pad cypher (use with extreme care!).
  9.  
  10. There are several restrictions for this to work: both parameters must have
  11. the same byte length (meaning: be careful with non-ascii characters), and
  12. the OTP parameter must truly be unique (if it is repeated, the encryption
  13. can be broken). Additionally, no parameter must be controlled by the user
  14. because this algorithm is malleable.
  15. If that holds, then this encryption is information-theoretically secure.
  16. """
  17.  
  18. @staticmethod
  19. def _check_param_before_conversion(param: TParam) -> bool:
  20. if not isinstance(param, (bytes, str, bytearray)):
  21. raise TypeError('Both parameters must be an instance of bytes, str or '
  22. 'bytearray')
  23. return True
  24.  
  25. @classmethod
  26. def _check_params_before_conversion(cls, p1: TParam, p2: TParam) -> bool:
  27. return all((cls._check_param_before_conversion(p1),
  28. cls._check_param_before_conversion(p2)))
  29.  
  30. @staticmethod
  31. def _convert_param_to_process(param: TParam) -> bytearray:
  32. if isinstance(param, str):
  33. return bytearray(param, 'utf-8')
  34. return bytearray(param)
  35.  
  36. @staticmethod
  37. def _check_params_before_process(p1: bytearray, p2: bytearray) -> bool:
  38. if not isinstance(p1, bytearray) or not isinstance(p2, bytearray):
  39. raise TypeError('Both parameters must be an instance of bytearray')
  40. if len(p1) != len(p2):
  41. raise ValueError('Both parameters must be of the same length')
  42. return True
  43.  
  44. @classmethod
  45. def _convert_params_to_process(cls,
  46. p1: TParam,
  47. p2: TParam) -> Tuple[bytearray, bytearray]:
  48. cls._check_params_before_conversion(p1, p2)
  49. p1_c, p2_c = (cls._convert_param_to_process(p1),
  50. cls._convert_param_to_process(p2))
  51. cls._check_params_before_process(p1_c, p2_c)
  52. return p1_c, p2_c
  53.  
  54. @staticmethod
  55. def _convert_to_output(value: bytearray) -> str:
  56. return value.decode('utf-8')
  57.  
  58. @classmethod
  59. def encrypt_decrypt(cls, key: TParam, pt_ct: TParam) -> str:
  60. """Encrypt or decrypt given parameters.
  61.  
  62. :param key: Key parameter that will be used to encrypt or decrypt.
  63. :param pt_ct: Either plain text to encrypt or cypher text to decrypt.
  64. :return: The result of XORing each byte of both parameters, as UTF-8
  65. string.
  66. """
  67. # ToDo: maybe use a short header to know whether it's encrypted or not
  68. key_p, pt_ct_p = cls._convert_params_to_process(key, pt_ct)
  69. processed = bytearray(p1 ^ p2 for p1, p2 in zip(key_p, pt_ct_p))
  70. return cls._convert_to_output(processed)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement