221 lines
4.6 KiB
PHP
221 lines
4.6 KiB
PHP
<?php
|
|
/* Icinga Web 2 | (c) 2021 Icinga GmbH | GPLv2+ */
|
|
|
|
namespace Icinga\Crypt;
|
|
|
|
use UnexpectedValueException;
|
|
use RuntimeException;
|
|
|
|
/**
|
|
* Data encryption and decryption using symmetric algorithm
|
|
*
|
|
* # Example Usage
|
|
*
|
|
* ```php
|
|
*
|
|
* // Encryption
|
|
* $encryptedData = new AesCrypt()->encrypt($data); // Accepts a string
|
|
*
|
|
*
|
|
* // Encrypt and encode to Base64
|
|
* $encryptedData = (new AesCrypt())->encryptToBase64($data); // Accepts a string
|
|
*
|
|
*
|
|
* // Decryption
|
|
* $aesCrypt = (new AesCrypt())
|
|
* ->setTag($tag)
|
|
* ->setIV($iv)
|
|
* ->setKey($key);
|
|
*
|
|
* $decryptedData = $aesCrypt->decrypt($data);
|
|
*
|
|
* // Decode from Base64 and decrypt
|
|
* $aesCrypt = (new AesCrypt())
|
|
* ->setTag($tag)
|
|
* ->setIV($iv)
|
|
* ->setKey($key);
|
|
*
|
|
* $decryptedData = $aesCrypt->->decryptFromBase64($data);
|
|
* ```
|
|
*
|
|
*/
|
|
class AesCrypt
|
|
{
|
|
/** @var string The encryption key */
|
|
private $key;
|
|
|
|
/** @var string The initialization vector which is not NULL */
|
|
private $iv;
|
|
|
|
/** @var string The authentication tag which is passed by reference when using AEAD cipher mode */
|
|
private $tag;
|
|
|
|
/** @var string The cipher method */
|
|
private $method = 'aes-128-gcm';
|
|
|
|
public function __construct($random_bytes_len = 128)
|
|
{
|
|
$len = openssl_cipher_iv_length($this->method);
|
|
$this->iv = random_bytes($len);
|
|
$this->key = random_bytes($random_bytes_len);
|
|
}
|
|
|
|
/**
|
|
* Set the key
|
|
*
|
|
* @return $this
|
|
*/
|
|
public function setKey($key)
|
|
{
|
|
$this->key = $key;
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Get the key
|
|
*
|
|
* @return string
|
|
*
|
|
* @throws RuntimeException If the key is not set
|
|
*/
|
|
public function getKey()
|
|
{
|
|
if (empty($this->key)) {
|
|
throw new RuntimeException('No key set');
|
|
}
|
|
|
|
return $this->key;
|
|
}
|
|
|
|
/**
|
|
* Set the IV
|
|
*
|
|
* @return $this
|
|
*/
|
|
public function setIV($iv)
|
|
{
|
|
$this->iv = $iv;
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Get the IV
|
|
*
|
|
* @return string
|
|
*
|
|
* @throws RuntimeException If the IV is not set
|
|
*/
|
|
public function getIV()
|
|
{
|
|
if (empty($this->iv)) {
|
|
throw new RuntimeException('No iv set');
|
|
}
|
|
|
|
return $this->iv;
|
|
}
|
|
|
|
/**
|
|
* Set the Tag
|
|
*
|
|
* @return $this
|
|
*/
|
|
public function setTag($tag)
|
|
{
|
|
if (strlen($tag) !== 16) {
|
|
throw new UnexpectedValueException(sprintf(
|
|
'expects tag length to be 16, got instead %s',
|
|
strlen($tag)
|
|
));
|
|
}
|
|
|
|
$this->tag = $tag;
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Get the Tag
|
|
*
|
|
* @return string
|
|
*
|
|
* @throws RuntimeException If the Tag is not set
|
|
*/
|
|
public function getTag()
|
|
{
|
|
if (empty($this->tag)) {
|
|
throw new RuntimeException('No tag set');
|
|
}
|
|
|
|
return $this->tag;
|
|
}
|
|
|
|
/**
|
|
* Decrypt the given data using the key, iv and tag
|
|
*
|
|
* @param string $data
|
|
*
|
|
* @return string
|
|
*
|
|
* @throws RuntimeException If decryption fails
|
|
*/
|
|
public function decrypt($data)
|
|
{
|
|
$decrypt = openssl_decrypt($data, $this->method, $this->getKey(), 0, $this->getIV(), $this->getTag());
|
|
if (is_bool($decrypt) && $decrypt === false) {
|
|
throw new RuntimeException('Decryption failed');
|
|
}
|
|
|
|
return $decrypt;
|
|
}
|
|
|
|
/**
|
|
* Decode from Base64 and decrypt the given data using the key, iv and tag
|
|
*
|
|
* @param string $data
|
|
*
|
|
* @return string decrypted data
|
|
*
|
|
* @throws RuntimeException If decryption fails
|
|
*/
|
|
public function decryptFromBase64($data)
|
|
{
|
|
return $this->decrypt(base64_decode($data));
|
|
}
|
|
|
|
/**
|
|
* Encrypt the given data using the key, iv and tag
|
|
*
|
|
* @param string $data
|
|
*
|
|
* @return string encrypted data
|
|
*
|
|
* @throws RuntimeException If decryption fails
|
|
*/
|
|
public function encrypt($data)
|
|
{
|
|
$encrypt = openssl_encrypt($data, $this->method, $this->getkey(), 0, $this->getIV(), $this->tag);
|
|
|
|
if (is_bool($encrypt) && $encrypt === false) {
|
|
throw new RuntimeException('Encryption failed');
|
|
}
|
|
|
|
return $encrypt;
|
|
}
|
|
|
|
/**
|
|
* Encrypt the given string using the the key, iv, tag and encode to Base64
|
|
*
|
|
* @param string $data
|
|
*
|
|
* @return string encrypted and encoded to Base64 data
|
|
*
|
|
* @throws RuntimeException If encryption fails
|
|
*/
|
|
public function encryptToBase64($data)
|
|
{
|
|
return base64_encode($this->encrypt($data));
|
|
}
|
|
}
|