annotate sat/memory/crypto.py @ 3028:ab2696e34d29

Python 3 port: /!\ this is a huge commit /!\ starting from this commit, SàT is needs Python 3.6+ /!\ SàT maybe be instable or some feature may not work anymore, this will improve with time This patch port backend, bridge and frontends to Python 3. Roughly this has been done this way: - 2to3 tools has been applied (with python 3.7) - all references to python2 have been replaced with python3 (notably shebangs) - fixed files not handled by 2to3 (notably the shell script) - several manual fixes - fixed issues reported by Python 3 that where not handled in Python 2 - replaced "async" with "async_" when needed (it's a reserved word from Python 3.7) - replaced zope's "implements" with @implementer decorator - temporary hack to handle data pickled in database, as str or bytes may be returned, to be checked later - fixed hash comparison for password - removed some code which is not needed anymore with Python 3 - deactivated some code which needs to be checked (notably certificate validation) - tested with jp, fixed reported issues until some basic commands worked - ported Primitivus (after porting dependencies like urwid satext) - more manual fixes
author Goffi <goffi@goffi.org>
date Tue, 13 Aug 2019 19:08:41 +0200
parents 003b8b4b56a7
children fee60f17ebac
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
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
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.
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
95 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
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
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
117 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
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"""
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
122 s = s.decode('utf-8')
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
123 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
124
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 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
127
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
128 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
129
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
130 @classmethod
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
131 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
132 """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
133
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
134 @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
135 @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
136 @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
137 @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
138 """
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
139 if leave_empty and password == "":
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
140 return succeed(b"")
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
141 salt = (
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
142 b64decode(salt)[: PasswordHasher.SALT_LEN]
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
143 if salt
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
144 else urandom(PasswordHasher.SALT_LEN)
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
145 )
1028
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
146 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
147 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
148 return d
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
149
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
150 @classmethod
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
151 def compare_hash(cls, hashed_attempt, hashed):
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
152 assert isinstance(hashed, bytes)
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
153 return hashed_attempt == hashed
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
154
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
155 @classmethod
1028
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
156 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
157 """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
158
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
159 @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
160 @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
161 @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
162 """
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
163 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
164 d = PasswordHasher.hash(attempt, hashed, leave_empty)
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
165 d.addCallback(cls.compare_hash, hashed=hashed.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
166 return d