pumpwood_communication.encrypt

Modules to encript data on Pumpwood Systems.

1"""Modules to encript data on Pumpwood Systems."""
2from .encrypt import PumpwoodCryptography
3
4__all__ = [
5    PumpwoodCryptography
6]
class PumpwoodCryptography:
 13class PumpwoodCryptography:
 14    """Encrypt and decrypt PumpWood data using Fernet."""
 15
 16    _fernet_object: Fernet = None
 17    """Configured Fernet instance, or None when no key is set."""
 18
 19    def __init__(self, fernet_key: str = None):
 20        """Initialize cryptography helper.
 21
 22        Args:
 23            fernet_key (str):
 24                Optional Fernet key. When omitted, reads
 25                ``CRYPTO_FERNET_KEY`` from configuration.
 26
 27        Raises:
 28            PumpWoodOtherException:
 29                If the Fernet key is invalid.
 30        """
 31        if fernet_key is None:
 32            fernet_key = CRYPTO_FERNET_KEY
 33            if fernet_key is None:
 34                log_msg = (
 35                    'PUMPWOOD_COMMUNICATION__CRYPTO_FERNET_KEY is not set, '
 36                    'PumpwoodCryptography encription is disable and will '
 37                    'raise error if used')
 38                logger.info(log_msg)
 39            else:
 40                try:
 41                    self._fernet_object = Fernet(fernet_key)
 42                except Exception as e:
 43                    error_str = str(e)
 44                    msg = (
 45                        'Fernet is not correctly cofigured, error when '
 46                        'creating PumpwoodCryptography object. '
 47                        'Error: {erro_msg}')
 48                    raise PumpWoodOtherException(
 49                        message=msg, payload={'erro_msg': error_str})
 50
 51    def _check_if_configured(self) -> bool:
 52        """Check if PumpwoodCryptography is configured.
 53
 54        Returns:
 55            bool:
 56                True when Fernet is configured.
 57
 58        Raises:
 59            PumpWoodOtherException:
 60                If the Fernet key was not configured.
 61        """
 62        if self._fernet_object is None:
 63            msg = (
 64                'PumpwoodCryptography is not configured, fernet key was not '
 65                'passed as argument on object creation and env variable '
 66                '`PUMPWOOD_COMMUNICATION__CRYPTO_FERNET_KEY` was not set')
 67            raise PumpWoodOtherException(message=msg)
 68        return True
 69
 70    def encrypt(self, value: any) -> str:
 71        """Encrypt value using object Fernet Key.
 72
 73        It will serialize the data to JSON and if bytes it will be converted to
 74        base64. Data will then be encrypted using the fernet key.
 75
 76        Args:
 77            value (any):
 78                Value that will be encrypted. It is possible to encrypt
 79                python objects and bytes.
 80
 81        Returns:
 82            Return a string with encripted information using objects Fernet
 83            Key.
 84        """
 85        self._check_if_configured()
 86
 87        # None objects should not be encripted
 88        if value is None:
 89            return None
 90
 91        encoded_value = None
 92        # If type is bytes, convert to a dictinary that will be used when
 93        # decrypting data to convert information back to bytes again
 94        if type(value) is bytes:
 95            # Convert bytes to base64 before encription
 96            encoded_base64 = base64.b64encode(value).decode('utf-8')
 97            encoded_value = pumpJsonDump({
 98                '__type__': 'bytes',
 99                '__base64__': encoded_base64,
100                '__PumpwoodCryptography__': True})
101        else:
102            encoded_value = pumpJsonDump(value)
103        encrypted_data = self._fernet_object.encrypt(encoded_value)
104        return encrypted_data.decode('utf-8')
105
106    def decrypt(self, value: str) -> any:
107        """Decrypt value using object Fernet Key.
108
109        Args:
110            value (str):
111                String value that will be decripted.
112
113        Returns:
114            Return the encrypted object.
115
116        Raise:
117            PumpWoodNotImplementedError:
118                Raise this error if the encrypted data is a dictinary with
119                key `__PumpwoodCryptography__` is equal to `True`, but the
120                key `__type__` indicates
121        """
122        self._check_if_configured()
123        if value is None:
124            return value
125
126        decrypted_value = self._fernet_object.decrypt(value.encode('utf-8'))
127        python_obj = orjson.loads(decrypted_value)
128        if type(python_obj) is not dict:
129            return python_obj
130
131        # Dictionary data with `__PumpwoodCryptography__` key indicates
132        # that the information was treated on encryption
133        is_PumpwoodCryptography = python_obj.get(
134            '__PumpwoodCryptography__', False)
135        if not is_PumpwoodCryptography:
136            return python_obj
137
138        # __type__ will indicated the type of the data that was encrypted,
139        # this will be used to correctly undo the encryption
140        obj_type = python_obj.get('__type__')
141        if obj_type == 'bytes':
142            return base64.b64decode(python_obj['__base64__'])
143
144        msg = (
145            "Object is encrypted using PumpwoodCryptography, but type "
146            "[{obj_type}] could not be recognized. Check if the version of "
147            "Pumpwood Communication used at encryption is compatible")
148        raise PumpWoodNotImplementedError(message=msg, payload={
149            'obj_type': obj_type})

Encrypt and decrypt PumpWood data using Fernet.

PumpwoodCryptography(fernet_key: str = None)
19    def __init__(self, fernet_key: str = None):
20        """Initialize cryptography helper.
21
22        Args:
23            fernet_key (str):
24                Optional Fernet key. When omitted, reads
25                ``CRYPTO_FERNET_KEY`` from configuration.
26
27        Raises:
28            PumpWoodOtherException:
29                If the Fernet key is invalid.
30        """
31        if fernet_key is None:
32            fernet_key = CRYPTO_FERNET_KEY
33            if fernet_key is None:
34                log_msg = (
35                    'PUMPWOOD_COMMUNICATION__CRYPTO_FERNET_KEY is not set, '
36                    'PumpwoodCryptography encription is disable and will '
37                    'raise error if used')
38                logger.info(log_msg)
39            else:
40                try:
41                    self._fernet_object = Fernet(fernet_key)
42                except Exception as e:
43                    error_str = str(e)
44                    msg = (
45                        'Fernet is not correctly cofigured, error when '
46                        'creating PumpwoodCryptography object. '
47                        'Error: {erro_msg}')
48                    raise PumpWoodOtherException(
49                        message=msg, payload={'erro_msg': error_str})

Initialize cryptography helper.

Arguments:
  • fernet_key (str): Optional Fernet key. When omitted, reads CRYPTO_FERNET_KEY from configuration.
Raises:
  • PumpWoodOtherException: If the Fernet key is invalid.
def encrypt(self, value: <built-in function any>) -> str:
 70    def encrypt(self, value: any) -> str:
 71        """Encrypt value using object Fernet Key.
 72
 73        It will serialize the data to JSON and if bytes it will be converted to
 74        base64. Data will then be encrypted using the fernet key.
 75
 76        Args:
 77            value (any):
 78                Value that will be encrypted. It is possible to encrypt
 79                python objects and bytes.
 80
 81        Returns:
 82            Return a string with encripted information using objects Fernet
 83            Key.
 84        """
 85        self._check_if_configured()
 86
 87        # None objects should not be encripted
 88        if value is None:
 89            return None
 90
 91        encoded_value = None
 92        # If type is bytes, convert to a dictinary that will be used when
 93        # decrypting data to convert information back to bytes again
 94        if type(value) is bytes:
 95            # Convert bytes to base64 before encription
 96            encoded_base64 = base64.b64encode(value).decode('utf-8')
 97            encoded_value = pumpJsonDump({
 98                '__type__': 'bytes',
 99                '__base64__': encoded_base64,
100                '__PumpwoodCryptography__': True})
101        else:
102            encoded_value = pumpJsonDump(value)
103        encrypted_data = self._fernet_object.encrypt(encoded_value)
104        return encrypted_data.decode('utf-8')

Encrypt value using object Fernet Key.

It will serialize the data to JSON and if bytes it will be converted to base64. Data will then be encrypted using the fernet key.

Arguments:
  • value (any): Value that will be encrypted. It is possible to encrypt python objects and bytes.
Returns:

Return a string with encripted information using objects Fernet Key.

def decrypt(self, value: str) -> <built-in function any>:
106    def decrypt(self, value: str) -> any:
107        """Decrypt value using object Fernet Key.
108
109        Args:
110            value (str):
111                String value that will be decripted.
112
113        Returns:
114            Return the encrypted object.
115
116        Raise:
117            PumpWoodNotImplementedError:
118                Raise this error if the encrypted data is a dictinary with
119                key `__PumpwoodCryptography__` is equal to `True`, but the
120                key `__type__` indicates
121        """
122        self._check_if_configured()
123        if value is None:
124            return value
125
126        decrypted_value = self._fernet_object.decrypt(value.encode('utf-8'))
127        python_obj = orjson.loads(decrypted_value)
128        if type(python_obj) is not dict:
129            return python_obj
130
131        # Dictionary data with `__PumpwoodCryptography__` key indicates
132        # that the information was treated on encryption
133        is_PumpwoodCryptography = python_obj.get(
134            '__PumpwoodCryptography__', False)
135        if not is_PumpwoodCryptography:
136            return python_obj
137
138        # __type__ will indicated the type of the data that was encrypted,
139        # this will be used to correctly undo the encryption
140        obj_type = python_obj.get('__type__')
141        if obj_type == 'bytes':
142            return base64.b64decode(python_obj['__base64__'])
143
144        msg = (
145            "Object is encrypted using PumpwoodCryptography, but type "
146            "[{obj_type}] could not be recognized. Check if the version of "
147            "Pumpwood Communication used at encryption is compatible")
148        raise PumpWoodNotImplementedError(message=msg, payload={
149            'obj_type': obj_type})

Decrypt value using object Fernet Key.

Arguments:
  • value (str): String value that will be decripted.
Returns:

Return the encrypted object.

Raises:
  • PumpWoodNotImplementedError: Raise this error if the encrypted data is a dictinary with key __PumpwoodCryptography__ is equal to True, but the key __type__ indicates