#-*- coding: utf-8 -*-
# (c) 2015 Anders Andersen
# See http://www.cs.uit.no/~aa/dist/tools/py/COPYING for details

# Equal to version 2 in "pycryptex.py", but using CBC mode (not CTR mode).
# With CBC we have to add padding to the text before it is encrypted.

# Load modules
import os
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes, padding

# Shared values (encrypt/decrypt)
pwd = "My secret password"
txt = "Attack at dawn"
icv = os.urandom(algorithms.AES.block_size//8)

# Generate key and encrypt
dig = hashes.Hash(hashes.SHA256(), backend=default_backend())
dig.update(pwd.encode())
key = dig.finalize()
cip = Cipher(algorithms.AES(key), modes.CBC(icv), backend=default_backend())
enc = cip.encryptor()
pdr = padding.PKCS7(algorithms.AES.block_size).padder()
pad = pdr.update(txt.encode()) + pdr.finalize()
msg = enc.update(pad) + enc.finalize()

# Print text and cipher text
print(txt)
print(msg)

# Generate key and decrypt
dig2 = hashes.Hash(hashes.SHA256(), backend=default_backend())
dig2.update(pwd.encode())
key2 = dig2.finalize()
cip2 = Cipher(algorithms.AES(key2), modes.CBC(icv), backend=default_backend())
enc2 = cip2.decryptor()
upr = padding.PKCS7(128).unpadder()
pad2 = enc2.update(msg) + enc2.finalize()
print((upr.update(pad2) + upr.finalize()).decode())