]>
Commit | Line | Data |
---|---|---|
1 | # -*- coding: utf-8 -*- | |
2 | ||
3 | # Copyright (c) 2018 Michael Rasmussen <mir@datanom.net> | |
4 | ||
5 | # This file is part of SecureMail. | |
6 | ||
7 | # SecureMail is free software: you can redistribute it and/or modify | |
8 | # it under the terms of the GNU General Public License as published by | |
9 | # the Free Software Foundation, either version 3 of the License, or | |
10 | # (at your option) any later version. | |
11 | # | |
12 | # SecureMail is distributed in the hope that it will be useful, | |
13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | # GNU General Public License for more details. | |
16 | # | |
17 | # You should have received a copy of the GNU General Public License | |
18 | # along with SecureMail. If not, see <https://www.gnu.org/licenses/>. | |
19 | ||
20 | import pickle | |
21 | from db import DBInterface as DBI | |
22 | from cryptonize import Cryptonize | |
23 | from nacl.public import PublicKey | |
24 | from nacl import __version__ as NACL_VERSION | |
25 | ||
26 | class NoSuchUser(Exception): | |
27 | pass | |
28 | ||
29 | class User: | |
30 | """ | |
31 | Class implementing the backend users | |
32 | """ | |
33 | def __init__(self, key=None): | |
34 | if key is not None: | |
35 | self.load(key) | |
36 | else: | |
37 | self.pubkeys = {} | |
38 | ||
39 | def store(self, key): | |
40 | crypto = Cryptonize() | |
41 | if NACL_VERSION < "1.1.0": | |
42 | from nacl.utils import random | |
43 | from nacl.public import SecretBox | |
44 | nonce = random(SecretBox.NONCE_SIZE) | |
45 | cipher = crypto.symmetric_encrypt(key, pickle.dumps(self), nonce) | |
46 | else: | |
47 | cipher = crypto.symmetric_encrypt(key, pickle.dumps(self)) | |
48 | DBI.store_user(crypto.generate_hash(key), cipher) | |
49 | ||
50 | def load(self, key): | |
51 | crypto = Cryptonize() | |
52 | cipher = DBI.load_user(crypto.generate_hash(key)) | |
53 | if cipher is None: | |
54 | raise NoSuchUser('{0}: User not found'.format(key)) | |
55 | plain = crypto.symmetric_decrypt(key, cipher) | |
56 | try: | |
57 | obj = pickle.loads(plain) | |
58 | self.__dict__.update(obj.__dict__) | |
59 | except pickle.UnpicklingError as e: | |
60 | raise e | |
61 | ||
62 | def add_pubkey(self, email, key): | |
63 | if email not in self.pubkeys: | |
64 | self.pubkeys[email] = key.encode() | |
65 | else: | |
66 | raise KeyError('{0}: Exists'.format(email)) | |
67 | ||
68 | def update_pubkey(self, email, key): | |
69 | self.pubkeys[email] = key.encode() | |
70 | ||
71 | def delete_pubkey(self, email): | |
72 | if email in self.pubkeys: | |
73 | del self.pubkeys[email] | |
74 | ||
75 | def get_pubkey(self, email): | |
76 | if email in self.pubkeys: | |
77 | key = self.pubkeys[email] | |
78 | key = PublicKey(key) | |
79 | else: | |
80 | key = None | |
81 | ||
82 | return key | |
83 | ||
84 | @property | |
85 | def name(self): | |
86 | return self._name | |
87 | ||
88 | @name.setter | |
89 | def name(self, name): | |
90 | self._name = name | |
91 | ||
92 | @property | |
93 | def email(self): | |
94 | return self._email | |
95 | ||
96 | @email.setter | |
97 | def email(self, email): | |
98 | self._email = email | |
99 | ||
100 | @property | |
101 | def pubkeys(self): | |
102 | return self._pubkeys | |
103 | ||
104 | @pubkeys.setter | |
105 | def pubkeys(self, pubkeys): | |
106 | if type(pubkeys) is not type({}): | |
107 | raise ValueError('Not dictionary') | |
108 | self._pubkeys = pubkeys | |
109 | ||
110 | if __name__ == '__main__': | |
111 | try: | |
112 | u = User('test') | |
113 | for attr, value in u.__dict__.items(): | |
114 | print ('{0}: {1}'.format(attr, value)) | |
115 | print ('{0} - {1} - {2}'.format(u.name, u.email, u.pubkeys)) | |
116 | key = '' | |
117 | for i in range(40): | |
118 | key += '{0}'.format(i) | |
119 | u = User() | |
120 | u.name = 'testname1' | |
121 | u.email = 'testname1@securemail.icu' | |
122 | u.pubkeys = {'test': 'some test', 'test1': 'some test 1'} | |
123 | try: | |
124 | u.store(key) | |
125 | except: | |
126 | u = User(key) | |
127 | for attr, value in u.__dict__.items(): | |
128 | print ('{0}: {1}'.format(attr, value)) | |
129 | print ('{0} - {1} - {2}'.format(u.name, u.email, u.pubkeys)) | |
130 | from nacl.public import Box | |
131 | c = Cryptonize() | |
132 | keypair1 = c.get_key_pair() | |
133 | keypair2 = c.get_key_pair() | |
134 | try: | |
135 | u.add_pubkey('test', keypair2[1]) | |
136 | except KeyError: | |
137 | u.update_pubkey('test', keypair2[1]) | |
138 | bob_box = Box(keypair1[0], u.get_pubkey('test')) | |
139 | message = "Kill all humans æøåÅØÆ" | |
140 | encrypted = bob_box.encrypt(message.encode()) | |
141 | alice_box = Box(keypair2[0], keypair1[1]) | |
142 | plaintext = alice_box.decrypt(encrypted) | |
143 | print (plaintext.decode()) | |
144 | # c = Cryptonize() | |
145 | # key = 'æselØre' #c.get_random_key() | |
146 | # cipher = c.symmetric_encrypt(key, pickle.dumps(u)) | |
147 | # obj = pickle.loads(c.symmetric_decrypt(key, cipher)) | |
148 | # for attr, value in obj.__dict__.items(): | |
149 | # print ('{0}: {1}'.format(attr, value)) | |
150 | except NoSuchUser: | |
151 | u = User() | |
152 | u.name = 'testname' | |
153 | u.email = 'testname@securemail.icu' | |
154 | u.store('test') | |
155 | except Exception as e: | |
156 | print (e) |