SwiftGUI_Encryption 0.0.3__tar.gz → 0.0.5__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.
- {swiftgui_encryption-0.0.3 → swiftgui_encryption-0.0.5}/PKG-INFO +1 -1
- {swiftgui_encryption-0.0.3 → swiftgui_encryption-0.0.5}/pyproject.toml +1 -1
- {swiftgui_encryption-0.0.3 → swiftgui_encryption-0.0.5}/src/SwiftGUI_Encryption/Advanced/__init__.py +1 -1
- {swiftgui_encryption-0.0.3 → swiftgui_encryption-0.0.5}/src/SwiftGUI_Encryption/Advanced/low_level.py +29 -0
- {swiftgui_encryption-0.0.3 → swiftgui_encryption-0.0.5}/src/SwiftGUI_Encryption/__init__.py +1 -1
- {swiftgui_encryption-0.0.3 → swiftgui_encryption-0.0.5}/src/SwiftGUI_Encryption/basics.py +56 -5
- {swiftgui_encryption-0.0.3 → swiftgui_encryption-0.0.5}/src/SwiftGUI_Encryption/sg/dictFile.py +9 -2
- {swiftgui_encryption-0.0.3 → swiftgui_encryption-0.0.5}/LICENSE +0 -0
- {swiftgui_encryption-0.0.3 → swiftgui_encryption-0.0.5}/README.md +0 -0
- {swiftgui_encryption-0.0.3 → swiftgui_encryption-0.0.5}/src/SwiftGUI_Encryption/key_files.py +0 -0
- {swiftgui_encryption-0.0.3 → swiftgui_encryption-0.0.5}/src/SwiftGUI_Encryption/sg/__init__.py +0 -0
- {swiftgui_encryption-0.0.3 → swiftgui_encryption-0.0.5}/src/SwiftGUI_Encryption/sg/popup_create_password.py +0 -0
|
@@ -45,6 +45,35 @@ def argon2_key_derivation(derive_from: bytes, salt: bytes, multiplier: int = 1,
|
|
|
45
45
|
|
|
46
46
|
return argon2pure.argon2(derive_from, salt, multiplier, 8 * multiplier, parallelism=1, tag_length=n)
|
|
47
47
|
|
|
48
|
+
def encrypt_CTR(data: bytes, key: bytes, nonce: bytes) -> bytes:
|
|
49
|
+
"""
|
|
50
|
+
Encrypt some data in AES-256-CTR mode.
|
|
51
|
+
|
|
52
|
+
:param data:
|
|
53
|
+
:param key:
|
|
54
|
+
:param nonce: A 12-byte random number, which you should definetly remember
|
|
55
|
+
:return: Encrypted
|
|
56
|
+
"""
|
|
57
|
+
crypter = AES.new(key, AES.MODE_CTR, nonce=nonce)
|
|
58
|
+
enc_data = crypter.encrypt(data)
|
|
59
|
+
|
|
60
|
+
return enc_data
|
|
61
|
+
|
|
62
|
+
def decrypt_CTR(enc_data:bytes, key:bytes, nonce:bytes) -> bytes:
|
|
63
|
+
"""
|
|
64
|
+
Decrypt some data in AES-256-CTR mode.
|
|
65
|
+
The decrypted data is not verified, since this isn't a feature of AES-CTR
|
|
66
|
+
|
|
67
|
+
:param enc_data: Encrypted data
|
|
68
|
+
:param key: This needs to be the same as with the encryption
|
|
69
|
+
:param nonce: This needs to be the same as with the encryption
|
|
70
|
+
:return:
|
|
71
|
+
"""
|
|
72
|
+
crypter = AES.new(key, AES.MODE_CTR, nonce=nonce)
|
|
73
|
+
data = crypter.decrypt(enc_data)
|
|
74
|
+
|
|
75
|
+
return data
|
|
76
|
+
|
|
48
77
|
def encrypt(data: bytes, key: bytes, nonce: bytes, mac_len: int = 8) -> bytes:
|
|
49
78
|
"""
|
|
50
79
|
Encrypt some data.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
from . import Advanced
|
|
3
3
|
random_key = Advanced.random_key
|
|
4
4
|
|
|
5
|
-
from .basics import decrypt_full, encrypt_full, encrypt_with_password, decrypt_with_password, password_to_key
|
|
5
|
+
from .basics import decrypt_full, encrypt_full, encrypt_with_password, decrypt_with_password, password_to_key, encrypt_multilayer, decrypt_multilayer
|
|
6
6
|
from .key_files import KeyFile, KeyHandler, BaseKeyFile
|
|
7
7
|
|
|
8
8
|
try:
|
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
import argon2pure
|
|
2
|
-
from Crypto.Cipher import AES
|
|
3
|
-
import os
|
|
4
|
-
import hashlib
|
|
5
|
-
|
|
6
1
|
from SwiftGUI_Encryption import Advanced as adv
|
|
7
2
|
|
|
8
3
|
# This should not be chanced, it just doesn't feel right to add magic numbers...
|
|
@@ -34,6 +29,62 @@ def decrypt_full(data: bytes, key: bytes) -> bytes:
|
|
|
34
29
|
|
|
35
30
|
return adv.decrypt(data, key, nonce)
|
|
36
31
|
|
|
32
|
+
def encrypt_multilayer(data: bytes, *keys: bytes) -> bytes:
|
|
33
|
+
"""
|
|
34
|
+
Encrypt some data multiple times.
|
|
35
|
+
Pass a key for every layer of encryption.
|
|
36
|
+
|
|
37
|
+
This is overkill for most applications.
|
|
38
|
+
A single AES-256-GCM-encryption is already very secure, even against quantumcomputers.
|
|
39
|
+
|
|
40
|
+
VERY IMPORTANT:
|
|
41
|
+
To attack even a 3-layer-encryption is basically impossible.
|
|
42
|
+
So the attack will be on the keys, not the encryption.
|
|
43
|
+
Make sure the keys are secure, they are the weakest link.
|
|
44
|
+
|
|
45
|
+
Also, don't correlate the keys in any way.
|
|
46
|
+
If you can calculate key2 from key1, it defies the whole reason for this multilayer-encryption.
|
|
47
|
+
|
|
48
|
+
KINDA IMPORTANT:
|
|
49
|
+
Using two keys is only a little better than one key, because someone could do a "meet-in-the-middle-attack".
|
|
50
|
+
As a general rule, you should use an odd number of keys.
|
|
51
|
+
|
|
52
|
+
TECHNICALITIES:
|
|
53
|
+
Only the innermost encryption is using AES-GCM Mode. All other layers are AES-CTR.
|
|
54
|
+
That's because full AES-GCM allows guessing, if the decryption was successful.
|
|
55
|
+
Especially for short data, you could brute-force through layer by layer, leaving only a few possible keys per layer.
|
|
56
|
+
|
|
57
|
+
So, this function disables that verification-step for the outer layers.
|
|
58
|
+
You can only check if the full decryption was a success, but not separate layers.
|
|
59
|
+
|
|
60
|
+
:return:
|
|
61
|
+
"""
|
|
62
|
+
# GCM encryption
|
|
63
|
+
data = encrypt_full(data, keys[0])
|
|
64
|
+
|
|
65
|
+
# CTR encryptions
|
|
66
|
+
for key in keys[1:]:
|
|
67
|
+
nonce = adv.random_key(12)
|
|
68
|
+
data = nonce + adv.encrypt_CTR(data, key, nonce)
|
|
69
|
+
|
|
70
|
+
return data
|
|
71
|
+
|
|
72
|
+
def decrypt_multilayer(data: bytes, *keys: bytes) -> bytes:
|
|
73
|
+
"""
|
|
74
|
+
Read the description of encrypt_multilayer.
|
|
75
|
+
|
|
76
|
+
The keys have to be in the same order as with the encryption.
|
|
77
|
+
|
|
78
|
+
:return:
|
|
79
|
+
"""
|
|
80
|
+
# CTR encryptions
|
|
81
|
+
for key in keys[1:][::-1]:
|
|
82
|
+
nonce = data[:12]
|
|
83
|
+
data = adv.decrypt_CTR(data[12:], key, nonce)
|
|
84
|
+
|
|
85
|
+
# GCM encryption
|
|
86
|
+
return decrypt_full(data, keys[0])
|
|
87
|
+
|
|
37
88
|
def encrypt_with_password(data: bytes, password: str, security_multiplier: int = 1) -> bytes:
|
|
38
89
|
"""
|
|
39
90
|
IMPORTANT:
|
{swiftgui_encryption-0.0.3 → swiftgui_encryption-0.0.5}/src/SwiftGUI_Encryption/sg/dictFile.py
RENAMED
|
@@ -107,8 +107,10 @@ class PasswordJSONDictFile(EncryptedJSONDictFile):
|
|
|
107
107
|
**kwargs
|
|
108
108
|
)
|
|
109
109
|
|
|
110
|
-
def _regenerate_key(self):
|
|
111
|
-
|
|
110
|
+
def _regenerate_key(self, new_salt = True):
|
|
111
|
+
if new_salt:
|
|
112
|
+
self._salt = random_key(SALT_LEN)
|
|
113
|
+
|
|
112
114
|
self._filekey = adv.argon2_key_derivation(self._password.encode(), self._salt)
|
|
113
115
|
|
|
114
116
|
def change_key(self, new_key: bytes):
|
|
@@ -151,6 +153,11 @@ class PasswordJSONDictFile(EncryptedJSONDictFile):
|
|
|
151
153
|
) -> dict:
|
|
152
154
|
raw = path.read_bytes()
|
|
153
155
|
|
|
156
|
+
salt = raw[:SALT_LEN]
|
|
157
|
+
if salt != self._salt:
|
|
158
|
+
self._salt = salt
|
|
159
|
+
self._regenerate_key(new_salt=False)
|
|
160
|
+
|
|
154
161
|
raw = decrypt_full(raw[SALT_LEN:], self._filekey).decode()
|
|
155
162
|
return json.loads(raw)
|
|
156
163
|
|
|
File without changes
|
|
File without changes
|
{swiftgui_encryption-0.0.3 → swiftgui_encryption-0.0.5}/src/SwiftGUI_Encryption/key_files.py
RENAMED
|
File without changes
|
{swiftgui_encryption-0.0.3 → swiftgui_encryption-0.0.5}/src/SwiftGUI_Encryption/sg/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|