passphera-core 0.8.2__tar.gz → 0.9.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {passphera-core-0.8.2 → passphera-core-0.9.0}/PKG-INFO +2 -2
- {passphera-core-0.8.2 → passphera-core-0.9.0}/passphera_core/__init__.py +1 -1
- passphera-core-0.9.0/passphera_core/entities.py +125 -0
- passphera-core-0.9.0/passphera_core/exceptions.py +49 -0
- passphera-core-0.9.0/passphera_core/interfaces.py +92 -0
- {passphera-core-0.8.2 → passphera-core-0.9.0}/passphera_core.egg-info/PKG-INFO +2 -2
- {passphera-core-0.8.2 → passphera-core-0.9.0}/passphera_core.egg-info/SOURCES.txt +2 -1
- {passphera-core-0.8.2 → passphera-core-0.9.0}/setup.py +2 -2
- passphera-core-0.8.2/passphera_core/exceptions.py +0 -3
- passphera-core-0.8.2/passphera_core/generator.py +0 -228
- {passphera-core-0.8.2 → passphera-core-0.9.0}/README.md +0 -0
- {passphera-core-0.8.2 → passphera-core-0.9.0}/passphera_core.egg-info/dependency_links.txt +0 -0
- {passphera-core-0.8.2 → passphera-core-0.9.0}/passphera_core.egg-info/requires.txt +0 -0
- {passphera-core-0.8.2 → passphera-core-0.9.0}/passphera_core.egg-info/top_level.txt +0 -0
- {passphera-core-0.8.2 → passphera-core-0.9.0}/setup.cfg +0 -0
@@ -1,11 +1,11 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: passphera-core
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.9.0
|
4
4
|
Summary: The core system of passphera project
|
5
5
|
Home-page: https://github.com/passphera/core
|
6
6
|
Author: Fathi Abdelmalek
|
7
7
|
Author-email: abdelmalek.fathi.2001@gmail.com
|
8
|
-
Classifier: Development Status ::
|
8
|
+
Classifier: Development Status :: 3 - Alpha
|
9
9
|
Classifier: License :: OSI Approved :: MIT License
|
10
10
|
Classifier: Operating System :: OS Independent
|
11
11
|
Classifier: Programming Language :: Python
|
@@ -1,2 +1,2 @@
|
|
1
|
-
from passphera_core.generator import
|
1
|
+
from passphera_core.entities.generator import Generator
|
2
2
|
from passphera_core.exceptions import InvalidAlgorithmException
|
@@ -0,0 +1,125 @@
|
|
1
|
+
from dataclasses import dataclass, field
|
2
|
+
from datetime import datetime, timezone
|
3
|
+
from uuid import UUID, uuid4
|
4
|
+
|
5
|
+
from cryptography.fernet import Fernet
|
6
|
+
|
7
|
+
from cipherspy.cipher import *
|
8
|
+
from cipherspy.cipher.base_cipher import BaseCipherAlgorithm
|
9
|
+
from cipherspy.utilities import generate_salt, derive_key
|
10
|
+
|
11
|
+
from passphera_core import exceptions
|
12
|
+
|
13
|
+
|
14
|
+
@dataclass
|
15
|
+
class Password:
|
16
|
+
id: UUID = field(default_factory=uuid4)
|
17
|
+
user_id: UUID = field(default_factory=uuid4)
|
18
|
+
created_at: datetime = field(default=datetime.now(timezone.utc))
|
19
|
+
updated_at: datetime = field(default=datetime.now(timezone.utc))
|
20
|
+
context: str = field(default_factory=str)
|
21
|
+
text: str = field(default_factory=str)
|
22
|
+
password: str = field(default_factory=str)
|
23
|
+
salt: bytes = field(default_factory=bytes)
|
24
|
+
|
25
|
+
def encrypt(self) -> None:
|
26
|
+
self.salt = generate_salt()
|
27
|
+
key = derive_key(self.password, self.salt)
|
28
|
+
self.password = Fernet(key).encrypt(self.password.encode()).decode()
|
29
|
+
|
30
|
+
def decrypt(self) -> str:
|
31
|
+
key = derive_key(self.password, self.salt)
|
32
|
+
return Fernet(key).decrypt(self.password.encode()).decode()
|
33
|
+
|
34
|
+
|
35
|
+
@dataclass
|
36
|
+
class GeneratorConfig:
|
37
|
+
id: UUID = field(default_factory=uuid4)
|
38
|
+
generator_id: UUID = field(default_factory=uuid4)
|
39
|
+
shift: int = field(default=3)
|
40
|
+
multiplier: int = field(default=3)
|
41
|
+
key: str = field(default="hill")
|
42
|
+
algorithm: str = field(default="hill")
|
43
|
+
prefix: str = field(default="secret")
|
44
|
+
postfix: str = field(default="secret")
|
45
|
+
characters_replacements: dict[str, str] = field(default_factory=dict[str, str])
|
46
|
+
_cipher_registry: dict[str, BaseCipherAlgorithm] = field(default_factory=lambda: {
|
47
|
+
'caesar': CaesarCipherAlgorithm,
|
48
|
+
'affine': AffineCipherAlgorithm,
|
49
|
+
'playfair': PlayfairCipherAlgorithm,
|
50
|
+
'hill': HillCipherAlgorithm,
|
51
|
+
}, init=False)
|
52
|
+
|
53
|
+
def get_algorithm(self) -> BaseCipherAlgorithm:
|
54
|
+
"""
|
55
|
+
Get the primary algorithm used to cipher the password
|
56
|
+
:return: BaseCipherAlgorithm: The primary algorithm used for the cipher
|
57
|
+
"""
|
58
|
+
if self.algorithm.lower() not in self._cipher_registry:
|
59
|
+
raise exceptions.InvalidAlgorithmException(self.algorithm)
|
60
|
+
return self._cipher_registry[self.algorithm.lower()]
|
61
|
+
|
62
|
+
def replace_character(self, char: str, replacement: str) -> None:
|
63
|
+
"""
|
64
|
+
Replace a character with another character or set of characters
|
65
|
+
Eg: pg.replace_character('a', '@1')
|
66
|
+
:param char: The character to be replaced
|
67
|
+
:param replacement: The (character|set of characters) to replace the first one
|
68
|
+
:return:
|
69
|
+
"""
|
70
|
+
self.characters_replacements[char[0]] = replacement
|
71
|
+
|
72
|
+
def reset_character(self, char: str) -> None:
|
73
|
+
"""
|
74
|
+
Reset a character to its original value (remove its replacement from characters_replacements)
|
75
|
+
:param char: The character to be reset to its original value
|
76
|
+
:return:
|
77
|
+
"""
|
78
|
+
self.characters_replacements.pop(char, None)
|
79
|
+
|
80
|
+
|
81
|
+
@dataclass
|
82
|
+
class Generator:
|
83
|
+
id: UUID = field(default_factory=uuid4)
|
84
|
+
user_id: UUID = field(default_factory=uuid4)
|
85
|
+
created_at: datetime = field(default_factory=datetime.now)
|
86
|
+
updated_at: datetime = field(default_factory=datetime.now)
|
87
|
+
config: GeneratorConfig = field(default_factory=GeneratorConfig)
|
88
|
+
|
89
|
+
def apply_replacements(self, password: str) -> str:
|
90
|
+
"""
|
91
|
+
Replace character from the ciphered password with character replacements from the generator configurations
|
92
|
+
:return: str: The new ciphered password after character replacements
|
93
|
+
"""
|
94
|
+
translation_table = str.maketrans(self.config.characters_replacements)
|
95
|
+
return password.translate(translation_table)
|
96
|
+
|
97
|
+
def generate_password(self, text: str) -> str:
|
98
|
+
"""
|
99
|
+
Generate a strong password string using the raw password (add another layer of encryption to it)
|
100
|
+
:return: str: The generated ciphered password
|
101
|
+
"""
|
102
|
+
affine = AffineCipherAlgorithm(self.config.shift, self.config.multiplier)
|
103
|
+
intermediate = affine.encrypt(f"{self.config.prefix}{text}{self.config.postfix}")
|
104
|
+
main_algorithm = self.config.get_algorithm()
|
105
|
+
password = main_algorithm.encrypt(intermediate)
|
106
|
+
password = self.apply_replacements(password)
|
107
|
+
return ''.join(c.upper() if c in text else c for c in password)
|
108
|
+
|
109
|
+
|
110
|
+
@dataclass
|
111
|
+
class User:
|
112
|
+
id: UUID = field(default_factory=uuid4)
|
113
|
+
created_at: datetime = field(default_factory=datetime.now)
|
114
|
+
updated_at: datetime = field(default_factory=datetime.now)
|
115
|
+
username: str = field(default_factory=str)
|
116
|
+
email: str = field(default_factory=str)
|
117
|
+
password: str = field(default_factory=str)
|
118
|
+
generator: UUID = field(default_factory=UUID)
|
119
|
+
passwords: list[UUID] = field(default_factory=list[UUID])
|
120
|
+
|
121
|
+
def add_password(self, password_id: UUID) -> None:
|
122
|
+
self.passwords.append(password_id)
|
123
|
+
|
124
|
+
def delete_password(self, password_id: UUID) -> None:
|
125
|
+
self.passwords.remove(password_id)
|
@@ -0,0 +1,49 @@
|
|
1
|
+
from typing import Union, Literal
|
2
|
+
|
3
|
+
from passphera_core.entities import Password, Generator, User
|
4
|
+
|
5
|
+
|
6
|
+
class InvalidAlgorithmException(Exception):
|
7
|
+
def __init__(self, algorithm: str) -> None:
|
8
|
+
self.algorithm = algorithm
|
9
|
+
super().__init__(f"Invalid algorithm: '{algorithm}'")
|
10
|
+
|
11
|
+
|
12
|
+
class EntityNotFoundException(Exception):
|
13
|
+
def __init__(self, entity: Union[Password, Generator, User]) -> None:
|
14
|
+
self.entity = entity
|
15
|
+
entity_type = entity.__class__.__name__
|
16
|
+
super().__init__(f"{entity_type} not found")
|
17
|
+
|
18
|
+
|
19
|
+
class DuplicateEntityException(Exception):
|
20
|
+
def __init__(
|
21
|
+
self,
|
22
|
+
entity: Union[Password, User],
|
23
|
+
duplicate_field: Literal['context', 'email', 'username'] = None
|
24
|
+
) -> None:
|
25
|
+
self.entity = entity
|
26
|
+
self.duplicate_field = duplicate_field
|
27
|
+
message = self._build_message(entity, duplicate_field)
|
28
|
+
super().__init__(message)
|
29
|
+
|
30
|
+
def _build_message(self, entity: Union[Password, User], duplicate_field: str | None) -> str:
|
31
|
+
if isinstance(entity, Password):
|
32
|
+
return self._build_password_message(entity)
|
33
|
+
elif isinstance(entity, User):
|
34
|
+
return self._build_user_message(entity, duplicate_field)
|
35
|
+
return "Duplicate entity detected"
|
36
|
+
|
37
|
+
@staticmethod
|
38
|
+
def _build_password_message(password: Password) -> str:
|
39
|
+
if hasattr(password, 'context') and password.context:
|
40
|
+
return f"Password for context '{password.context}' already exists"
|
41
|
+
return "Duplicate password detected"
|
42
|
+
|
43
|
+
@staticmethod
|
44
|
+
def _build_user_message(user: User, duplicate_field: str) -> str:
|
45
|
+
if duplicate_field == 'email':
|
46
|
+
return f"User with email '{user.email}' already exists"
|
47
|
+
elif duplicate_field == 'username':
|
48
|
+
return f"User with username '{user.username}' already exists"
|
49
|
+
return "Duplicate user detected"
|
@@ -0,0 +1,92 @@
|
|
1
|
+
from abc import ABC, abstractmethod
|
2
|
+
from uuid import UUID
|
3
|
+
|
4
|
+
from passphera_core.entities import Password, Generator, GeneratorConfig, User
|
5
|
+
|
6
|
+
|
7
|
+
class PasswordRepository(ABC):
|
8
|
+
@abstractmethod
|
9
|
+
def save(self, password: Password) -> None:
|
10
|
+
pass
|
11
|
+
|
12
|
+
@abstractmethod
|
13
|
+
def update(self, password: Password) -> None:
|
14
|
+
pass
|
15
|
+
|
16
|
+
@abstractmethod
|
17
|
+
def delete(self, password_id: UUID) -> None:
|
18
|
+
pass
|
19
|
+
|
20
|
+
@abstractmethod
|
21
|
+
def find_by_id(self, password_id: UUID) -> Password:
|
22
|
+
pass
|
23
|
+
|
24
|
+
|
25
|
+
class GeneratorRepository(ABC):
|
26
|
+
@abstractmethod
|
27
|
+
def save(self, generator: Generator) -> None:
|
28
|
+
pass
|
29
|
+
|
30
|
+
@abstractmethod
|
31
|
+
def update(self, generator: Generator) -> None:
|
32
|
+
pass
|
33
|
+
|
34
|
+
@abstractmethod
|
35
|
+
def delete(self, generator_id: UUID) -> None:
|
36
|
+
pass
|
37
|
+
|
38
|
+
@abstractmethod
|
39
|
+
def find_by_id(self, generator_id: UUID) -> Generator:
|
40
|
+
pass
|
41
|
+
|
42
|
+
@abstractmethod
|
43
|
+
def find_by_user_id(self, user_id: UUID) -> Generator:
|
44
|
+
pass
|
45
|
+
|
46
|
+
|
47
|
+
class GeneratorConfigRepository(ABC):
|
48
|
+
@abstractmethod
|
49
|
+
def save(self, generator_config: GeneratorConfig) -> None:
|
50
|
+
pass
|
51
|
+
|
52
|
+
@abstractmethod
|
53
|
+
def update(self, generator_config: GeneratorConfig) -> None:
|
54
|
+
pass
|
55
|
+
|
56
|
+
@abstractmethod
|
57
|
+
def delete(self, generator_config_id: UUID) -> None:
|
58
|
+
pass
|
59
|
+
|
60
|
+
@abstractmethod
|
61
|
+
def find_by_id(self, generator_config_id: UUID) -> GeneratorConfig:
|
62
|
+
pass
|
63
|
+
|
64
|
+
@abstractmethod
|
65
|
+
def find_by_generator_id(self, generator_id: UUID) -> GeneratorConfig:
|
66
|
+
pass
|
67
|
+
|
68
|
+
|
69
|
+
class UserRepository(ABC):
|
70
|
+
@abstractmethod
|
71
|
+
def save(self, user: User) -> None:
|
72
|
+
pass
|
73
|
+
|
74
|
+
@abstractmethod
|
75
|
+
def update(self, user: User) -> None:
|
76
|
+
pass
|
77
|
+
|
78
|
+
@abstractmethod
|
79
|
+
def delete(self, user_id: UUID) -> None:
|
80
|
+
pass
|
81
|
+
|
82
|
+
@abstractmethod
|
83
|
+
def find_by_id(self, user_id: UUID) -> User:
|
84
|
+
pass
|
85
|
+
|
86
|
+
@abstractmethod
|
87
|
+
def find_by_username(self, username: str) -> User:
|
88
|
+
pass
|
89
|
+
|
90
|
+
@abstractmethod
|
91
|
+
def find_by_email(self, email: str) -> User:
|
92
|
+
pass
|
@@ -1,11 +1,11 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: passphera-core
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.9.0
|
4
4
|
Summary: The core system of passphera project
|
5
5
|
Home-page: https://github.com/passphera/core
|
6
6
|
Author: Fathi Abdelmalek
|
7
7
|
Author-email: abdelmalek.fathi.2001@gmail.com
|
8
|
-
Classifier: Development Status ::
|
8
|
+
Classifier: Development Status :: 3 - Alpha
|
9
9
|
Classifier: License :: OSI Approved :: MIT License
|
10
10
|
Classifier: Operating System :: OS Independent
|
11
11
|
Classifier: Programming Language :: Python
|
@@ -1,8 +1,9 @@
|
|
1
1
|
README.md
|
2
2
|
setup.py
|
3
3
|
passphera_core/__init__.py
|
4
|
+
passphera_core/entities.py
|
4
5
|
passphera_core/exceptions.py
|
5
|
-
passphera_core/
|
6
|
+
passphera_core/interfaces.py
|
6
7
|
passphera_core.egg-info/PKG-INFO
|
7
8
|
passphera_core.egg-info/SOURCES.txt
|
8
9
|
passphera_core.egg-info/dependency_links.txt
|
@@ -5,7 +5,7 @@ with open("README.md", "r") as fh:
|
|
5
5
|
|
6
6
|
setup(
|
7
7
|
name='passphera-core',
|
8
|
-
version='0.
|
8
|
+
version='0.9.0',
|
9
9
|
author='Fathi Abdelmalek',
|
10
10
|
author_email='abdelmalek.fathi.2001@gmail.com',
|
11
11
|
url='https://github.com/passphera/core',
|
@@ -16,7 +16,7 @@ setup(
|
|
16
16
|
python_requires='>=3',
|
17
17
|
install_requires=['cipherspy'],
|
18
18
|
classifiers=[
|
19
|
-
"Development Status ::
|
19
|
+
"Development Status :: 3 - Alpha",
|
20
20
|
"License :: OSI Approved :: MIT License",
|
21
21
|
"Operating System :: OS Independent",
|
22
22
|
"Programming Language :: Python",
|
@@ -1,228 +0,0 @@
|
|
1
|
-
from cipherspy.cipher import *
|
2
|
-
|
3
|
-
from .exceptions import InvalidAlgorithmException
|
4
|
-
|
5
|
-
|
6
|
-
class PasswordGenerator:
|
7
|
-
"""
|
8
|
-
A strong password generator use multiple cipher algorithms to cipher a given plain text
|
9
|
-
"""
|
10
|
-
def __init__(
|
11
|
-
self,
|
12
|
-
shift: int = 3,
|
13
|
-
multiplier: int = 3,
|
14
|
-
key: str = "hill",
|
15
|
-
algorithm: str = 'hill',
|
16
|
-
prefix: str = 'secret',
|
17
|
-
postfix: str = 'secret',
|
18
|
-
characters_replacements: dict = None,
|
19
|
-
):
|
20
|
-
"""
|
21
|
-
:param shift: number of characters to shift each character (default 3)
|
22
|
-
:param multiplier: number of characters to shift each character (default 3)
|
23
|
-
:param key: cipher key string (default "secret")
|
24
|
-
:param algorithm: main cipher algorithm name (default 'playfair')
|
25
|
-
:param characters_replacements: replace characters with the given values (default {})
|
26
|
-
:param text: plain text to be ciphered
|
27
|
-
"""
|
28
|
-
if characters_replacements is None:
|
29
|
-
characters_replacements = {}
|
30
|
-
self._shift: int = shift
|
31
|
-
self._multiplier: int = multiplier
|
32
|
-
self._key: str = key
|
33
|
-
self._algorithm_name: str = algorithm.lower()
|
34
|
-
self._algorithm = self._set_algorithm()
|
35
|
-
self._prefix: str = prefix
|
36
|
-
self._postfix: str = postfix
|
37
|
-
self._characters_replacements: dict = characters_replacements
|
38
|
-
|
39
|
-
@property
|
40
|
-
def shift(self) -> int:
|
41
|
-
"""
|
42
|
-
Returns the shift value for the cipher algorithm
|
43
|
-
Eg: ```shift = pg.shift```
|
44
|
-
:return: int: The shift value for the cipher algorithm
|
45
|
-
"""
|
46
|
-
return self._shift
|
47
|
-
|
48
|
-
@shift.setter
|
49
|
-
def shift(self, shift: int) -> None:
|
50
|
-
"""
|
51
|
-
Sets the shift value for the cipher algorithm
|
52
|
-
Eg: ```pg.shift = 3```
|
53
|
-
:param shift: The shift value for the cipher algorithm
|
54
|
-
:return:
|
55
|
-
"""
|
56
|
-
self._shift = shift
|
57
|
-
|
58
|
-
@property
|
59
|
-
def multiplier(self) -> int:
|
60
|
-
"""
|
61
|
-
Returns the multiplier value for the cipher algorithm
|
62
|
-
Eg: ```multiplier = pg.multiplier```
|
63
|
-
:return: int: The multiplier value for the cipher algorithm
|
64
|
-
"""
|
65
|
-
return self._multiplier
|
66
|
-
|
67
|
-
@multiplier.setter
|
68
|
-
def multiplier(self, multiplier: int) -> None:
|
69
|
-
"""
|
70
|
-
Sets the multiplier value for the cipher algorithm
|
71
|
-
Eg: ```pg.multiplier = 3```
|
72
|
-
:param multiplier: The multiplier value for the cipher algorithm
|
73
|
-
:return:
|
74
|
-
"""
|
75
|
-
self._multiplier = multiplier
|
76
|
-
|
77
|
-
@property
|
78
|
-
def key(self) -> str:
|
79
|
-
"""
|
80
|
-
Returns the key string for the cipher algorithm
|
81
|
-
Eg: ```key = pg.key```
|
82
|
-
:return: str: The key string for the cipher algorithm
|
83
|
-
"""
|
84
|
-
return self._key
|
85
|
-
|
86
|
-
@key.setter
|
87
|
-
def key(self, key: str) -> None:
|
88
|
-
"""
|
89
|
-
Sets the key string for the cipher algorithm
|
90
|
-
Eg: ```pg.key = 'secret key'```
|
91
|
-
:param key: The key string for the cipher algorithm
|
92
|
-
:return:
|
93
|
-
"""
|
94
|
-
self._key = key
|
95
|
-
|
96
|
-
@property
|
97
|
-
def prefix(self) -> str:
|
98
|
-
"""
|
99
|
-
Returns the prefix string for the cipher algorithm
|
100
|
-
Eg: ```prefix = pg.prefix```
|
101
|
-
:return: str: The prefix string for the cipher algorithm
|
102
|
-
"""
|
103
|
-
return self._prefix
|
104
|
-
|
105
|
-
@prefix.setter
|
106
|
-
def prefix(self, prefix: str):
|
107
|
-
"""
|
108
|
-
Sets the prefix string for the cipher algorithm
|
109
|
-
Eg: ```pg.prefix = 'something'```
|
110
|
-
:param prefix: The string for the cipher algorithm
|
111
|
-
:return:
|
112
|
-
"""
|
113
|
-
self._prefix = prefix
|
114
|
-
|
115
|
-
@property
|
116
|
-
def postfix(self) -> str:
|
117
|
-
"""
|
118
|
-
Returns the postfix string for the cipher algorithm
|
119
|
-
Eg: ```postfix = pg.postfix```
|
120
|
-
:return: str: The postfix string for the cipher algorithm
|
121
|
-
"""
|
122
|
-
return self._postfix
|
123
|
-
|
124
|
-
@postfix.setter
|
125
|
-
def postfix(self, postfix: str):
|
126
|
-
"""
|
127
|
-
Sets the postfix string for the cipher algorithm
|
128
|
-
Eg: ```pg.postfix = 'something'```
|
129
|
-
:param postfix: The string for the cipher algorithm
|
130
|
-
:return:
|
131
|
-
"""
|
132
|
-
self._postfix = postfix
|
133
|
-
|
134
|
-
@property
|
135
|
-
def algorithm(self) -> str:
|
136
|
-
"""
|
137
|
-
Returns the main cipher algorithm name
|
138
|
-
Eg: ```algorithm = pg.algorithm```
|
139
|
-
:return: str: The main cipher algorithm name
|
140
|
-
"""
|
141
|
-
return self._algorithm_name
|
142
|
-
|
143
|
-
@algorithm.setter
|
144
|
-
def algorithm(self, algorithm: str) -> None:
|
145
|
-
"""
|
146
|
-
Sets the main cipher algorithm
|
147
|
-
Eg: ```pg.algorithm = 'playfair'```
|
148
|
-
:param algorithm: The name of the main cipher algorithm
|
149
|
-
:return:
|
150
|
-
"""
|
151
|
-
self._algorithm_name = algorithm.lower()
|
152
|
-
self._algorithm = self._set_algorithm()
|
153
|
-
|
154
|
-
@property
|
155
|
-
def characters_replacements(self) -> dict:
|
156
|
-
"""
|
157
|
-
Returns the dictionary of the characters replacements
|
158
|
-
Eg: ```print(pg.characters_replacements) # {'a': '@1', 'b': '#2'}```
|
159
|
-
:return: dict: The dictionary of the characters replacements
|
160
|
-
"""
|
161
|
-
return self._characters_replacements
|
162
|
-
|
163
|
-
def _set_algorithm(self):
|
164
|
-
"""
|
165
|
-
Return new instance of the used algorithm to the given one by it's name
|
166
|
-
:return: new algorithm class
|
167
|
-
"""
|
168
|
-
match self._algorithm_name:
|
169
|
-
case 'caesar':
|
170
|
-
return CaesarCipher(self._shift)
|
171
|
-
case 'affine':
|
172
|
-
return AffineCipher(self._shift, self._multiplier)
|
173
|
-
case 'playfair':
|
174
|
-
return PlayfairCipher(self._key)
|
175
|
-
case 'hill':
|
176
|
-
return HillCipher(self._key)
|
177
|
-
case _:
|
178
|
-
raise InvalidAlgorithmException(self._algorithm_name)
|
179
|
-
|
180
|
-
def _update_algorithm_properties(self) -> None:
|
181
|
-
"""
|
182
|
-
Update the main cipher algorithm
|
183
|
-
"""
|
184
|
-
self._algorithm = self._set_algorithm()
|
185
|
-
|
186
|
-
def replace_character(self, char: str, replacement: str) -> None:
|
187
|
-
"""
|
188
|
-
Replace a character with another character or set of characters
|
189
|
-
Eg: pg.replace_character('a', '@1')
|
190
|
-
:param char: The character to be replaced
|
191
|
-
:param replacement: The (character|set of characters) to replace the first one
|
192
|
-
:return:
|
193
|
-
"""
|
194
|
-
self._characters_replacements[char[0]] = replacement
|
195
|
-
|
196
|
-
def reset_character(self, char: str) -> None:
|
197
|
-
"""
|
198
|
-
Reset a character to it's original value (remove it's replacement from characters_replacements)
|
199
|
-
:param char: The character to be reset to its original value
|
200
|
-
:return:
|
201
|
-
"""
|
202
|
-
if char in self._characters_replacements:
|
203
|
-
del self._characters_replacements[char]
|
204
|
-
|
205
|
-
def generate_raw_password(self, text: str) -> str:
|
206
|
-
"""
|
207
|
-
Generate a raw password string using the given parameters
|
208
|
-
:return: str: The generated raw password
|
209
|
-
"""
|
210
|
-
self._update_algorithm_properties()
|
211
|
-
return self._algorithm.encrypt(f"{self._prefix}{text}{self._postfix}")
|
212
|
-
|
213
|
-
def generate_password(self, text: str) -> str:
|
214
|
-
"""
|
215
|
-
Generate a strong password string using the raw password (add another layer of encryption to it)
|
216
|
-
:return: str: The generated strong password
|
217
|
-
"""
|
218
|
-
old_algorithm = self._algorithm_name
|
219
|
-
self._algorithm_name = 'affine'
|
220
|
-
password = self.generate_raw_password(text)
|
221
|
-
self._algorithm_name = old_algorithm
|
222
|
-
password = self.generate_raw_password(password)
|
223
|
-
for char, replacement in self._characters_replacements.items():
|
224
|
-
password = password.replace(char, replacement)
|
225
|
-
for char in password:
|
226
|
-
if char in text:
|
227
|
-
password = password.replace(char, char.upper())
|
228
|
-
return password
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|