tags: #crypto #python #php #javascript #recipes
Sometimes I have cause to encrypt with Python, and decrypt with PHP, or encrypt with PHP and decrypt with [CryptoJS](/crypto/js/CryptoJS). Here we give simple examples of how to make this work, as there are subtle differences in how things are done in each language.
## 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