annotate sat/memory/crypto.py @ 3254:6cf4bd6972c2

core, frontends: avatar refactoring: /!\ huge commit Avatar logic has been reworked around the IDENTITY plugin: plugins able to handle avatar or other identity related metadata (like nicknames) register to IDENTITY plugin in the same way as for other features like download/upload. Once registered, IDENTITY plugin will call them when suitable in order of priority, and handle caching. Methods to manage those metadata from frontend now use serialised data. For now `avatar` and `nicknames` are handled: - `avatar` is now a dict with `path` + metadata like `media_type`, instead of just a string path - `nicknames` is now a list of nicknames in order of priority. This list is never empty, and `nicknames[0]` should be the preferred nickname to use by frontends in most cases. In addition to contact specified nicknames, user set nickname (the one set in roster) is used in priority when available. Among the side changes done with this commit, there are: - a new `contactGet` bridge method to get roster metadata for a single contact - SatPresenceProtocol.send returns a Deferred to check when it has actually been sent - memory's methods to handle entities data now use `client` as first argument - metadata filter can be specified with `getIdentity` - `getAvatar` and `setAvatar` are now part of the IDENTITY plugin instead of XEP-0054 (and there signature has changed) - `isRoom` and `getBareOrFull` are now part of XEP-0045 plugin - jp avatar/get command uses `xdg-open` first when available for `--show` flag - `--no-cache` has been added to jp avatar/get and identity/get - jp identity/set has been simplified, explicit options (`--nickname` only for now) are used instead of `--field`. `--field` may come back in the future if necessary for extra data. - QuickContactList `SetContact` now handle None as a value, and doesn't use it to delete the metadata anymore - improved cache handling for `metadata` and `nicknames` in quick frontend - new `default` argument in QuickContactList `getCache`
author Goffi <goffi@goffi.org>
date Tue, 14 Apr 2020 21:00:33 +0200
parents 330a5f1d9eea
children be6d91572633
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
3137
559a625a236b fixed shebangs
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
2
1028
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
3 # SAT: a jabber client
3136
9d0df638c8b4 dates update
Goffi <goffi@goffi.org>
parents: 3040
diff changeset
4 # Copyright (C) 2009-2020 Jérôme Poisson (goffi@goffi.org)
1766
d17772b0fe22 copyright update
Goffi <goffi@goffi.org>
parents: 1396
diff changeset
5 # 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
6
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
7 # 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
8 # 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
9 # 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
10 # (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
11
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
12 # 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
13 # 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
14 # 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
15 # 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
16
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
17 # 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
18 # 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
19
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
20 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
21 from base64 import b64encode, b64decode
3160
330a5f1d9eea core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
22 from cryptography.hazmat.primitives import hashes
330a5f1d9eea core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
23 from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
330a5f1d9eea core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
24 from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
330a5f1d9eea core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
25 from cryptography.hazmat.backends import default_backend
330a5f1d9eea core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
26
330a5f1d9eea core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
27
330a5f1d9eea core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
28 crypto_backend = default_backend()
1028
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
29
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
30
3160
330a5f1d9eea core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
31 class BlockCipher:
1028
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
32
3160
330a5f1d9eea core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
33 BLOCK_SIZE = 16
330a5f1d9eea core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
34 MAX_KEY_SIZE = 32
1028
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
35 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
36
3160
330a5f1d9eea core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
37 @staticmethod
330a5f1d9eea core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
38 def encrypt(key, text, leave_empty=True):
1028
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
39 """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
40
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
41 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
42
1098
77cd312d32c4 memory: fixes encoding issues during encryption
souliane <souliane@mailoo.org>
parents: 1028
diff changeset
43 @param key (unicode): the encryption key
77cd312d32c4 memory: fixes encoding issues during encryption
souliane <souliane@mailoo.org>
parents: 1028
diff changeset
44 @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
45 @param leave_empty (bool): if True, empty text will be returned "as is"
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
46 @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
47 """
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
48 if leave_empty and text == "":
3160
330a5f1d9eea core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
49 return ""
1028
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
50 iv = BlockCipher.getRandomKey()
3160
330a5f1d9eea core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
51 key = key.encode()
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
52 key = (
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
53 key[: BlockCipher.MAX_KEY_SIZE]
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
54 if len(key) >= BlockCipher.MAX_KEY_SIZE
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
55 else BlockCipher.pad(key)
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
56 )
1028
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
57
3160
330a5f1d9eea core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
58 cipher = Cipher(algorithms.AES(key), modes.CFB8(iv), backend=crypto_backend)
330a5f1d9eea core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
59 encryptor = cipher.encryptor()
330a5f1d9eea core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
60 encrypted = encryptor.update(BlockCipher.pad(text.encode())) + encryptor.finalize()
330a5f1d9eea core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
61 return b64encode(iv + encrypted).decode()
330a5f1d9eea core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
62
330a5f1d9eea core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
63 @staticmethod
330a5f1d9eea core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
64 def decrypt(key, ciphertext, leave_empty=True):
1028
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
65 """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
66
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
67 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
68
1098
77cd312d32c4 memory: fixes encoding issues during encryption
souliane <souliane@mailoo.org>
parents: 1028
diff changeset
69 @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
70 @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
71 @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
72 @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
73 """
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
74 if leave_empty and ciphertext == "":
3160
330a5f1d9eea core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
75 return ""
1028
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
76 ciphertext = b64decode(ciphertext)
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
77 iv, ciphertext = (
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
78 ciphertext[: BlockCipher.IV_SIZE],
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 )
3160
330a5f1d9eea core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
81 key = key.encode()
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
82 key = (
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
83 key[: BlockCipher.MAX_KEY_SIZE]
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
84 if len(key) >= BlockCipher.MAX_KEY_SIZE
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
85 else BlockCipher.pad(key)
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
86 )
1028
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
87
3160
330a5f1d9eea core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
88 cipher = Cipher(algorithms.AES(key), modes.CFB8(iv), backend=crypto_backend)
330a5f1d9eea core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
89 decryptor = cipher.decryptor()
330a5f1d9eea core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
90 decrypted = decryptor.update(ciphertext) + decryptor.finalize()
330a5f1d9eea core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
91 return BlockCipher.unpad(decrypted)
330a5f1d9eea core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
92
330a5f1d9eea core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
93 @staticmethod
330a5f1d9eea core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
94 def getRandomKey(size=None, base64=False):
1028
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
95 """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
96
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
97 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
98
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
99 @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
100 @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
101 @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
102 """
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
103 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
104 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
105 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
106 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
107
3160
330a5f1d9eea core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
108 @staticmethod
330a5f1d9eea core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
109 def pad(s):
1028
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
110 """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
111 bs = BlockCipher.BLOCK_SIZE
3160
330a5f1d9eea core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
112 return s + (bs - len(s) % bs) * (chr(bs - len(s) % bs)).encode()
1028
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
113
3160
330a5f1d9eea core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
114 @staticmethod
330a5f1d9eea core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
115 def unpad(s):
1028
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"""
3160
330a5f1d9eea core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
117 s = s.decode()
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
118 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
119
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
120
3160
330a5f1d9eea core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
121 class PasswordHasher:
1028
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
122
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
123 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
124
3160
330a5f1d9eea core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
125 @staticmethod
330a5f1d9eea core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
126 def hash(password, salt=None, leave_empty=True):
1028
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
127 """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
128
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
129 @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
130 @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
131 @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
132 @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
133 """
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
134 if leave_empty and password == "":
3160
330a5f1d9eea core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
135 return ""
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
136 salt = (
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
137 b64decode(salt)[: PasswordHasher.SALT_LEN]
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
138 if salt
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
139 else urandom(PasswordHasher.SALT_LEN)
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
140 )
1028
127c96020022 memory, test: added module crypto to hash passwords and encrypt/decrypt passwords or blocks
souliane <souliane@mailoo.org>
parents:
diff changeset
141
3160
330a5f1d9eea core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
142 # we use PyCrypto's PBKDF2 arguments while porting to crytography, to stay
330a5f1d9eea core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
143 # compatible with existing installations. But this is temporary and we need
330a5f1d9eea core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
144 # to update them to more secure values.
330a5f1d9eea core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
145 kdf = PBKDF2HMAC(
330a5f1d9eea core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
146 # FIXME: SHA1() is not secure, it is used here for historical reasons
330a5f1d9eea core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
147 # and must be changed as soon as possible
330a5f1d9eea core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
148 algorithm=hashes.SHA1(),
330a5f1d9eea core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
149 length=16,
330a5f1d9eea core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
150 salt=salt,
330a5f1d9eea core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
151 iterations=1000,
330a5f1d9eea core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
152 backend=crypto_backend
330a5f1d9eea core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
153 )
330a5f1d9eea core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
154 key = kdf.derive(password.encode())
330a5f1d9eea core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
155 return b64encode(salt + key).decode()
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
156
3160
330a5f1d9eea core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
157 @staticmethod
330a5f1d9eea core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
158 def verify(attempt, pwd_hash):
1028
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
3160
330a5f1d9eea core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
162 @param pwd_hash (str): the hash of the password
1028
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
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
165 assert isinstance(attempt, str)
3160
330a5f1d9eea core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
166 assert isinstance(pwd_hash, str)
330a5f1d9eea core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
167 leave_empty = pwd_hash == ""
330a5f1d9eea core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
168 attempt_hash = PasswordHasher.hash(attempt, pwd_hash, leave_empty)
330a5f1d9eea core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
169 assert isinstance(attempt_hash, str)
330a5f1d9eea core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents: 3137
diff changeset
170 return attempt_hash == pwd_hash