|
@@ -2,6 +2,7 @@ import hashlib
|
|
|
import os
|
|
import os
|
|
|
|
|
|
|
|
from .secret_properties import secret_properties
|
|
from .secret_properties import secret_properties
|
|
|
|
|
+from .secret import secret
|
|
|
|
|
|
|
|
class secret_generator(metaclass = secret_properties):
|
|
class secret_generator(metaclass = secret_properties):
|
|
|
def __init__(self, password: str):
|
|
def __init__(self, password: str):
|
|
@@ -12,50 +13,25 @@ class secret_generator(metaclass = secret_properties):
|
|
|
def password(self) -> str:
|
|
def password(self) -> str:
|
|
|
return self.__password
|
|
return self.__password
|
|
|
|
|
|
|
|
- def validate(self, secret: str) -> bool:
|
|
|
|
|
- if not self.__check_secret(secret):
|
|
|
|
|
- return False
|
|
|
|
|
-
|
|
|
|
|
- hashed, salt = self.__split_secret(secret)
|
|
|
|
|
- target_hashed, second_salt = self.__generate_hashed(salt)
|
|
|
|
|
|
|
+ def validate(self, target: secret) -> bool:
|
|
|
|
|
+ hashed = target.hashed
|
|
|
|
|
+ salt = target.salt
|
|
|
|
|
+ target_hashed = self.__generate_hashed(salt)
|
|
|
|
|
|
|
|
return hashed == target_hashed
|
|
return hashed == target_hashed
|
|
|
|
|
|
|
|
- def __check_secret(self, secret: str) -> bool:
|
|
|
|
|
|
|
+ def __generate_salt(self) -> bytes:
|
|
|
properties = self.__class__
|
|
properties = self.__class__
|
|
|
-
|
|
|
|
|
- hash_length = properties.hash_hex_length
|
|
|
|
|
- salt_length = properties.salt_hex_length
|
|
|
|
|
- separator = properties.salt_separator
|
|
|
|
|
-
|
|
|
|
|
- if secret.find(separator) != hash_length:
|
|
|
|
|
- return False
|
|
|
|
|
-
|
|
|
|
|
- if len(secret) != hash_length + salt_length + len(separator):
|
|
|
|
|
- return False
|
|
|
|
|
-
|
|
|
|
|
- return True
|
|
|
|
|
|
|
+ result = os.urandom(properties.salt_length)
|
|
|
|
|
|
|
|
- def __split_secret(self, secret: str) -> [bytes, bytes]:
|
|
|
|
|
- properties = self.__class__
|
|
|
|
|
- separator = properties.salt_separator
|
|
|
|
|
- splited = secret.split(separator)
|
|
|
|
|
-
|
|
|
|
|
- hashed = bytes.fromhex(splited[0])
|
|
|
|
|
- salt = bytes.fromhex(splited[-1])
|
|
|
|
|
-
|
|
|
|
|
- return hashed, salt
|
|
|
|
|
|
|
+ return result
|
|
|
|
|
|
|
|
- def __generate_hashed(self, salt: bytes | None = None) -> str:
|
|
|
|
|
|
|
+ def __generate_hashed(self, salt: bytes) -> bytes:
|
|
|
properties = self.__class__
|
|
properties = self.__class__
|
|
|
|
|
|
|
|
rounds = properties.hash_rounds
|
|
rounds = properties.hash_rounds
|
|
|
algorithm = properties.hash_algorithm
|
|
algorithm = properties.hash_algorithm
|
|
|
password = self.password.encode("UTF-8")
|
|
password = self.password.encode("UTF-8")
|
|
|
-
|
|
|
|
|
- if salt is None:
|
|
|
|
|
- random_size = properties.salt_length
|
|
|
|
|
- salt = os.urandom(random_size)
|
|
|
|
|
|
|
|
|
|
hashed = hashlib.pbkdf2_hmac(
|
|
hashed = hashlib.pbkdf2_hmac(
|
|
|
algorithm,
|
|
algorithm,
|
|
@@ -64,25 +40,14 @@ class secret_generator(metaclass = secret_properties):
|
|
|
rounds
|
|
rounds
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
- return hashed, salt
|
|
|
|
|
|
|
+ return hashed
|
|
|
|
|
|
|
|
@property
|
|
@property
|
|
|
- def secret(self) -> str:
|
|
|
|
|
|
|
+ def secret(self) -> secret:
|
|
|
if self.__secret is not None:
|
|
if self.__secret is not None:
|
|
|
return self.__secret
|
|
return self.__secret
|
|
|
|
|
|
|
|
- hashed, salt = self.__generate_hashed()
|
|
|
|
|
- self.__secret = self.__create_secret(hashed, salt)
|
|
|
|
|
-
|
|
|
|
|
- return self.secret
|
|
|
|
|
-
|
|
|
|
|
- def __create_secret(self, hashed: bytes, salt: bytes) -> str:
|
|
|
|
|
- properties = self.__class__
|
|
|
|
|
- separator = properties.salt_separator
|
|
|
|
|
-
|
|
|
|
|
- result = hashed.hex() + separator + salt.hex()
|
|
|
|
|
-
|
|
|
|
|
- if not self.__check_secret(result):
|
|
|
|
|
- raise Exception("Can not create secret. Check secret settings!")
|
|
|
|
|
-
|
|
|
|
|
- return result
|
|
|
|
|
|
|
+ salt = self.__generate_salt()
|
|
|
|
|
+ hashed = self.__generate_hashed(salt)
|
|
|
|
|
+
|
|
|
|
|
+ return secret.build(hashed, salt)
|