SwiftGUI_Encryption 0.0.4__tar.gz → 0.0.6__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: SwiftGUI_Encryption
3
- Version: 0.0.4
3
+ Version: 0.0.6
4
4
  Summary: Useful encryption-features for SwiftGUI-applications based on PyCryptoDome
5
5
  License-Expression: Apache-2.0
6
6
  License-File: LICENSE
@@ -31,4 +31,15 @@ I let you use my encryption-schemes, so you won't have to dive deep into cryptog
31
31
 
32
32
  Also, this package can be used as an addon for SwiftGUI, but doesn't have to be.
33
33
 
34
+ # Installation
35
+ Open your terminal and execute this:
36
+ ```bash
37
+ pip install SwiftGUI_Encryption
38
+ ```
39
+
40
+ # Dependancies
41
+ This package wouldn't be possible without the following open-source packages:
42
+ - `PyCryptoDome`: A Python-package featuring a lot of cryptography algorithms
43
+ - `argon2pure`: A small package implementing the argon2-key-derivation algorithm
44
+
34
45
 
@@ -13,3 +13,14 @@ I let you use my encryption-schemes, so you won't have to dive deep into cryptog
13
13
 
14
14
  Also, this package can be used as an addon for SwiftGUI, but doesn't have to be.
15
15
 
16
+ # Installation
17
+ Open your terminal and execute this:
18
+ ```bash
19
+ pip install SwiftGUI_Encryption
20
+ ```
21
+
22
+ # Dependancies
23
+ This package wouldn't be possible without the following open-source packages:
24
+ - `PyCryptoDome`: A Python-package featuring a lot of cryptography algorithms
25
+ - `argon2pure`: A small package implementing the argon2-key-derivation algorithm
26
+
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "SwiftGUI_Encryption"
3
- version = "0.0.4"
3
+ version = "0.0.6"
4
4
  packages = [
5
5
  { include = "SwiftGUI_Encryption", from = "src" }
6
6
  ]
@@ -1,3 +1,3 @@
1
1
 
2
- from .low_level import encrypt, decrypt, readable_hash, make_hash, random_key, argon2_key_derivation
2
+ from .low_level import encrypt, decrypt, readable_hash, make_hash, random_key, argon2_key_derivation, encrypt_CTR, decrypt_CTR
3
3
 
@@ -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.
@@ -65,7 +94,7 @@ def encrypt(data: bytes, key: bytes, nonce: bytes, mac_len: int = 8) -> bytes:
65
94
  def decrypt(enc_data:bytes, key:bytes, nonce:bytes, mac_len: int = 8) -> bytes:
66
95
  """
67
96
  Decrypt some data.
68
- The tag needs to be appended to the data.
97
+ The tag needs to be appended to the front of the data.
69
98
 
70
99
  Raises a value-error if the data was manipulated (tag is invalid)
71
100
 
@@ -84,4 +113,3 @@ def decrypt(enc_data:bytes, key:bytes, nonce:bytes, mac_len: int = 8) -> bytes:
84
113
  crypter.verify(tag)
85
114
 
86
115
  return data
87
-
@@ -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,70 @@ 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
+ Don't correlate the keys in any way.
42
+ If you calculate key2 from key1, you can just leave out key2.
43
+ DON'T DO SECURITY-BY-OBSCURITY!
44
+
45
+ KINDA IMPORTANT:
46
+ Using two keys is only a little more secure than one key, because someone could do a "meet-in-the-middle-attack".
47
+ As a general rule, you should only use an odd number of keys.
48
+
49
+ TECHNICALITIES:
50
+ Only the innermost encryption is using AES-GCM Mode. All other layers are AES-CTR.
51
+ That's because full AES-GCM allows guessing, if the decryption was successful.
52
+ Especially for short data, you could brute-force through layer by layer, leaving only a few possible keys per layer.
53
+
54
+ So, this function disables that verification-step for the outer layers.
55
+ You can only check if the full decryption was a success, but not separate layers.
56
+
57
+ :return:
58
+ """
59
+ # GCM encryption
60
+ first_nonce = adv.random_key(NONCE_LEN)
61
+ nonce = first_nonce
62
+ data = adv.encrypt(data, keys[0], nonce)
63
+
64
+ # CTR encryptions
65
+ for key in keys[1:]:
66
+ nonce = adv.make_hash(nonce)[:12]
67
+ data = adv.encrypt_CTR(data, key, nonce)
68
+
69
+ return first_nonce + data
70
+
71
+ def decrypt_multilayer(data: bytes, *keys: bytes) -> bytes:
72
+ """
73
+ Read the description of encrypt_multilayer.
74
+
75
+ The keys have to be in the same order as with the encryption.
76
+
77
+ :return:
78
+ """
79
+ first_nonce = data[:NONCE_LEN]
80
+ data = data[NONCE_LEN:]
81
+
82
+ nonce = first_nonce
83
+ nonces = list()
84
+
85
+ for i in range(len(keys) - 1):
86
+ nonce = adv.make_hash(nonce)[:12]
87
+ nonces.append(nonce)
88
+
89
+ # CTR encryptions
90
+ for nonce, key in zip(nonces[::-1], keys[1:][::-1]):
91
+ data = adv.decrypt_CTR(data, key, nonce)
92
+
93
+ # GCM encryption
94
+ return adv.decrypt(data, keys[0], first_nonce)
95
+
37
96
  def encrypt_with_password(data: bytes, password: str, security_multiplier: int = 1) -> bytes:
38
97
  """
39
98
  IMPORTANT: