Browse Source

Finaly have secret_crypto.

Cixo Develop 7 months ago
parent
commit
4250ad002b
3 changed files with 136 additions and 20 deletions
  1. 1 0
      assets/__init__.py
  2. 135 0
      assets/secret_crypto.py
  3. 0 20
      assets/secret_encryption.py

+ 1 - 0
assets/__init__.py

@@ -4,3 +4,4 @@ from .user import user_builder
 from .user_loader import user_loader
 from .user_loader import user_loader
 from .database import database
 from .database import database
 from .apikey import apikey
 from .apikey import apikey
+from .secret_crypto import secret_crypto

+ 135 - 0
assets/secret_crypto.py

@@ -0,0 +1,135 @@
+import Crypto.Cipher.AES
+import hashlib
+import os
+
+class secret_crypto:
+    """
+    This class is responsible for creation and manage of the secrets crypto.
+    All of the secrets would have own IV. When new secret_crypto is creating,
+    IV is random. It could be change by function set_iv. Set IV is necessary
+    to decrypt secret.
+
+    Password HAVE NOT being stored in database. It must be given from API, 
+    to protect database. Password from the user is hashed by SHA256 to use it 
+    as key. IV is random, and other for all of the keys.
+    
+    If database leaks, secrets are save, because keys is provided from user
+    every request for the secret.
+    """
+
+    def __init__(
+        self, 
+        password: str, 
+        __iv: bytes | None = None,
+        __key: bytes | None = None
+    ) -> None:
+        """
+        This function create new secret_crypto. It could be used encrypt new
+        secret. To decrypt secret, app must set IV.
+
+        password: str - Password to encrypt secrets
+        __iv: bytes | None - IV, used to clone (default: None)
+        __key: bytes | None - Key, used to clone (default: None)
+        """
+
+        if __key is None:
+            encoded = password.encode("UTF-8")
+            hashed = hashlib.sha256(encoded)
+            __key = hashed.digest()
+
+        if __iv is None:
+            __iv = os.urandom(16)
+
+        self.__iv = __iv
+        self.__key = __key
+        self.__password = password
+
+    def encrypt(self, secret: str) -> bytes:
+        """
+        This function encrypt secret, using previously loaded password as key
+        and IV. IV would be random, and own for all secrets.
+
+        secret: str - Secret to encode
+        return: bytes - Encrypted secret
+        """
+
+        return self.__cipher.encrypt(secret.encode("UTF-8"))
+
+    def decrypt(self, crypted: bytes) -> str:
+        """
+        This function decrypt previously crypted secret using given password
+        as key. IV must be restore. When random IV is used, then cipher would
+        not decrypt secret.
+        
+        crypted: bytes - Crypted secret to decrypt
+        return: str - Decrypted secret
+        """
+
+        return self.__cipher.decrypt(crypted).decode("UTF-8")
+
+    def crypted(self, secret: str) -> [bytes, bytes]:
+        """
+        This function is complex version of encrypt. It do exacly the same, 
+        but it return also IV, which could make code look better.
+
+        secret: str - Secret to encrypt
+        return: [bytes, bytes] - [Encrypted secret, IV]
+        """
+
+        return self.encrypt(secret), self.iv
+
+    @property
+    def password(self) -> str:
+        """
+        return: str - Password to encrypt
+        """
+
+        return self.__password
+
+    @property
+    def key(self) -> bytes:
+        """
+        return: bytes - Password as 256 bit binary key
+        """
+
+        return self.__key
+
+    @property
+    def iv(self) -> bytes:
+        """
+        return: bytes - IV of the crypto, get it to save in database
+        """
+
+        return self.__iv
+
+    def set_iv(self, iv: bytes) -> object:
+        """
+        This function set IV. IV must be save in database, to decrypt secret
+        later. This function is used to restore IV, previously read from 
+        database.
+
+        iv: bytes - IV read from database
+        return: secret_crypto - Clone of crypto with set given iv
+        """
+
+        return secret_crypto(self.password, iv, self.key)
+
+    @property
+    def mode(self) -> int:
+        """
+        return: int - Mode of the AES used to crypt
+        """
+
+        return Crypto.Cipher.AES.MODE_CFB
+
+    @property
+    def __cipher(self) -> object:
+        """
+        return: object - New clean cipher, which could be used to work
+        """
+
+        return Crypto.Cipher.AES.new(
+            self.key, 
+            self.mode, 
+            iv = self.iv
+        )

+ 0 - 20
assets/secret_encryption.py

@@ -1,20 +0,0 @@
-import Crypto
-import hashlib
-import os
-
-class secret_crypto:
-    def __init__(self, password: str):
-        self.__iv = os.urandom(16)
-        self.__key = self.__create_key(password)
-
-    @property
-    def __cipher(self) -> Crypto.Cipher:
-        return Crypto.Cipher.AES.new(self.__key
-
-    def __create_key(self, password: str) -> bytes:
-        encoded = password.encode("UTF-8")
-        hashed = hashlib.sha256(encoded)
-
-        return hashed.digest()
-    
-