annotate sat/memory/crypto.py @ 2890:c652d079a9a1

core (memory/persistent): added clear method + initialise with a dict: A "clear" method has been added to delete all data for a specific namespace (and profile). Internal cache (self._cache) is not initialised with an empty dict instead of None to allow using methods like __setitem__ or clear without having to do a potentially expansive `load()` before. The only counterpart is that we won't have an exception anymore if developer forget to load() data before using them, which can make debugging a bit more difficult.
author Goffi <goffi@goffi.org>
date Sun, 07 Apr 2019 18:44:57 +0200
parents 003b8b4b56a7
children ab2696e34d29
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1934
2daf7b4c6756 use of /usr/bin/env instead of /usr/bin/python in shebang
Goffi <goffi@goffi.org>
parents: 1766
diff changeset
1 #!/usr/bin/env python2
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
003b8b4b56a7 date update
Goffi <goffi@goffi.org>
parents: 2624
diff changeset
5 # Copyright (C) 2009-2019 Jérôme Poisson (goffi@goffi.org)
1766
d17772b0fe22 copyright update
Goffi <goffi@goffi.org>
parents: 1396
diff changeset
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"
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
48 @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
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))
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
62 return d
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
63
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
64 @classmethod
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
65 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
66 """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
67
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
68 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
69
1098
77cd312d32c4 memory: fixes encoding issues during encryption
souliane <souliane@mailoo.org>
parents: 1028
diff changeset
70 @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
71 @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
72 @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
73 @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
74 """
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
75 if leave_empty and ciphertext == "":
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
76 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
77 ciphertext = b64decode(ciphertext)
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
78 iv, ciphertext = (
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
79 ciphertext[: BlockCipher.IV_SIZE],
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 )
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
82 key = key.encode("utf-8")
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
83 key = (
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
84 key[: BlockCipher.MAX_KEY_SIZE]
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
85 if len(key) >= BlockCipher.MAX_KEY_SIZE
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
86 else BlockCipher.pad(key)
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
87 )
1028
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
88 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
89 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
90 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
91 # 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
92 # 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
93 # 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
94 # thanks to the "leave_empty" parameter which is used by default.
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
95 d.addCallback(lambda text: text.decode("utf-8") 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
96 return d
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
97
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
98 @classmethod
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
99 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
100 """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
101
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
102 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
103
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
104 @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
105 @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
106 @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
107 """
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
108 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
109 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
110 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
111 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
112
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
113 @classmethod
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
114 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
115 """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
116 bs = BlockCipher.BLOCK_SIZE
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
117 return s + (bs - len(s) % bs) * chr(bs - len(s) % bs)
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
118
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
119 @classmethod
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
120 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
121 """Method from http://stackoverflow.com/a/12525165"""
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
122 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
123
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
124
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
125 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
126
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
127 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
128
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
129 @classmethod
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
130 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
131 """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
132
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
133 @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
134 @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
135 @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
136 @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
137 """
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
138 if leave_empty and password == "":
1028
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
139 return succeed(password)
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
140 salt = (
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
141 b64decode(salt)[: PasswordHasher.SALT_LEN]
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
142 if salt
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
143 else urandom(PasswordHasher.SALT_LEN)
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
144 )
1028
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
145 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
146 d.addCallback(lambda hashed: b64encode(salt + hashed))
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
147 return d
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
148
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
149 @classmethod
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
150 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
151 """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
152
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
153 @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
154 @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
155 @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
156 """
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
157 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
158 d = PasswordHasher.hash(attempt, hashed, leave_empty)
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
159 d.addCallback(lambda hashed_attempt: hashed_attempt == hashed)
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
160 return d