Mercurial > libervia-backend
annotate sat/memory/crypto.py @ 3087:a51f7fce1e2c
tools (stream): data modification on SatFile:
- if `data_cb` is used and if it returns a not None value, it is used instead of the data
read from the file. This allows data modification on the fly, useful notably for
encryption
- new `check_size_with_read` argument which check size on `close()` using amount of data
actually read/written instead of file size. This avoid a warning when file is modified
on the fly
- added `closed` attribute
author | Goffi <goffi@goffi.org> |
---|---|
date | Fri, 20 Dec 2019 12:28:04 +0100 |
parents | fee60f17ebac |
children | 9d0df638c8b4 |
rev | line source |
---|---|
3028 | 1 #!/usr/bin/env python3 |
1028
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
2 # -*- coding: utf-8 -*- |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
3 |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
4 # SAT: a jabber client |
2771 | 5 # Copyright (C) 2009-2019 Jérôme Poisson (goffi@goffi.org) |
1766 | 6 # Copyright (C) 2013-2016 Adrien Cossa (souliane@mailoo.org) |
1028
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
7 |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
8 # This program is free software: you can redistribute it and/or modify |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
9 # it under the terms of the GNU Affero General Public License as published by |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
10 # the Free Software Foundation, either version 3 of the License, or |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
11 # (at your option) any later version. |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
12 |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
13 # This program is distributed in the hope that it will be useful, |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
16 # GNU Affero General Public License for more details. |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
17 |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
18 # You should have received a copy of the GNU Affero General Public License |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
19 # along with this program. If not, see <http://www.gnu.org/licenses/>. |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
20 |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
21 try: |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
22 from Crypto.Cipher import AES |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
23 from Crypto.Protocol.KDF import PBKDF2 |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
24 except ImportError: |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
25 raise Exception("PyCrypto is not installed.") |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
26 |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
27 from os import urandom |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
28 from base64 import b64encode, b64decode |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
29 from twisted.internet.threads import deferToThread |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
30 from twisted.internet.defer import succeed |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
31 |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
32 |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
33 class BlockCipher(object): |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
34 |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
35 BLOCK_SIZE = AES.block_size # 16 bits |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
36 MAX_KEY_SIZE = AES.key_size[-1] # 32 bits = AES-256 |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
37 IV_SIZE = BLOCK_SIZE # initialization vector size, 16 bits |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
38 |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
39 @classmethod |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
40 def encrypt(cls, key, text, leave_empty=True): |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
41 """Encrypt a message. |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
42 |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
43 Based on http://stackoverflow.com/a/12525165 |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
44 |
1098
77cd312d32c4
memory: fixes encoding issues during encryption
souliane <souliane@mailoo.org>
parents:
1028
diff
changeset
|
45 @param key (unicode): the encryption key |
77cd312d32c4
memory: fixes encoding issues during encryption
souliane <souliane@mailoo.org>
parents:
1028
diff
changeset
|
46 @param text (unicode): the text to encrypt |
1028
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
47 @param leave_empty (bool): if True, empty text will be returned "as is" |
3040 | 48 @return (D(str)): base-64 encoded encrypted message |
1028
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
49 """ |
2624
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
50 if leave_empty and text == "": |
1028
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
51 return succeed(text) |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
52 iv = BlockCipher.getRandomKey() |
2624
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
53 key = key.encode("utf-8") |
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
54 key = ( |
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
55 key[: BlockCipher.MAX_KEY_SIZE] |
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
56 if len(key) >= BlockCipher.MAX_KEY_SIZE |
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
57 else BlockCipher.pad(key) |
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
58 ) |
1028
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
59 cipher = AES.new(key, AES.MODE_CFB, iv) |
2624
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
60 d = deferToThread(cipher.encrypt, BlockCipher.pad(text.encode("utf-8"))) |
1028
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
61 d.addCallback(lambda ciphertext: b64encode(iv + ciphertext)) |
3040 | 62 d.addCallback(lambda bytes_cypher: bytes_cypher.decode('utf-8')) |
1028
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
63 return d |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
64 |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
65 @classmethod |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
66 def decrypt(cls, key, ciphertext, leave_empty=True): |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
67 """Decrypt a message. |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
68 |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
69 Based on http://stackoverflow.com/a/12525165 |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
70 |
1098
77cd312d32c4
memory: fixes encoding issues during encryption
souliane <souliane@mailoo.org>
parents:
1028
diff
changeset
|
71 @param key (unicode): the decryption key |
1028
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
72 @param ciphertext (base-64 encoded str): the text to decrypt |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
73 @param leave_empty (bool): if True, empty ciphertext will be returned "as is" |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
74 @return: Deferred: str or None if the password could not be decrypted |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
75 """ |
2624
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
76 if leave_empty and ciphertext == "": |
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
77 return succeed("") |
1028
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
78 ciphertext = b64decode(ciphertext) |
2624
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
79 iv, ciphertext = ( |
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
80 ciphertext[: BlockCipher.IV_SIZE], |
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
81 ciphertext[BlockCipher.IV_SIZE :], |
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
82 ) |
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
83 key = key.encode("utf-8") |
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
84 key = ( |
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
85 key[: BlockCipher.MAX_KEY_SIZE] |
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
86 if len(key) >= BlockCipher.MAX_KEY_SIZE |
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
87 else BlockCipher.pad(key) |
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
88 ) |
1028
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
89 cipher = AES.new(key, AES.MODE_CFB, iv) |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
90 d = deferToThread(cipher.decrypt, ciphertext) |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
91 d.addCallback(lambda text: BlockCipher.unpad(text)) |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
92 # XXX: cipher.decrypt gives no way to make the distinction between |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
93 # a decrypted empty value and a decryption failure... both return |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
94 # the empty value. Fortunately, we detect empty passwords beforehand |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
95 # thanks to the "leave_empty" parameter which is used by default. |
3028 | 96 d.addCallback(lambda text: text if text else None) |
1028
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
97 return d |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
98 |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
99 @classmethod |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
100 def getRandomKey(cls, size=None, base64=False): |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
101 """Return a random key suitable for block cipher encryption. |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
102 |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
103 Note: a good value for the key length is to make it as long as the block size. |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
104 |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
105 @param size: key length in bytes, positive or null (default: BlockCipher.IV_SIZE) |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
106 @param base64: if True, encode the result to base-64 |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
107 @return: str (eventually base-64 encoded) |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
108 """ |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
109 if size is None or size < 0: |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
110 size = BlockCipher.IV_SIZE |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
111 key = urandom(size) |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
112 return b64encode(key) if base64 else key |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
113 |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
114 @classmethod |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
115 def pad(self, s): |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
116 """Method from http://stackoverflow.com/a/12525165""" |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
117 bs = BlockCipher.BLOCK_SIZE |
3028 | 118 return s + (bs - len(s) % bs) * (chr(bs - len(s) % bs)).encode('utf-8') |
1028
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
119 |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
120 @classmethod |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
121 def unpad(self, s): |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
122 """Method from http://stackoverflow.com/a/12525165""" |
3028 | 123 s = s.decode('utf-8') |
2624
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
124 return s[0 : -ord(s[-1])] |
1028
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
125 |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
126 |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
127 class PasswordHasher(object): |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
128 |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
129 SALT_LEN = 16 # 128 bits |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
130 |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
131 @classmethod |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
132 def hash(cls, password, salt=None, leave_empty=True): |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
133 """Hash a password. |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
134 |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
135 @param password (str): the password to hash |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
136 @param salt (base-64 encoded str): if not None, use the given salt instead of a random value |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
137 @param leave_empty (bool): if True, empty password will be returned "as is" |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
138 @return: Deferred: base-64 encoded str |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
139 """ |
2624
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
140 if leave_empty and password == "": |
3040 | 141 return succeed("") |
2624
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
142 salt = ( |
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
143 b64decode(salt)[: PasswordHasher.SALT_LEN] |
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
144 if salt |
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
145 else urandom(PasswordHasher.SALT_LEN) |
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
146 ) |
1028
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
147 d = deferToThread(PBKDF2, password, salt) |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
148 d.addCallback(lambda hashed: b64encode(salt + hashed)) |
3040 | 149 d.addCallback(lambda hashed_bytes: hashed_bytes.decode('utf-8')) |
1028
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
150 return d |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
151 |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
152 @classmethod |
3028 | 153 def compare_hash(cls, hashed_attempt, hashed): |
3040 | 154 assert isinstance(hashed, str) |
3028 | 155 return hashed_attempt == hashed |
156 | |
157 @classmethod | |
1028
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
158 def verify(cls, attempt, hashed): |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
159 """Verify a password attempt. |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
160 |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
161 @param attempt (str): the attempt to check |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
162 @param hashed (str): the hash of the password |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
163 @return: Deferred: boolean |
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
164 """ |
3040 | 165 assert isinstance(attempt, str) |
166 assert isinstance(hashed, str) | |
2624
56f94936df1e
code style reformatting using black
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
167 leave_empty = hashed == "" |
1028
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
168 d = PasswordHasher.hash(attempt, hashed, leave_empty) |
3040 | 169 d.addCallback(cls.compare_hash, hashed=hashed) |
1028
127c96020022
memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
170 return d |