MCPcopy Create free account
hub / github.com/amyasnikov/validity / EncryptedString

Class EncryptedString

validity/fields/encrypted.py:26–64  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

24
25@dataclass
26class EncryptedString:
27 cipher: bytes
28 salt: bytes
29 _fernet: Fernet | None = field(default=None, compare=False, repr=False)
30
31 secret_key: ClassVar[bytes] = settings.SECRET_KEY.encode()
32
33 def __post_init__(self):
34 if self._fernet is None:
35 self._fernet = self.get_fernet(base64.urlsafe_b64decode(self.salt))
36
37 def __len__(self) -> int:
38 return len(self.cipher)
39
40 @classmethod
41 def from_plain_text(cls, message: str | bytes, salt: bytes = b""):
42 message = message.encode() if isinstance(message, str) else message
43 salt = salt or os.urandom(16)
44 fernet = cls.get_fernet(salt)
45 cipher = fernet.encrypt(message)
46 return cls(cipher, base64.urlsafe_b64encode(salt), fernet)
47
48 @classmethod
49 def get_fernet(cls, salt: bytes) -> Fernet:
50 if isinstance(salt, str):
51 salt = salt.encode()
52 kdf = PBKDF2HMAC(algorithm=hashes.SHA256(), length=32, salt=salt, iterations=480000, backend=default_backend())
53 return Fernet(base64.urlsafe_b64encode(kdf.derive(cls.secret_key)))
54
55 def decrypt(self) -> str:
56 return self._fernet.decrypt(self.cipher).decode()
57
58 def serialize(self) -> str:
59 return f"${self.salt.decode()}${self.cipher.decode()}$"
60
61 @classmethod
62 def deserialize(cls, value: str):
63 salt, cipher = value.strip("$").split("$")
64 return cls(cipher.encode(), salt.encode())
65
66
67class EncryptedObject(EncryptedString):

Callers

nothing calls this directly

Calls 1

encodeMethod · 0.80

Tested by

no test coverage detected