mirror of
https://github.com/phpseclib/phpseclib.git
synced 2024-06-07 02:50:49 +00:00
AES: move GCM code to Rijndael
This commit is contained in:
parent
5abb16dc6d
commit
f98e0afc76
|
@ -49,8 +49,6 @@
|
|||
|
||||
namespace phpseclib\Crypt;
|
||||
|
||||
use phpseclib\Common\Functions\Strings;
|
||||
|
||||
/**
|
||||
* Pure-PHP implementation of AES.
|
||||
*
|
||||
|
@ -60,38 +58,6 @@ use phpseclib\Common\Functions\Strings;
|
|||
*/
|
||||
class AES extends Rijndael
|
||||
{
|
||||
/**
|
||||
* Test for engine validity
|
||||
*
|
||||
* This is mainly just a wrapper to set things up for \phpseclib\Crypt\Common\SymmetricKey::isValidEngine()
|
||||
*
|
||||
* @see \phpseclib\Crypt\Common\SymmetricKey::__construct()
|
||||
* @param int $engine
|
||||
* @access protected
|
||||
* @return bool
|
||||
*/
|
||||
protected function isValidEngineHelper($engine)
|
||||
{
|
||||
switch ($engine) {
|
||||
case self::ENGINE_LIBSODIUM:
|
||||
return function_exists('sodium_crypto_aead_aes256gcm_is_available') &&
|
||||
sodium_crypto_aead_aes256gcm_is_available() &&
|
||||
$this->mode == self::MODE_GCM &&
|
||||
$this->key_length == 32 &&
|
||||
$this->nonce && strlen($this->nonce) == 12;
|
||||
case self::ENGINE_OPENSSL_GCM:
|
||||
if (!extension_loaded('openssl')) {
|
||||
return false;
|
||||
}
|
||||
$methods = openssl_get_cipher_methods();
|
||||
return $this->mode == self::MODE_GCM &&
|
||||
version_compare(PHP_VERSION, '7.1.0', '>=') &&
|
||||
in_array('aes-' . $this->getKeyLength() . '-gcm', $methods);
|
||||
}
|
||||
|
||||
return parent::isValidEngineHelper($engine);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dummy function
|
||||
*
|
||||
|
@ -154,101 +120,4 @@ class AES extends Rijndael
|
|||
|
||||
parent::setKey($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts a message.
|
||||
*
|
||||
* @see self::decrypt()
|
||||
* @see parent::encrypt()
|
||||
* @access public
|
||||
* @param string $plaintext
|
||||
* @return string
|
||||
*/
|
||||
public function encrypt($plaintext)
|
||||
{
|
||||
switch ($this->engine) {
|
||||
case self::ENGINE_LIBSODIUM:
|
||||
$this->checkForChanges();
|
||||
$this->newtag = sodium_crypto_aead_aes256gcm_encrypt($plaintext, $this->aad, $this->nonce, $this->key);
|
||||
return Strings::shift($this->newtag, strlen($plaintext));
|
||||
case self::ENGINE_OPENSSL_GCM:
|
||||
$this->checkForChanges();
|
||||
return openssl_encrypt(
|
||||
$plaintext,
|
||||
'aes-' . $this->getKeyLength() . '-gcm',
|
||||
$this->key,
|
||||
OPENSSL_RAW_DATA,
|
||||
$this->nonce,
|
||||
$this->newtag,
|
||||
$this->aad
|
||||
);
|
||||
}
|
||||
|
||||
return parent::encrypt($plaintext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts a message.
|
||||
*
|
||||
* @see self::encrypt()
|
||||
* @see parent::decrypt()
|
||||
* @access public
|
||||
* @param string $ciphertext
|
||||
* @return string
|
||||
*/
|
||||
public function decrypt($ciphertext)
|
||||
{
|
||||
switch ($this->engine) {
|
||||
case self::ENGINE_LIBSODIUM:
|
||||
$this->checkForChanges();
|
||||
if ($this->oldtag === false) {
|
||||
throw new \UnexpectedValueException('Authentication Tag has not been set');
|
||||
}
|
||||
if (strlen($this->oldtag) != 16) {
|
||||
break;
|
||||
}
|
||||
$plaintext = sodium_crypto_aead_aes256gcm_decrypt($ciphertext . $this->oldtag, $this->aad, $this->nonce, $this->key);
|
||||
if ($plaintext === false) {
|
||||
$this->oldtag = false;
|
||||
throw new \UnexpectedValueException('Error decrypting ciphertext with libsodium');
|
||||
}
|
||||
return $plaintext;
|
||||
case self::ENGINE_OPENSSL_GCM:
|
||||
$this->checkForChanges();
|
||||
if ($this->oldtag === false) {
|
||||
throw new \UnexpectedValueException('Authentication Tag has not been set');
|
||||
}
|
||||
$plaintext = openssl_decrypt(
|
||||
$ciphertext,
|
||||
'aes-' . $this->getKeyLength() . '-gcm',
|
||||
$this->key,
|
||||
OPENSSL_RAW_DATA,
|
||||
$this->nonce,
|
||||
$this->oldtag,
|
||||
$this->aad
|
||||
);
|
||||
if ($plaintext === false) {
|
||||
$this->oldtag = false;
|
||||
throw new \UnexpectedValueException('Error decrypting ciphertext with OpenSSL');
|
||||
}
|
||||
return $plaintext;
|
||||
}
|
||||
|
||||
return parent::decrypt($ciphertext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check For Changes
|
||||
*
|
||||
* @see self::encrypt()
|
||||
* @see self::decrypt()
|
||||
* @access private
|
||||
*/
|
||||
private function checkForChanges()
|
||||
{
|
||||
if ($this->changed) {
|
||||
$this->setup();
|
||||
$this->changed = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1031,10 +1031,7 @@ abstract class SymmetricKey
|
|||
$plaintext = $this->pad($plaintext);
|
||||
}
|
||||
|
||||
if ($this->changed) {
|
||||
$this->setup();
|
||||
$this->changed = false;
|
||||
}
|
||||
$this->setup();
|
||||
|
||||
if ($this->mode == self::MODE_GCM) {
|
||||
$oldIV = $this->iv;
|
||||
|
@ -1369,10 +1366,7 @@ abstract class SymmetricKey
|
|||
throw new \LengthException('The ciphertext length (' . strlen($ciphertext) . ') needs to be a multiple of the block size (' . $this->block_size . ')');
|
||||
}
|
||||
|
||||
if ($this->changed) {
|
||||
$this->setup();
|
||||
$this->changed = false;
|
||||
}
|
||||
$this->setup();
|
||||
|
||||
if ($this->mode == self::MODE_GCM) {
|
||||
if ($this->oldtag === false) {
|
||||
|
@ -2252,6 +2246,12 @@ abstract class SymmetricKey
|
|||
*/
|
||||
protected function setup()
|
||||
{
|
||||
if (!$this->changed) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->changed = false;
|
||||
|
||||
$this->enbuffer = $this->debuffer = ['ciphertext' => '', 'xor' => '', 'pos' => 0, 'enmcrypt_init' => true];
|
||||
//$this->newtag = $this->oldtag = false;
|
||||
|
||||
|
|
|
@ -56,6 +56,8 @@ namespace phpseclib\Crypt;
|
|||
|
||||
use phpseclib\Crypt\Common\BlockCipher;
|
||||
|
||||
use phpseclib\Common\Functions\Strings;
|
||||
|
||||
/**
|
||||
* Pure-PHP implementation of Rijndael.
|
||||
*
|
||||
|
@ -279,6 +281,22 @@ class Rijndael extends BlockCipher
|
|||
protected function isValidEngineHelper($engine)
|
||||
{
|
||||
switch ($engine) {
|
||||
case self::ENGINE_LIBSODIUM:
|
||||
return function_exists('sodium_crypto_aead_aes256gcm_is_available') &&
|
||||
sodium_crypto_aead_aes256gcm_is_available() &&
|
||||
$this->mode == self::MODE_GCM &&
|
||||
$this->key_length == 32 &&
|
||||
$this->nonce && strlen($this->nonce) == 12 &&
|
||||
$this->block_size == 16;
|
||||
case self::ENGINE_OPENSSL_GCM:
|
||||
if (!extension_loaded('openssl')) {
|
||||
return false;
|
||||
}
|
||||
$methods = openssl_get_cipher_methods();
|
||||
return $this->mode == self::MODE_GCM &&
|
||||
version_compare(PHP_VERSION, '7.1.0', '>=') &&
|
||||
in_array('aes-' . $this->getKeyLength() . '-gcm', $methods) &&
|
||||
$this->block_size == 16;
|
||||
case self::ENGINE_OPENSSL:
|
||||
if ($this->block_size != 16) {
|
||||
return false;
|
||||
|
@ -913,4 +931,86 @@ class Rijndael extends BlockCipher
|
|||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts a message.
|
||||
*
|
||||
* @see self::decrypt()
|
||||
* @see parent::encrypt()
|
||||
* @access public
|
||||
* @param string $plaintext
|
||||
* @return string
|
||||
*/
|
||||
public function encrypt($plaintext)
|
||||
{
|
||||
$this->setup();
|
||||
|
||||
switch ($this->engine) {
|
||||
case self::ENGINE_LIBSODIUM:
|
||||
$this->newtag = sodium_crypto_aead_aes256gcm_encrypt($plaintext, $this->aad, $this->nonce, $this->key);
|
||||
return Strings::shift($this->newtag, strlen($plaintext));
|
||||
case self::ENGINE_OPENSSL_GCM:
|
||||
return openssl_encrypt(
|
||||
$plaintext,
|
||||
'aes-' . $this->getKeyLength() . '-gcm',
|
||||
$this->key,
|
||||
OPENSSL_RAW_DATA,
|
||||
$this->nonce,
|
||||
$this->newtag,
|
||||
$this->aad
|
||||
);
|
||||
}
|
||||
|
||||
return parent::encrypt($plaintext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts a message.
|
||||
*
|
||||
* @see self::encrypt()
|
||||
* @see parent::decrypt()
|
||||
* @access public
|
||||
* @param string $ciphertext
|
||||
* @return string
|
||||
*/
|
||||
public function decrypt($ciphertext)
|
||||
{
|
||||
$this->setup();
|
||||
|
||||
switch ($this->engine) {
|
||||
case self::ENGINE_LIBSODIUM:
|
||||
if ($this->oldtag === false) {
|
||||
throw new \UnexpectedValueException('Authentication Tag has not been set');
|
||||
}
|
||||
if (strlen($this->oldtag) != 16) {
|
||||
break;
|
||||
}
|
||||
$plaintext = sodium_crypto_aead_aes256gcm_decrypt($ciphertext . $this->oldtag, $this->aad, $this->nonce, $this->key);
|
||||
if ($plaintext === false) {
|
||||
$this->oldtag = false;
|
||||
throw new \UnexpectedValueException('Error decrypting ciphertext with libsodium');
|
||||
}
|
||||
return $plaintext;
|
||||
case self::ENGINE_OPENSSL_GCM:
|
||||
if ($this->oldtag === false) {
|
||||
throw new \UnexpectedValueException('Authentication Tag has not been set');
|
||||
}
|
||||
$plaintext = openssl_decrypt(
|
||||
$ciphertext,
|
||||
'aes-' . $this->getKeyLength() . '-gcm',
|
||||
$this->key,
|
||||
OPENSSL_RAW_DATA,
|
||||
$this->nonce,
|
||||
$this->oldtag,
|
||||
$this->aad
|
||||
);
|
||||
if ($plaintext === false) {
|
||||
$this->oldtag = false;
|
||||
throw new \UnexpectedValueException('Error decrypting ciphertext with OpenSSL');
|
||||
}
|
||||
return $plaintext;
|
||||
}
|
||||
|
||||
return parent::decrypt($ciphertext);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user