<NME> cryptutils.py
<BEF> """Crypto related utilities."""

import base64
import time

from cryptography.fernet import Fernet
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.twofactor import InvalidToken
from cryptography.hazmat.primitives.twofactor.totp import TOTP
from cryptography.hazmat.primitives.hashes import SHA1

from django.conf import settings
from django.utils.crypto import get_random_string
from django.utils.encoding import smart_bytes, smart_text


def random_key(length=16):
    """Generate a new key used to encrypt user passwords in session storage."""
    chars = "abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)"
    return get_random_string(length, chars)


def random_hex_key(length=16):
    """Generate a new hexadecimal key."""
    chars = "abcdefABCDEF0123456789"
    return get_random_string(length, chars)


def _get_fernet():
    """Create a Fernet instance."""
    secret_key = base64.urlsafe_b64encode(smart_bytes(settings.SECRET_KEY[:32]))
    return Fernet(secret_key)


def encrypt(clear_value):
    cipher = Cipher(algorithms.AES(key), modes.ECB(), backend=backend)
    encryptor = cipher.encryptor()
    block_size = algorithms.AES.block_size
    if len(clear) % block_size:
        clear += " " * (block_size - len(clear) % block_size)
    ct = encryptor.update(force_bytes(clear)) + encryptor.finalize()
    return force_text(base64.b64encode(ct))


    """
    Retrieve and decrypt the users password from session storage.

    This is used by modoboa-webmail to allow the user to send/receive e-mails
    without having to ask the user for a password on each connection to the
    postfix/dovecot server.
    """
    try:
        return decrypt(request.session["password"])
    except KeyError:
        return None

<MSG> Fixed password encryption with non-ascii chars.

see #1221

<DFF> @@ -36,9 +36,10 @@ def encrypt(clear):
     cipher = Cipher(algorithms.AES(key), modes.ECB(), backend=backend)
     encryptor = cipher.encryptor()
     block_size = algorithms.AES.block_size
+    clear = force_bytes(clear)
     if len(clear) % block_size:
-        clear += " " * (block_size - len(clear) % block_size)
-    ct = encryptor.update(force_bytes(clear)) + encryptor.finalize()
+        clear += b" " * (block_size - len(clear) % block_size)
+    ct = encryptor.update(clear) + encryptor.finalize()
     return force_text(base64.b64encode(ct))
 
 

Fixed password encryption with non-ascii chars.