## Python ```python from Crypto.Cipher import AES def pad_pcs7(x): l = len(x) a = l % 16 b = 16 - a c = bytes([b]*b) return x + c def enc(plaintext,phrase,iterations=1234): salt = os.urandom(256) iv = os.urandom(16) key = hashlib.pbkdf2_hmac("sha512",phrase.encode("utf8"),salt,iterations,32) aes = AES.new(key, AES.MODE_CBC, IV=iv) bplaintext = plaintext.encode("utf8") bplaintext = pad_pcs7(bplaintext) ciphertext = aes.encrypt(bplaintext) ciphertext_b64 = b64e(ciphertext) obj = { "ciphertext": ciphertext_b64.decode("utf8"), "salt": salt.hex(), "iv": iv.hex(), "iterations": iterations } return obj ``` I use this, for example, to create SelfDecryptingWebpage's in Python which can be decrypted with Javascript (using CryptoJS). This example class comes from [this stackexchange answer](https://stackoverflow.com/questions/12524994/encrypt-and-decrypt-using-pycrypto-aes-256) ```python import base64 import hashlib from Crypto import Random from Crypto.Cipher import AES class AESCipher(object): def __init__(self, key): self.bs = AES.block_size self.key = hashlib.sha256(key.encode()).digest() def encrypt(self, raw): raw = self._pad(raw) iv = Random.new().read(AES.block_size) cipher = AES.new(self.key, AES.MODE_CBC, iv) return base64.b64encode(iv + cipher.encrypt(raw.encode())) def decrypt(self, enc): enc = base64.b64decode(enc) iv = enc[:AES.block_size] cipher = AES.new(self.key, AES.MODE_CBC, iv) return self._unpad(cipher.decrypt(enc[AES.block_size:])).decode('utf-8') def _pad(self, s): return s + (self.bs - len(s) % self.bs) * chr(self.bs - len(s) % self.bs) @staticmethod def _unpad(s): return s[:-ord(s[len(s)-1:])] ``` ## Javascript This is compatible with the Python encrypt above. Using [cryptojs](https://cdnjs.com/libraries/crypto-js) on my [gitub](https://github.com/johnallsup/crypto-js) ```html ... ``` ```javascript const enc = (passphrase,plaintext,iterations=1977) => { const salt = CryptoJS.lib.WordArray.random(256) const iv = CryptoJS.lib.WordArray.random(16) const key = CryptoJS.PBKDF2(passphrase, salt, { hasher: CryptoJS.algo.SHA512, keySize: 64/8, iterations}) const encrypted = CryptoJS.AES.encrypt(plaintext, key, { iv }) const ciphertext = encrypted.toString() const obj = { ciphertext, salt: salt.toString(CryptoJS.enc.Hex), iv: iv.toString(CryptoJS.enc.Hex), iterations } return obj } const decrypt = (passphrase,obj) => { const { ciphertext, iterations } = obj const salt = CryptoJS.enc.Hex.parse(obj.salt) const iv = CryptoJS.enc.Hex.parse(obj.iv) const key = CryptoJS.PBKDF2(passphrase, salt, { hasher: CryptoJS.algo.SHA512, keySize: 64/8, iterations}) const decrypted = CryptoJS.AES.decrypt(ciphertext, key, { iv }) return decrypted.toString(CryptoJS.enc.Utf8) } ``` ## Php This may not be compatible with the above This also generates a hash, and stores the iv and hash in the ciphertext. ```php function encrypt($plaintext, $password) { $method = "AES-256-CBC"; $key = hash('sha256', $password, true); $iv = openssl_random_pseudo_bytes(16); $ciphertext = openssl_encrypt($plaintext, $method, $key, OPENSSL_RAW_DATA, $iv); $hash = hash_hmac('sha256', $ciphertext . $iv, $key, true); return $iv . $hash . $ciphertext; } function decrypt($ivHashCiphertext, $password) { $method = "AES-256-CBC"; $iv = substr($ivHashCiphertext, 0, 16); $hash = substr($ivHashCiphertext, 16, 32); $ciphertext = substr($ivHashCiphertext, 48); $key = hash('sha256', $password, true); if (!hash_equals(hash_hmac('sha256', $ciphertext . $iv, $key, true), $hash)) return null; return openssl_decrypt($ciphertext, $method, $key, OPENSSL_RAW_DATA, $iv); } ``` ### Slightly less secure but slightly less data This is perhaps slightly less secure, for situations where you want some crypto, but it's not critical enough to warrant generating a cryptographically random iv and storing a hmac. ```php