openssl_encrypt
openssl_encrypt($data, $cipher_algo, $passphrase, $options = 0, $iv = "", &$tag = null, $aad = "", $tag_length = 16)
Encrypts data with a chosen cipher and key. For new data aes-256-gcm is suitable: it encrypts and also adds an authentication tag, so decryption detects whether anyone has tampered with the data. Returns the encrypted data (in base64 without the OPENSSL_RAW_DATA option), or false on failure.
Parameters
- $data – the text to encrypt.
- $cipher_algo – the name of the cipher:
aes-256-gcm(recommended),aes-256-cbc,chacha20-poly1305… - $passphrase – the key: random bytes of the right length (32 bytes for AES-256), not a password.
- $options –
OPENSSL_RAW_DATA= return binary data instead of base64. - $iv – the initialization vector: a new random one for each encryption,
openssl_cipher_iv_length()returns its length. - &$tag – with GCM the function writes the authentication tag here (needed for decryption); $aad – data that is verified but not encrypted.
Examples
// the key: 32 random bytes, stored outside the database (in .env or the configuration)
$key = random_bytes(32);
$iv = random_bytes(openssl_cipher_iv_length("aes-256-gcm"));
$encrypted = openssl_encrypt("Passport no. 123456789", "aes-256-gcm", $key, OPENSSL_RAW_DATA, $iv, $tag);
echo strlen($iv) . " " . strlen($tag); // 12 16
// store the IV, the tag and the ciphertext in the database (neither the IV nor the tag is secret)
$stored = base64_encode($iv . $tag . $encrypted);
// decryption
$data = base64_decode($stored);
echo openssl_decrypt(substr($data, 28), "aes-256-gcm", $key, OPENSSL_RAW_DATA, substr($data, 0, 12), substr($data, 12, 16)); // Passport no. 123456789
Things to watch out for
- Never use the same IV with the same key twice with GCM – it reveals the contents of both messages. Always take the IV from
random_bytes(). - Do not use a password directly as the key. A key is derived from a password with
hash_pbkdf2()orsodium_crypto_pwhash()with a random salt. - The
aes-256-cbcmode has no authentication – without your own HMAC an attacker can modify the ciphertext. Do not use the ECB mode (aes-256-ecb) on real data. - User passwords are not encrypted but hashed (
password_hash()) – encryption is for data that needs to be read back.
Related functions:
openssl_decrypt()
openssl_cipher_iv_length()
random_bytes()
sodium_crypto_secretbox()
hash_pbkdf2()
base64_encode()