-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbase.py
122 lines (97 loc) · 3.65 KB
/
base.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
from cryptography import fernet
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
import hashlib
import uuid
import base64
class ChildNotFoundException(Exception):
pass
class Node:
def __init__(self,
parent_key: bytes,
name: bytes = None,
children: list["Node"] = None,
content: bytes = None,
password: bytes = None
):
self.name = name
self.uuid = uuid.uuid4().bytes
self.children = []
if children:
self.children = children
key = self.get_key(parent_key=parent_key)
f = fernet.Fernet(key)
if content == None:
content = b"no content"
self.content = f.encrypt(content)
self.enc_key = None
if password:
self.set_password(parent_key=parent_key, password=password)
def get_key(self, parent_key: bytes=None, password: bytes=None):
assert parent_key != None or password != None
if parent_key:
key_hash = hashlib.sha256(parent_key, usedforsecurity=True)
key_hash = key_hash.digest()
return key_from_hash(key_hash, self.uuid)
elif password:
assert self.enc_key != None
passw_key = self.get_key(parent_key=password)
f = fernet.Fernet(passw_key)
return f.decrypt(self.enc_key)
def get_content(self, key):
assert self.content != None
f = fernet.Fernet(key)
return f.decrypt(self.content)
def set_password(self, password: bytes, parent_key: bytes=None, old_pass=None):
assert parent_key != None or old_pass != None
key = None
if parent_key:
key = self.get_key(parent_key=parent_key)
elif old_pas:
key = self.get_key(password=old_pass)
assert key != None
# this will fail if you have the wrong key
# to make sure you have the correct key, call get_content
self.get_content(key)
password_key = self.get_key(parent_key=password)
f = fernet.Fernet(password_key)
self.enc_key = f.encrypt(key)
def update_content(self, key, content: bytes):
f = fernet.Fernet(key)
# this will fail if you have the wrong key
# and is used so you don't overwrite the content with content encrypted with the wrong key
f.decrypt(self.content)
self.content = f.encrypt(content)
def get_child_node(self, path: list[str]):
if len(path) == 0:
return self
for child in self.children:
if child.name == path[0]:
return child.get_child_node(path[1:])
raise Exception("child wasn't found")
def get_child_key(self, key, path: list[str]):
if len(path) == 0:
return key
for child in self.children:
if child.name == path[0]:
child_key = child.get_key(parent_key=key)
return child.get_child_key(child_key, path[1:])
raise ChildNotFoundException("child wasn't found")
def to_json(self):
json = {
"name": self.name,
"uuid": self.uuid,
"content": self.content,
"children": []
}
for child in self.children:
json["children"].append(child.to_json())
return json
def key_from_hash(password_hash: bytes, salt: bytes):
kdf = PBKDF2HMAC(
algorithm=hashes.SHA256(),
length=32,
salt=salt,
iterations=100000
)
return base64.urlsafe_b64encode(kdf.derive(password_hash))